Issue with syncing of Business Central "Sales Invoice Line" table to Dataverse.
Hello Team.
I hope this article will be useful for some developers who will try to sync "Sales Invoice Line" table to Dataverse separately.
I created replication for many Business Central tables to Dataverse using steps described here:
But with "Sales Invoice Line" - I failed first time. I created standard set of objects, created "Integration Table mappings" and so on. And after I ran "Full synchronization" - I got next error on my job:
"Cannot synchronize invoice lines separately."
It's quite hard to debug job sync especially on Production environment, so I started to check Dataverse replication objects because error looked like some Label type variable. I extracted from Base Application all objects with name started with "CRM":
And in the codeunit 5341 "CRM Int. Table. Subscriber" I found what I wanted:
This Error label used in only event subscriber:
[EventSubscriber(ObjectType::Codeunit, Codeunit::"CRM Integration Table Synch.", 'OnQueryPostFilterIgnoreRecord', '', false, false)] procedure OnQueryPostFilterIgnoreRecord(SourceRecordRef: RecordRef; var IgnoreRecord: Boolean) begin if IgnoreRecord then exit; case SourceRecordRef.Number() of DATABASE::Contact: HandleContactQueryPostFilterIgnoreRecord(SourceRecordRef, IgnoreRecord); DATABASE::Opportunity: HandleOpportunityQueryPostFilterIgnoreRecord(SourceRecordRef, IgnoreRecord); DATABASE::"Sales Invoice Line": Error(CannotSynchOnlyLinesErr); DATABASE::Item: HandleItemQueryPostFilterIgnoreRecord(SourceRecordRef, IgnoreRecord); DATABASE::Resource: HandleResourceQueryPostFilterIgnoreRecord(SourceRecordRef, IgnoreRecord); end; end;
So "Sales Invoice Line" the only table you can't sync. You'll get the error each time you run the sync process. I think because it's a part of D365 Sales integration. But we don't use it and I need this table in Dataverse.
I can't change standard code and must resolve this issue using extensions only.
Event placed in codeunit 5340 "CRM Integration Table Synch.":
procedure SyncNAVRecordToCRM(var SourceRecordRef: RecordRef; IntegrationTableMapping: Record "Integration Table Mapping"; var IntegrationTableSynch: Codeunit "Integration Table Synch."; var TempCRMIntegrationRecord: Record "CRM Integration Record" temporary; var LatestLocalModifiedOn: DateTime) var DestinationRecordRef: RecordRef; SystemIdFieldRef: FieldRef; IgnoreRecord: Boolean; ForceModify: Boolean; LocalModifiedOn: DateTime; begin ForceModify := IntegrationTableMapping."Delete After Synchronization"; IgnoreRecord := false; OnQueryPostFilterIgnoreRecord(SourceRecordRef, IgnoreRecord); if not IgnoreRecord then begin SystemIdFieldRef := SourceRecordRef.Field(SourceRecordRef.SystemIdNo); if not TempCRMIntegrationRecord.IsIntegrationIdCoupled(SystemIdFieldRef.Value()) then IgnoreRecord := IntegrationTableMapping."Synch. Only Coupled Records"; if not IgnoreRecord then IntegrationTableSynch.Synchronize(SourceRecordRef, DestinationRecordRef, ForceModify, false); end; // collect latest modified time across all local records including not synched LocalModifiedOn := IntegrationTableSynch.GetRowLastModifiedOn(IntegrationTableMapping, SourceRecordRef); if LocalModifiedOn > LatestLocalModifiedOn then LatestLocalModifiedOn := LocalModifiedOn; end;
We could see that we can skip this event if send IgnoreRecord = true, but this way we skip record sync totally (checked).
As I use SaaS and "Sales Invoice Line" is not a big table - I created a clone of this table using this event:
[EventSubscriber(ObjectType::Table, Database::"Sales Invoice Line", 'OnAfterInsertEvent', '', false, false)] local procedure InsertCloneLine(var Rec: Record "Sales Invoice Line"; RunTrigger: Boolean) var SalesInvoiceLineClone: Record "AWR_Sales Invoice Line clone"; begin If Rec.IsTemporary then exit; SalesInvoiceLineClone.Init(); SalesInvoiceLineClone.TransferFields(Rec, true); if SalesInvoiceLineClone.Insert() then; end;
So the Idea is next:
1. After sales invoice post - lines automatically creates in my clone table
2. Job queue then sync this clone table into Dataverse as usual.
Now this schema works like a charm and shows that we can find a way when it seems like you can't do something with extensions.
Hope that it'll be useful for somebody!
Comments
-
Hello Andrey during Sales Invoice sync so only Header level data sync not line level and gave error like that "The Sales Invoice Line record cannot be updated because it is coupled to a deleted record." Any suggestion or hint for that so please tell me. Thanks Janak Dangar.
*This post is locked for comments