F&O Customer Integration Through CDS (Common Data Service) for Apps

F&O Customer Integration Through CDS (Common Data Service) for Apps

In one of the implementation projects recently, we used the F&O customer integration through CDS capabilities, available as a feature in the Common Data Service (CDS). Data Integration projects or data integrator (for administrators) is a framework ( available as part of the Common Data Service data integration) that is used to facilitate the integration of data between Dynamics 365 for Finance and Operations (FinOps) and Dynamics 365 for Sales.

F&O Customer Integration Through CDS

Through Power Query or M based queries, there can be other sources of data, too, that can be connected to for data integration. In this case, we are mapping accounts in Sales with customers in FinOps.

Setup Data Integration projects:

The prerequisite to setup Data Integration projects is to first set up the connection sets. Connection sets are the framework through which various sources of data can be connected to. For example, in the connection set below, we have set up a connection set that will facilitate integration of data between accounts in Dynamics 365 for Sales and customers in Finance and Operations. Ensure that the connection sets point to the right legal entities.                                                                                           Fig 1 – Connection Sets

After setting up the connection sets, set up the data integration projects and ensure that the mapping is set up properly. Also, ensure the field mapping setup properly once the data integration is set up accurately.

Scenario:

The scenario is to map accounts in Sales to customers in FinOps. In addition to this, the addresses and contact details of these accounts in Sales are mapped with the primary address or the primary contact type in FinOps. The other requirement is to have the ability to create non-primary addresses and non-primary contacts in FinOps. Data integration projects leverage the Data Management capabilities of FinOps to manage data integration. This also means that various data entities from the data management framework are triggered in FinOps. In this case for customers the data integration entity that is triggered is CustCustomerV3Entity.

Note:The integration entity in CDS that is used for Customers is CustCustomerV2Entity. One needs to delete the CustCustomerV2Entity under Data Management -> Data Entities. The Data Entity CustCustomerV2Entity needs to be deleted first and explicitly add CustCustomerV3Entity (as on Platform Update 8.0/Platform Update 8.1/Platform Update 8.1.1).

LogisticsPostalAddress Code:

Override the post-event handler to edit non-primary addresses after the address is created. In case of LogisticsPostalAddress, following is the X++ Code to edit the details in the grid control.

[PostHandlerFor(formStr(LogisticsPostalAddress), formMethodStr(LogisticsPostalAddress, updateControls))]
public static void LogisticsPostalAddress_Post_updateControls(XppPrePostArgs args)
{
FormRun sender = args.getThis();

//Retrieve the two form data sources used in LogisticsPostalAddress form
FormDataSource logisticsPostalAddress_ds, logisticsLocation_ds;
FormDataObject IsPrimaryDet;
LogisticsPostalAddress logisticsPostalAddress;
DirPartyLocationRole dirPartyLocationRole;

LogisticsLocation logisticsLocation;
DirPartyLocation dirPartyLocation;
CustTable custTable;

logisticsPostalAddress_ds = sender.dataSource("LogisticsPostalAddress");
logisticsLocation_ds = sender.dataSource("LogisticsLocation");

//LogisticsPostalAddress and logisticsLocation details retrieved
logisticsPostalAddress = logisticsPostalAddress_ds.cursor();
logisticsLocation = logisticsLocation_ds.cursor();

//Retrieve the location details
select firstonly dirPartyLocation
where dirPartyLocation.Location == logisticsLocation.RecId;

if(dirPartyLocation)
{
//Retrieve the customer details from the address grid
custTable = CustTable::findByPartyRecId(dirPartyLocation.Party);

//Check if the customer record is externally maintained
if(custTable && custTable.IsExternallyMaintained)
{
//Validate if the address is non-primary
if(!dirPartyLocation.IsPrimary)
{
//Edit the Postal Address details like City, State, Zip Code
logisticsPostalAddress_ds.allowEdit(true);
//Edit the name or description details in the Address
logisticsLocation_ds.allowEdit(true);

//Enable the purpose group
sender.control(sender.controlId(formControlStr(LogisticsPostalAddress,PurposeGroup))).enabled(true);
//IsPrimary toggle control disabled for non-Primary addresses
sender.control(sender.controlId(formControlStr(LogisticsPostalAddress,IsPrimary))).enabled(false);
}

}

}

}

LogisticsElectronicAddress Code:

[FormDataSourceEventHandler(formDataSourceStr(LogisticsContactInfoGrid, LogisticsElectronicAddress), FormDataSourceEventType::SelectionChanged)]
public static void LogisticsElectronicAddress_OnSelectionChanged(FormDataSource sender, FormDataSourceEventArgs e)
{
LogisticsElectronicAddress LogisticsElectronicAddress;
LogisticsLocation logisticsLocation;
DirPartyLocation dirPartyLocation;
CustTable custTable;
FormRun element;
FormControl advancedButton, deleteContactInfoButton;

// Retrieve the form buttons
element = sender.formRun();
advancedButton = element.design(0).controlName("DetailContactInfo");
deleteContactInfoButton = element.design(0).controlName("DeleteContactInfo") ;

// Retrieve the datasource fields objects
FormDataSource LogisticsElectronicAddress_ds = sender.formRun().dataSource("LogisticsElectronicAddress");
FormDataObject typeObject = LogisticsElectronicAddress_ds.object(fieldNum(LogisticsElectronicAddress, Type));
FormDataObject LocatorObject = LogisticsElectronicAddress_ds.object(fieldNum(LogisticsElectronicAddress, Locator));
FormDataObject LocatorExtensionObject = LogisticsElectronicAddress_ds.object(fieldNum(LogisticsElectronicAddress, LocatorExtension));
FormDataObject DescriptionObject = LogisticsElectronicAddress_ds.object(fieldNum(LogisticsElectronicAddress, Description));
FormDataObject CountryRegionCodeObject = LogisticsElectronicAddress_ds.object(fieldNum(LogisticsElectronicAddress, CountryRegionCode));
FormDataObject IsPrimaryObject = LogisticsElectronicAddress_ds.object(fieldNum(LogisticsElectronicAddress, IsPrimary));

// Retrieve customer record from the LogisticsElectronicAddress grid record
LogisticsElectronicAddress = LogisticsElectronicAddress_ds.cursor();
logisticsLocation = LogisticsLocation::find(LogisticsElectronicAddress.Location);
select firstonly dirPartyLocation where DirPartyLocation.Location == LogisticsLocation.RecId;

if (dirPartyLocation)
{
custTable = CustTable::findByPartyRecId(dirPartyLocation.Party);

// If the customer is externally maintained
if (CustTable && CustTable.IsExternallyMaintained)
{

// if contact information is not primary, make the fields in the grid editable
typeObject.allowEdit(!LogisticsElectronicAddress.IsPrimary);
LocatorObject.allowEdit(!LogisticsElectronicAddress.IsPrimary);
LocatorExtensionObject.allowEdit(!LogisticsElectronicAddress.IsPrimary);
DescriptionObject.allowEdit(!LogisticsElectronicAddress.IsPrimary);
CountryRegionCodeObject.allowEdit(!LogisticsElectronicAddress.IsPrimary);
//IsPrimaryObject.allowEdit(!LogisticsElectronicAddress.IsPrimary);

// if contact information is primary
// disable the advanced button so users cannot edit details in that screen
advancedButton.enabled(!LogisticsElectronicAddress.IsPrimary);

// disable the delete button
deleteContactInfoButton.enabled(!LogisticsElectronicAddress.IsPrimary);
}
}
}

Configuration Keys:

LedgerBasic is the configuration key that’s required for CustCustomerV3Entity to be enabled. This is enabled (by default) in Dynamics 365 for Finance and Operations.

GitHub link:

The code repository is uploaded on github and following is the link to the Visual Studio Project.
Note:

The project resides on the var layer.
https://github.com/nav21n/d365finops/tree/master/samples

References:

https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/data-entities/data-integration-cds

Disclaimer: The Questions and Answers provided on https://www.gigxp.com are for general information purposes only. We make no representations or warranties of any kind, express or implied, about the completeness, accuracy, reliability, suitability or availability with respect to the website or the information, products, services, or related graphics contained on the website for any purpose.
Avatar

Navneeth Nagrajan is a Technical Consultant at Avanade Australia focusing on implementation, pre-sales and support of Microsoft Dynamics 365 for Operations/ Microsoft Dynamics Ax ERP. Before Avanade, Navneeth worked as a Solutions Consultant at LM WindPower focusing on implementation and support of Microsoft Dynamics Ax Enterprise Resource Planning solution. Prior to LM WindPower, he worked as a Lead Consultant for ITC Infotech India Limited focusing on Enterprise Solutions like Microsoft Dynamics AX & Microsoft Dynamics CRM. He has worked for Microsoft as a Partner Technical Consultant. His primary focus area is Microsoft Dynamics AX and he specializes on Trade & Logistics, CRM, Service Management and Project Management functionalities. His secondary focus area is Microsoft Dynamics CRM and he specializes on Sales Management, Marketing Management and Service Management sections. He has successfully assisted more than 100 Microsoft partners and customers. At Microsoft, He has successfully written and published papers on '​'​ Needs for Microsoft Dynamics CRM in the Education Sector''. Prior to Microsoft, he has worked as a Functional Consultant and has implemented Microsoft Dynamics AX in the Manufacturing and Services Segment. He has also worked as a Business Development Executive implementing Document Management Systems for Security Broking and Manufacturing Organizations.