CRM Integration: Add a custom field to the existing CRM table

by Jul 18, 2023CRM Integration

Home 9 Development 9 CRM Integration 9 CRM Integration: Add a custom field to the existing CRM table

In the past weeks, I got a few questions about Microsoft Dynamics 365 Sales and Business Central Integration. I did some integration projects in past, but I also have experience with a heavily customized solution from this year. As a lot of questions were about how to extend the integration (and I agree that it’s not super well documented), I have decided to write a few posts about the integration customization.

I’m not yet decided about the number of posts or topics, so if you know an interesting topic you want to hear about, let me know at kapitan@kepty.cz. For now, I have content for 5-8 posts that I want to write in the next two months.

See all related articles here: CRM Integration | MSDyn365 Business Central – Tomas Kapitan (kepty.cz)


Let’s start with the basic example – our task is to integrate a new text field. This is just a text field with no relation or additional functionality, for example, the “Registration No.” field in the Customer and Vendor table. The source codes for this example could be found here: AL-Example-CRMIntegration/AddFieldToExistingTable-Basic at main · TKapitan/AL-Example-CRMIntegration (github.com)

As you probably know, there is only one table in CRM for both Customers and Vendors, called Account. This table is integrated out-of-the-box and exists in Business Central as the “CRM Account” table.

To add a new field, create a new table extension object, create a new field in this table extension and specify ExternalName and ExternalType fields. These fields specify the Schema Name and Data Type of the field in the Dataverse table (where you need to create the field first). For our example, I have created a field with the schema name “tka_registrationnumber“.

tableextension 50000 "TKA CRM Account" extends "CRM Account"
{
    fields
    {
        field(50000; TKA_RegistrationNumber; Text[50])
        {
            ExternalName = 'tka_registrationnumber';
            ExternalType = 'String';
            Description = '';
            Caption = 'Registration No.';
            DataClassification = CustomerContent;
        }
    }
}

To be able to see values in our new field in Dataverse directly in Business Central, we can extend the OOTB page “CRM Account List” using a page extension just like any standard page in Business Central.

pageextension 50000 "TKA CRM Account List" extends "CRM Account List"
{
    layout
    {
        addbefore(Coupled)
        {
            field(TKA_RegistrationNumber; Rec.TKA_RegistrationNumber)
            {
                ToolTip = 'Specifies data from a corresponding field in a Dataverse entity. For more information about Dataverse, see Dataverse Help Center.';
                ApplicationArea = All;
            }
        }
    }
}

Until now, we did nothing special (except defining ExternalName/ExternalType for our newly added field). Now we need to add our newly added field to CRM field mapping.

CRM Integration Mapping is defined in two different codeunits – “CDS Setup Defaults” and “CRM Setup Defaults“. What’s the difference? CDS is an old name for Dataverse. “CRM Setup Defaults” should contain only definitions for CRM-specific tables; on the other hand, “CDS Setup Defaults” contains more generic tables that are useful not only for CRM.

The “Account” table is located in “CDS Setup Defaults“; To extend integration mapping for this table, you need to subscribe to events “OnAfterResetCustomerAccountMapping” and “OnAfterResetVendorAccountMapping” in “CDS Setup Default“; see the example below.

To add a new field to mapping, use the CreateRecord(…) procedure from the “Integration Field Mapping” table. This procedure accepts

  • IntegrationTableMappingName, the name of table mapping, just pass the IntegrationTableMappingName variable.
  • TableFieldNo, Field Number from Business Central table (in our example, “Registration Number” from the Customer and Vendor tables)
  • IntegrationTableFieldNo, Field Number from CRM Integration table (“CRM Account”, our newly added field)
  • SynchDirection: Option, the default direction for synchronization (could be changed in a setup later), the field can be synchronized from CRM to BC, from BC to CRM or bidirectional.
  • ConstValue, you can pass a constant value; we are passing empty text in our example.
  • ValidateField, specifies if you want to validate the field in Business Central (when a new value is passed from CRM to BC); the best practice is always to validate the field, except if there are some logic issues or the value needs some additional processing later in the synchronization process.
  • ValidateIntegrationTableField, specifies if you want to validate the field in CRM (when a new value is passed from BC to CRM); this is usually false.
codeunit 50000 "TKA CRM Setup Defaults"
{
    SingleInstance = true;

    var
        IntegrationFieldMapping: Record "Integration Field Mapping";

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"CDS Setup Defaults", OnAfterResetCustomerAccountMapping, '', false, false)]
    local procedure OnAfterResetCustomerAccountMappingCDSSetupDefaults(IntegrationTableMappingName: Code[20])
    var
        Customer: Record Customer;
        CRMAccount: Record "CRM Account";
    begin
        IntegrationFieldMapping.CreateRecord(
            IntegrationTableMappingName, Customer.FieldNo("Registration Number"), CRMAccount.FieldNo(TKA_RegistrationNumber),
            IntegrationFieldMapping.Direction::Bidirectional, '', true, false
        );
    end;

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"CDS Setup Defaults", OnAfterResetVendorAccountMapping, '', false, false)]
    local procedure OnAfterResetVendorAccountMappingCDSSetupDefaults(IntegrationTableMappingName: Code[20])
    var
        Vendor: Record Vendor;
        CRMAccount: Record "CRM Account";
    begin
        IntegrationFieldMapping.CreateRecord(
            IntegrationTableMappingName, Vendor.FieldNo("Registration Number"), CRMAccount.FieldNo(TKA_RegistrationNumber),
            IntegrationFieldMapping.Direction::Bidirectional, '', true, false
        );
    end;
}

And that’s all! It’s really simple, isn’t it? In the next part, we will look at a bit more complicated field to add to synchronization.

Recent Articles from the category

Sign Up for News

Certifications

Highest certification
Microsoft Data Management and
also in D365 Business Central

Microsoft Certified: Dynamics 365 Business Central Functional Consultant Associate

See other certifications here