Category: VS Code
Create Actions on the Page for managing Coupling and Synchronization
This is the Eighth post in the series. If you want to go to previous post click here.
From the series of steps this post is dedicated to Step-7:
As a Seventh Step we will Create Actions on the Page for managing Coupling and Synchronization created in previous post.
On page 50120 Prospects created in previous post
Add Variables:
var
CRMIntegrationManagement: Codeunit "CRM Integration Management";
CRMCouplingManagement: Codeunit "CRM Coupling Management";
CDSIntegrationEnabled: Boolean;
CDSIsCoupledToRecord: Boolean;
Add Triggers:
trigger OnOpenPage()
begin
CDSIntegrationEnabled := CRMIntegrationManagement.IsCDSIntegrationEnabled();
end;
trigger OnAfterGetCurrRecord()
begin
if CDSIntegrationEnabled then
CDSIsCoupledToRecord := CRMCouplingManagement.IsRecordCoupledToCRM(Rec.RecordId);
end;
Add Actions:
Actions
{
area(Processing)
{
group(ActionGroupCDS)
{
Caption = 'Dataverse';
Visible = CDSIntegrationEnabled;
action(CDSGotoProspect)
{
Caption = 'Prospect';
Image = CoupledCustomer;
ToolTip = 'Open the coupled Dataverse Prospect.';
ApplicationArea = All;
trigger OnAction()
var
CRMIntegrationManagement: Codeunit "CRM Integration Management";
begin
CRMIntegrationManagement.ShowCRMEntityFromRecordID(Rec.RecordId);
end;
}
action(CDSSynchronizeNow)
{
Caption = 'Synchronize';
ApplicationArea = All;
Visible = true;
Image = Refresh;
Enabled = CDSIsCoupledToRecord;
ToolTip = 'Send or get updated data to or from Microsoft Dataverse.';
trigger OnAction()
var
CRMIntegrationManagement: Codeunit "CRM Integration Management";
begin
CRMIntegrationManagement.UpdateOneNow(Rec.RecordId);
end;
}
action(ShowLog)
{
Caption = 'Synchronization Log';
ApplicationArea = All;
Visible = true;
Image = Log;
ToolTip = 'View integration synchronization jobs for the Prospect table.';
trigger OnAction()
var
CRMIntegrationManagement: Codeunit "CRM Integration Management";
begin
CRMIntegrationManagement.ShowLog(Rec.RecordId);
end;
}
group(Coupling)
{
Caption = 'Coupling';
Image = LinkAccount;
ToolTip = 'Create, change, or delete a coupling between the Business Central record and a Microsoft Dataverse row.';
action(ManageCDSCoupling)
{
Caption = 'Set Up Coupling';
ApplicationArea = All;
Visible = true;
Image = LinkAccount;
ToolTip = 'Create or modify the coupling to a Microsoft Dataverse Prospect.';
trigger OnAction()
var
CRMIntegrationManagement: Codeunit "CRM Integration Management";
begin
CRMIntegrationManagement.DefineCoupling(Rec.RecordId);
end;
}
action(DeleteCDSCoupling)
{
Caption = 'Delete Coupling';
ApplicationArea = All;
Visible = true;
Image = UnLinkAccount;
Enabled = CDSIsCoupledToRecord;
ToolTip = 'Delete the coupling to a Microsoft Dataverse Prospect.';
trigger OnAction()
var
CRMCouplingManagement: Codeunit "CRM Coupling Management";
begin
CRMCouplingManagement.RemoveCoupling(Rec.RecordId);
end;
}
}
}
}
}
On page 50122 “CDS Prospect List” created above
Add Variables:
var
CurrentlyCoupledCDSProspect: Record "CDS cr95d_Prospects";
Add Trigger:
trigger OnInit()
begin
Codeunit.Run(Codeunit::"CRM Integration Management");
end;
Add Procedure:
procedure SetCurrentlyCoupledCDSProspect(CDSProspect: Record "CDS cr95d_Prospects")
begin
CurrentlyCoupledCDSProspect := CDSProspect;
end;
Add Action:
Actions
{
area(processing)
{
action(CreateFromCDS)
{
ApplicationArea = All;
Caption = 'Create in Business Central';
Promoted = true;
PromotedCategory = Process;
ToolTip = 'Generate the table from the coupled Microsoft Dataverse Prospect.';
trigger OnAction()
var
CDSProspect: Record "CDS cr95d_Prospects";
CRMIntegrationManagement: Codeunit "CRM Integration Management";
begin
CurrPage.SetSelectionFilter(CDSProspect);
CRMIntegrationManagement.CreateNewRecordsFromCRM(CDSProspect);
end;
}
}
}
Now you are good to proceed with Next Step.
You can jump to Next Step from here.
Create Integration Codeunit for Business Central & Dataverse Integration
This is the Seventh post in the series. If you want to go to previous post click here.
From the series of steps this post is dedicated to Step-6:
As a Sixth Step we will Create Integration Codeunit in Business Central
codeunit 50120 CDSDataverseEvent
{
}
Add these Procedures
local procedure LookupCDSProspect(SavedCRMId: Guid; var CRMId: Guid; IntTableFilter: Text): Boolean
var
CDSProspect: Record "CDS cr95d_Prospects";
OriginalCDSProspect: Record "CDS cr95d_Prospects";
OriginalCDSProspectList: Page "CDS Prospect List";
begin
if not IsNullGuid(CRMId) then begin
if CDSProspect.Get(CRMId) then
OriginalCDSProspectList.SetRecord(CDSProspect);
if not IsNullGuid(SavedCRMId) then
if OriginalCDSProspect.Get(SavedCRMId) then
OriginalCDSProspectList.SetCurrentlyCoupledCDSProspect(OriginalCDSProspect);
end;
CDSProspect.SetView(IntTableFilter);
OriginalCDSProspectList.SetTableView(CDSProspect);
OriginalCDSProspectList.LookupMode(true);
if OriginalCDSProspectList.RunModal = ACTION::LookupOK then begin
OriginalCDSProspectList.GetRecord(CDSProspect);
CRMId := CDSProspect.cr95d_ProspectsId;
exit(true);
end;
exit(false);
end;
local procedure AddEntityTableMapping(CRMEntityTypeName: Text; TableID: Integer; var TempNameValueBuffer: Record "Name/Value Buffer" temporary)
begin
TempNameValueBuffer.Init();
TempNameValueBuffer.ID := TempNameValueBuffer.Count + 1;
TempNameValueBuffer.Name := CopyStr(CRMEntityTypeName, 1, MaxStrLen(TempNameValueBuffer.Name));
TempNameValueBuffer.Value := Format(TableID);
TempNameValueBuffer.Insert();
end;
local procedure InsertIntegrationTableMapping(var IntegrationTableMapping: Record "Integration Table Mapping"; MappingName: Code[20]; TableNo: Integer; IntegrationTableNo: Integer; IntegrationTableUIDFieldNo: Integer; IntegrationTableModifiedFieldNo: Integer; TableConfigTemplateCode: Code[10]; IntegrationTableConfigTemplateCode: Code[10]; SynchOnlyCoupledRecords: Boolean)
begin
IntegrationTableMapping.CreateRecord(MappingName, TableNo, IntegrationTableNo, IntegrationTableUIDFieldNo, IntegrationTableModifiedFieldNo, TableConfigTemplateCode, IntegrationTableConfigTemplateCode, SynchOnlyCoupledRecords, IntegrationTableMapping.Direction::Bidirectional, 'CDS');
end;
procedure InsertIntegrationFieldMapping(IntegrationTableMappingName: Code[20]; TableFieldNo: Integer; IntegrationTableFieldNo: Integer; SynchDirection: Option; ConstValue: Text; ValidateField: Boolean; ValidateIntegrationTableField: Boolean)
var
IntegrationFieldMapping: Record "Integration Field Mapping";
begin
IntegrationFieldMapping.CreateRecord(IntegrationTableMappingName, TableFieldNo, IntegrationTableFieldNo, SynchDirection,
ConstValue, ValidateField, ValidateIntegrationTableField);
end;
To Add Event Subscriptions, Use the new Shift+Alt+E shortcut in the AL code editor to invoke a list of all events.
Search for Event OnGetCDSTableNo – “CRM Setup Defaults”
[EventSubscriber(ObjectType::Codeunit, Codeunit::"CRM Setup Defaults", 'OnGetCDSTableNo', '', false, false)]
local procedure OnGetCDSTableNo(BCTableNo: Integer; var CDSTableNo: Integer; var handled: Boolean);
begin
if BCTableNo = DATABASE::"Prospect" then begin
CDSTableNo := DATABASE::"CDS cr95d_Prospects";
handled := true;
end;
end;
Search for Event OnLookupCRMTables – “Lookup CRM Tables”
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Lookup CRM Tables", 'OnLookupCRMTables', '', false, false)]
local procedure OnLookupCRMTables(CRMTableID: Integer; NAVTableId: Integer; SavedCRMId: Guid; var CRMId: Guid; IntTableFilter: Text; var Handled: Boolean);
begin
if CRMTableID = Database::"CDS cr95d_Prospects" then
Handled := LookupCDSProspect(SavedCRMId, CRMId, IntTableFilter);
end;
Search for Event OnAddEntityTableMapping – “CRM Setup Defaults”
[EventSubscriber(ObjectType::Codeunit, Codeunit::"CRM Setup Defaults", 'OnAddEntityTableMapping', '', false, false)]
local procedure OnAddEntityTableMapping(var TempNameValueBuffer: Record "Name/Value Buffer");
begin
AddEntityTableMapping('Prospect', DATABASE::"CDS cr95d_Prospects", TempNameValueBuffer);
end;
Search for Event OnAfterResetConfiguration – “CDS Setup Defaults”
[EventSubscriber(ObjectType::Codeunit, Codeunit::"CDS Setup Defaults", 'OnAfterResetConfiguration', '', false, false)]
local procedure OnAfterResetConfiguration(CDSConnectionSetup: Record "CDS Connection Setup");
var
IntegrationTableMapping: Record "Integration Table Mapping";
IntegrationFieldMapping: Record "Integration Field Mapping";
CDSProspect: Record "CDS cr95d_Prospects";
Prospect: Record "Prospect";
begin
InsertIntegrationTableMapping(
IntegrationTableMapping, 'Prospect',
DATABASE::"Prospect", DATABASE::"CDS cr95d_Prospects", CDSProspect.FieldNo(cr95d_ProspectsId), CDSProspect.FieldNo(ModifiedOn), '', '', true);
InsertIntegrationFieldMapping('Prospect', Prospect.FieldNo("No."), CDSProspect.FieldNo(cr95d_ProspectsId), IntegrationFieldMapping.Direction::Bidirectional, '', true, false);
InsertIntegrationFieldMapping('Prospect', Prospect.FieldNo(Name), CDSProspect.FieldNo(cr95d_ProspectName), IntegrationFieldMapping.Direction::Bidirectional, '', true, false);
InsertIntegrationFieldMapping('Prospect', Prospect.FieldNo(Probability), CDSProspect.FieldNo(cr95d_Probability), IntegrationFieldMapping.Direction::Bidirectional, '', true, false);
InsertIntegrationFieldMapping('Prospect', Prospect.FieldNo("Contract Amount"), CDSProspect.FieldNo(cr95d_ContractAmount), IntegrationFieldMapping.Direction::Bidirectional, '', true, false);
InsertIntegrationFieldMapping('Prospect', Prospect.FieldNo("Contract Amount (Base)"), CDSProspect.FieldNo(cr95d_contractamount_Base), IntegrationFieldMapping.Direction::Bidirectional, '', true, false);
InsertIntegrationFieldMapping('Prospect', Prospect.FieldNo(Stage), CDSProspect.FieldNo(cr95d_Stage), IntegrationFieldMapping.Direction::Bidirectional, '', true, false);
InsertIntegrationFieldMapping('Prospect', Prospect.FieldNo("Forecast Revenue"), CDSProspect.FieldNo(cr95d_ForcastedRevenue), IntegrationFieldMapping.Direction::Bidirectional, '', true, false);
InsertIntegrationFieldMapping('Prospect', Prospect.FieldNo("Forecast Revenue (Base)"), CDSProspect.FieldNo(cr95d_forcastedrevenue_Base), IntegrationFieldMapping.Direction::Bidirectional, '', true, false);
end;
Now you are good to proceed with Next Step.
You can jump to Next Step from here.
Walkthrough Extension Development in Online Sandbox – Business Central
I have my Sandbox environment as below:

Details of the Sandbox as below:

Connecting VS code to above environment.

When you try to Publish the extension, it will ask you to authenticate.

Copy the Link and open in the browser and paste the code in the box as shown below.

Next it will ask for your Online Instance User Id & Password provide it and on confirmation close the page. It will start deploying the extension.
In this walkthrough I am using below scenario:
Requirement is we need to be able to define some code for dimension combinations. Let me say it will be Sales Code, you can choose name of your choice, this is not Salesperson code.

I am assuming these dimensions will follow the sequence as defined on my General Ledger Setup as below:

On Sales Order & Invoice user should be able to select this Sales Code and dimensions should be populated on order accordingly.
For tracking purpose this Sales Code should flow to Posted Sales Invoice and Customer Ledger.


So, Let’s Start with the development process:
Step-1 We will Create the Table

Here is the code for LookupDimValue Function, it will set filter for Dimension Code on Dimension Value table, as per the Dimension No passed. (1 is for Shortcut Dimension defined on General Ledger Setup, similarly for other 8 dimensions)

Step-2 Next, we will create the Page for this Setup

Step-3 Next, we will add the Sales Code field to all required Tables & Pages

Here is the code for AddDim Function. It is assumed that only combination provided in Sales Code Setup will be used. If you have defined Default dimensions or Combinations, those need to be preserved else this code will overwrite them. You will have to find the Data Set Entry, store them in temporary table used in below code and then add all the dimensions from the setup.
When you Select Sales Code on the Order or Invoice it will populate all the dimensions defined in the Setup.

Code for other Tables & Pages







Step-4 Next, we need to take care to flow the Sales Code to the Ledger and Posted documents.
For posted documents we need not to worry it will flow automatically provided we have defined the fields on same Id.
However, for ledger we will require to use Events to pass the data to their destinations. In this case we are only passing to Customer Ledger Entry. For this we will create a Codeunit.
To Add Event Subscriptions, Use the new Shift+Alt+E shortcut in the AL code editor to invoke a list of all events.

Search for the even you are looking for.
When pressing Enter to select an event entry, an event subscriber for the event will be inserted at the cursor position in the active AL code editor window.
Here is the Codeunit Code:

This is not the final code; much more can be done or need to be done before it can be delivered to customer for their use. Purpose of this walkthrough was to demo the way we can customize the solution using extensions and publishing to Online tenant in Sandbox.
Hope you enjoyed the information. Will come with more similar information in my next posts. Till then keep exploring, learning and sharing your knowledge with others.
Remain safe, take care of your loved ones, put your mask, maintain safe distance and don’t forget to get vaccinated.
You must be logged in to post a comment.