Streamlining CRM and Business Central Integration: Syncing Account IDs to the Customer Table

Imagine you’re managing customer relationships in Dynamics 365 CRM and handling financials or operations in Business Central. Each system has its own way of identifying customers—CRM uses an Account ID, while Business Central assigns a Customer No. During synchronization, you want the CRM Account ID to update the BC Customer table automatically, ensuring both systems stay aligned. This is especially useful when creating or updating customer records, as it eliminates manual entry errors and keeps your data in sync.

The solution revolves around a custom process that handles field mapping during synchronization. Here’s a breakdown of how it achieves this
  • Identifying the Source and Destination
    The process starts by checking where the data is coming from (CRM) and where it’s going (Business Central). When the source is a CRM account, the system retrieves the relevant account details, like its unique Account ID, and prepares to map it to Business Central’s Customer table.
  • Validation Before Syncing
    Before any updates happen, the system ensures the CRM account is ready to sync. For example, it might check a flag indicating whether synchronization is approved. If the account isn’t ready or doesn’t qualify as a customer, the process stops—no unnecessary updates, no clutter.
  • Updating Business Central
    Once validated, the CRM Account ID is linked to the corresponding customer record in Business Central. The customer’s record is updated with the CRM identifier, creating a direct connection between the two systems. This step ensures that anyone working in Business Central can trace a customer back to their CRM account effortlessly.
  • Updating CRM in Return
    The process isn’t one-sided. After linking the Account ID to the Customer table, it updates the CRM account with the Business Central Customer No. and sets a status to confirm the sync is complete. It also logs the date of the update and clears any previous error messages, keeping the integration clean and trackable.
  • Error-Free and Efficient
    The beauty of this approach is its efficiency. It only pulls in additional data (like vendor or customer tables) when absolutely necessary, reducing overhead. Plus, it handles updates on both ends—CRM and Business Central—ensuring consistency without manual intervention.

A Real-World Example

Let’s say a sales rep creates a new account in CRM for “Acme Corp” with an Account ID of “ACC-12345.” The integration kicks in, checks that Acme Corp is ready to sync, and updates the Business Central Customer table with “ACC-12345” tied to customer number “CUST001.” Meanwhile, CRM gets updated with “CUST001” and a “Synced” status. Now, whether you’re in CRM or Business Central, you’ve got a unified view of Acme Corp—ready for sales, billing, or support.
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Integration Rec. Synch. Invoke", 'OnAfterInsertRecord', '', true, true)]
    local procedure CRMSyncOnAfterInsertRecord(IntegrationTableMapping: Record "Integration Table Mapping"; SourceRecordRef: RecordRef; var DestinationRecordRef: RecordRef)
    var
        CDSIntegrationMgt: Codeunit "CDS Integration Mgt.";
    begin
        case DestinationRecordRef.Number() of
            Database::"CRM Account":
                CustomerFieldHandling(SourceRecordRef, DestinationRecordRef);
        end;
    end;
local procedure CustomerFieldHandling(Source: RecordRef; var Dest: RecordRef)
    var
        CustomCrmAccount: Record "CDS Account";
        CrmAccount: Record "CRM Account";
        Customer: Record Customer;
        Vendor: Record Vendor;
    begin
        case Source.Number() of
            Database::"CRM Account":
                begin
                    Source.SetTable(CrmAccount);
                    if not CustomCrmAccount.Get(CrmAccount.AccountId) then
                        exit;

                    if not CustomCrmAccount.nxn_ReadyToSync then
                        exit;

                    if CustomCrmAccount.nxn_IsCustomer then begin
                        Dest.SetTable(Customer);
                        UpdateCrmAccount(CustomCrmAccount, Customer."No.");
                    end;

                    // Only get tables if needed
                    Dest.GetTable(Customer);
                    Dest.GetTable(Vendor);
                end;
        end;
        case Dest.Number() of
            Database::"CRM Account":
                begin
                    Dest.SetTable(CrmAccount);
                    if Customer.Get(CrmAccount.nxn_BC) then begin
                        Customer."NXO CDS Account ID" := CrmAccount.AccountId;
                        Customer.Modify();
                        UpdateCrmAccountBasic(CrmAccount);
                    end;
                end;
        end;
    end;

    local procedure UpdateCrmAccount(var CustomCrmAccount: Record "CDS Account"; CustomerNo: Code[20])
    begin
        CustomCrmAccount.nxn_BC := CustomerNo;
        CustomCrmAccount.nxn_IntegrationUpdateDate := Today;
        CustomCrmAccount.nxn_SyncStatus := CustomCrmAccount.nxn_SyncStatus::BCSynced;
        CustomCrmAccount.nxn_ReadyToSync := true;
        CustomCrmAccount.nxn_IntegrationErrorDetails := '';
        CustomCrmAccount.Modify();
    end;

    local procedure UpdateCrmAccountBasic(var CrmAccount: Record "CRM Account")
    begin
        CrmAccount.nxn_IntegrationUpdateDate := Today;
        CrmAccount.nxn_SyncStatus := CrmAccount.nxn_SyncStatus::BCSynced;
        CrmAccount.nxn_IntegrationErrorDetails := '';
        CrmAccount.Modify();
    end;

 

Thank you for reading this post, don't forget to subscribe!