Table 5335 Integration Table Mapping
- App
- Base Application
- Namespace
- Microsoft.Integration.SyncEngine
- Versions
- 17-28
Fields, 41Keys, 3Procedures, 47Events, 6Obsolete, 1
Versions171819202122232425262728
Source29
Source in 29
src/Layers/W1/BaseApp/Integration/SynchEngine/IntegrationTableMapping.Table.al1269 lines, Copyright (c) Microsoft Corporation. MIT
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.Integration.SyncEngine;
using Microsoft.CRM.Opportunity;
using Microsoft.Integration.D365Sales;
using Microsoft.Integration.Dataverse;
using Microsoft.Sales.Document;
using System.IO;
using System.Reflection;
using System.Telemetry;
using System.Threading;
table 5335 "Integration Table Mapping"
{
Caption = 'Integration Table Mapping';
DrillDownPageID = "Integration Table Mapping List";
LookupPageID = "Integration Table Mapping List";
DataClassification = CustomerContent;
fields
{
field(1; Name; Code[20])
{
Caption = 'Name';
ToolTip = 'Specifies the name of the integration table mapping entry.';
NotBlank = true;
}
field(2; "Table ID"; Integer)
{
Caption = 'Table ID';
TableRelation = "Table Metadata".ID;
}
field(3; "Integration Table ID"; Integer)
{
Caption = 'Integration Table ID';
TableRelation = "Table Metadata".ID;
}
field(4; "Synch. Codeunit ID"; Integer)
{
Caption = 'Synch. Codeunit ID';
TableRelation = "Table Metadata".ID;
}
field(5; "Integration Table UID Fld. No."; Integer)
{
Caption = 'Integration Table UID Fld. No.';
Description = 'Integration Table Unique Identifier Field No.';
trigger OnValidate()
var
"Field": Record "Field";
TypeHelper: Codeunit "Type Helper";
begin
Field.Get("Integration Table ID", "Integration Table UID Fld. No.");
TypeHelper.TestFieldIsNotObsolete(Field);
"Int. Table UID Field Type" := Field.Type;
end;
}
field(6; "Int. Tbl. Modified On Fld. No."; Integer)
{
Caption = 'Int. Tbl. Modified On Fld. No.';
Description = 'Integration Table Modified On Field No.';
}
field(7; "Int. Table UID Field Type"; Integer)
{
Caption = 'Int. Table UID Field Type';
Editable = false;
}
field(8; "Table Config Template Code"; Code[10])
{
Caption = 'Table Config Template Code';
TableRelation = "Config. Template Header".Code where("Table ID" = field("Table ID"));
/// Replaced with Integration Table Config Template table for Dataverse type mappings
/// used only for Master Data Management mappings
}
field(9; "Int. Tbl. Config Template Code"; Code[10])
{
Caption = 'Int. Tbl. Config Template Code';
TableRelation = "Config. Template Header".Code where("Table ID" = field("Integration Table ID"));
/// Replaced with Integration Table Config Template table for Dataverse type mappings
/// used only for Master Data Management mappings
}
field(10; Direction; Option)
{
Caption = 'Direction';
ToolTip = 'Specifies the synchronization direction.';
OptionCaption = 'Bidirectional,ToIntegrationTable,FromIntegrationTable';
OptionMembers = Bidirectional,ToIntegrationTable,FromIntegrationTable;
trigger OnValidate()
var
"Field": Record "Field";
IntegrationFieldMapping: Record "Integration Field Mapping";
CRMFullSynchReviewLine: Record "CRM Full Synch. Review Line";
JobQueueEntry: Record "Job Queue Entry";
NoEnabledFieldMappingsExist: Boolean;
begin
if "Int. Table UID Field Type" = Field.Type::Option then
if Direction = Direction::Bidirectional then
Error(OptionMappingCannotBeBidirectionalErr)
else begin
IntegrationFieldMapping.SetRange("Integration Table Mapping Name", Name);
IntegrationFieldMapping.ModifyAll(Direction, Direction);
if CRMFullSynchReviewLine.Get(Name) then
if CRMFullSynchReviewLine.Direction <> Direction then begin
CRMFullSynchReviewLine.Direction := Direction;
CRMFullSynchReviewLine.Modify();
end;
if Direction = Direction::ToIntegrationTable then begin
JobQueueEntry.SetRange("Record ID to Process", RecordId);
JobQueueEntry.SetRange("Object ID to Run", Codeunit::"Integration Synch. Job Runner");
JobQueueEntry.SetRange("Object Type to Run", JobQueueEntry."Object Type to Run"::Codeunit);
if JobQueueEntry.FindFirst() then
if JobQueueEntry.Status = JobQueueEntry.Status::Ready then begin
JobQueueEntry.Status := JobQueueEntry.Status::"On Hold with Inactivity Timeout";
JobQueueEntry.Modify();
end;
end;
end
else begin
IntegrationFieldMapping.SetRange("Integration Table Mapping Name", Rec.Name);
IntegrationFieldMapping.SetRange(Status, IntegrationFieldMapping.Status::Enabled);
NoEnabledFieldMappingsExist := IntegrationFieldMapping.IsEmpty();
IntegrationFieldMapping.SetRange(Direction, Rec.Direction);
if not NoEnabledFieldMappingsExist then
if IntegrationFieldMapping.IsEmpty() then
if GuiAllowed() then
Error(DirectionFieldsErr, Format(Rec.Direction))
else
Error(DirectionFieldsNoUIHintErr, Format(Rec.Direction))
end;
if Rec.Direction <> Rec.Direction::FromIntegrationTable then
if Rec."Multi Company Synch. Enabled" then
Message(ChangeDirectionMultiCompanyMsg);
end;
}
field(11; "Int. Tbl. Caption Prefix"; Text[30])
{
Caption = 'Int. Tbl. Caption Prefix';
ToolTip = 'Specifies text that appears before the caption of the integration table wherever the caption is used.';
}
field(12; "Synch. Int. Tbl. Mod. On Fltr."; DateTime)
{
Caption = 'Synch. Int. Tbl. Mod. On Fltr.';
ToolTip = 'Specifies a date/time filter that uses the date on which records were modified to determine which records to synchronize to the integration system. The filter is based on the SystemModifiedAt field on the Business Central table records.';
Description = 'Scheduled synch. Integration Table Modified On Filter';
}
field(13; "Synch. Modified On Filter"; DateTime)
{
Caption = 'Synch. Modified On Filter';
ToolTip = 'Specifies a date/time filter that uses the date on which records were modified to determine which records to synchronize from the system you are integrating with. The filter is based on the Modified On field on the integration table records.';
Description = 'Scheduled synch. Modified On Filter';
}
field(14; "Table Filter"; BLOB)
{
Caption = 'Table Filter';
}
field(15; "Integration Table Filter"; BLOB)
{
Caption = 'Integration Table Filter';
}
field(16; "Synch. Only Coupled Records"; Boolean)
{
Caption = 'Synch. Only Coupled Records';
ToolTip = 'Specifies if the synchronization engine will process only currently coupled records or couple the newly created records as well.';
InitValue = true;
trigger OnValidate()
begin
CheckDeletionConflictResolutionStrategy();
end;
}
field(17; "Parent Name"; Code[20])
{
Caption = 'Parent Name';
}
field(18; "Graph Delta Token"; Text[250])
{
Caption = 'Graph Delta Token';
}
field(19; "Int. Tbl. Delta Token Fld. No."; Integer)
{
Caption = 'Int. Tbl. Delta Token Fld. No.';
}
field(20; "Int. Tbl. ChangeKey Fld. No."; Integer)
{
Caption = 'Int. Tbl. ChangeKey Fld. No.';
}
field(21; "Int. Tbl. State Fld. No."; Integer)
{
Caption = 'Int. Tbl. State Fld. No.';
}
field(22; "Delete After Synchronization"; Boolean)
{
Caption = 'Delete After Synchronization';
}
field(23; "BC Rec Page Id"; Integer)
{
Caption = 'The Id of the BC Record Page';
}
field(24; "CDS Rec Page Id"; Integer)
{
Caption = 'The Id of the Dataverse Record Page';
}
field(25; "Deletion-Conflict Resolution"; Enum "Integration Deletion Conflict Resolution")
{
Caption = 'Resolve Deletion Conflicts';
ToolTip = 'Specifies the action to take when a coupled record is deleted in one of the connected applications.';
trigger OnValidate()
begin
CheckDeletionConflictResolutionStrategy();
end;
}
field(26; "Update-Conflict Resolution"; Enum "Integration Update Conflict Resolution")
{
Caption = 'Resolve Update Conflicts';
ToolTip = 'Specifies the action to take when a coupled record is updated in both of the connected applications.';
}
field(27; "Uncouple Codeunit ID"; Integer)
{
Caption = 'Uncouple Codeunit ID';
TableRelation = "CodeUnit Metadata".ID;
}
field(28; "Coupling Codeunit ID"; Integer)
{
Caption = 'Coupling Codeunit ID';
TableRelation = "CodeUnit Metadata".ID;
}
field(29; "Synch. After Bulk Coupling"; Boolean)
{
Caption = 'Synch. After Match-Based Coupling';
}
field(30; "Dependency Filter"; Text[250])
{
Caption = 'Dependency Filter';
}
field(31; "Create New in Case of No Match"; Boolean)
{
Caption = 'Create New in Case of No Match';
}
field(32; Type; Enum "Integration Table Mapping Type")
{
Caption = 'Type';
}
field(33; "Disable Event Job Resch."; Boolean)
{
Caption = 'Disable Event-driven Synch. Job Rescheduling';
ToolTip = 'Specifies if event-based rescheduling of synchronization jobs should be turned off for this table mapping.';
trigger OnValidate()
begin
if not GuiAllowed() then
exit;
if Rec."Disable Event Job Resch." then
if not Confirm(DisableEventDrivenReshedulingQst) then
Error('');
if not Confirm(EnableEventDrivenReshedulingQst) then
Error('');
end;
}
field(34; "Multi Company Synch. Enabled"; Boolean)
{
Caption = 'Multi-Company Synchronization Enabled';
ToolTip = 'Specifies if the multi-company synchronization is enabled for this mapping.';
trigger OnValidate()
var
FeatureTelemetry: Codeunit "Feature Telemetry";
begin
FeatureTelemetry.LogUptake('0000LCM', 'Dataverse Multi-Company Synch', Enum::"Feature Uptake Status"::Discovered);
FeatureTelemetry.LogUptake('0000LCN', 'Dataverse Multi-Company Synch', Enum::"Feature Uptake Status"::"Set up");
if Rec."Multi Company Synch. Enabled" then
Rec.EnableMultiCompanySynchronization()
else
Rec.DisableMultiCompanySynchronization();
end;
}
field(35; "Table Caption"; Text[250])
{
Caption = 'Table Caption';
}
field(98; "No. of Errors"; Integer)
{
Caption = 'Number of Errors';
ToolTip = 'Specifies the number of errors for this mapping.';
FieldClass = FlowField;
CalcFormula = sum("Integration Synch. Job".Failed where("Integration Table Mapping Name" = field(Name)));
}
field(99; "No. of Skipped"; Integer)
{
Caption = 'Number of Skipped Records';
ToolTip = 'Specifies the number of records that are excluded from the synchronization because of repetitive errors.';
FieldClass = FlowField;
CalcFormula = count("CRM Integration Record" where("Table ID" = field("Table ID"), Skipped = const(true)));
}
field(100; "Full Sync is Running"; Boolean)
{
Caption = 'Full Sync is Running';
Description = 'This is set to TRUE when FullSync starts, and to FALSE when FullSync completes.';
trigger OnValidate()
begin
if xRec.Get(Name) then;
if (not xRec."Full Sync is Running") and "Full Sync is Running" then begin
"Last Full Sync Start DateTime" := CurrentDateTime;
"Full Sync Session ID" := SessionId();
end;
if not "Full Sync is Running" then
"Full Sync Session ID" := 0;
end;
}
field(101; "Full Sync Session ID"; Integer)
{
Caption = 'Full Sync Session ID';
Description = 'The ID of the session running the FullSync must be 0 if FullSync is not running.';
}
field(102; "Last Full Sync Start DateTime"; DateTime)
{
Caption = 'Last Full Sync Start DateTime';
Description = 'The starting date and time of the last time FullSync was run. This is used to re-run in case FullSync failed to reset these fields.';
}
field(103; "User Defined"; Boolean)
{
Caption = 'User Defined';
ToolTip = 'Specifies if the field is generated manually through the integration table mapping wizard.';
Description = 'Indicates whether the table mapping was defined manually by the user or by the system.';
}
}
keys
{
key(Key1; Name)
{
Clustered = true;
}
key(Key2; "Table ID", "Integration Table ID")
{
}
key(Key3; "Table ID", "Integration Table ID", Type)
{
}
}
fieldgroups
{
}
trigger OnDelete()
var
IntegrationFieldMapping: Record "Integration Field Mapping";
ManIntegrationTableMapping: Record "Man. Integration Table Mapping";
TableConfigTemplate: Record "Table Config Template";
IntTableConfigTemplate: Record "Int. Table Config Template";
begin
IntegrationFieldMapping.SetRange("Integration Table Mapping Name", Name);
IntegrationFieldMapping.DeleteAll();
ManIntegrationTableMapping.SetRange(Name, Name);
if ManIntegrationTableMapping.IsEmpty() then begin
TableConfigTemplate.SetRange("Integration Table Mapping Name", Name);
TableConfigTemplate.DeleteAll();
IntTableConfigTemplate.SetRange("Integration Table Mapping Name", Name);
IntTableConfigTemplate.DeleteAll();
end;
end;
var
JobLogEntryNo: Integer;
DateType: Option ,Integration,Local;
ConfirmIncludeEntitiesWithNoCompanyQst: Label 'Do you want the Integration Table Filter to include %1 entities with no value in %2 attribute?', Comment = '%1 - Dataverse service name; %2 - attribute name of a Dataverse entity';
OptionMappingCannotBeBidirectionalErr: Label 'Option mappings can only synchronize from integration table or to integration table.';
UserChoseNotToIncludeEntitiesWithEmptyCompanyNameTxt: Label 'User chose not to include %1 entities with empty company id in the Integration Table Filter of the %2 mapping.', Locked = true;
RemoveCouplingStrategyQst: Label 'Synch. Only Coupled Records is unchecked. Therefore, if conflict resolution strategy removes a broken coupling, a subsequent scheduled synchronization job may recreate the coupling. Do you want to continue?';
TelemetryCategoryTok: Label 'AL Dataverse Integration', Locked = true;
CompanyIdFieldNameTxt: Label 'CompanyId', Locked = true;
DisableEventDrivenReshedulingQst: Label 'This will disable the event-based rescheduling of synchronization jobs for this table. \\The frequency of the synchronization job runs is specified in the Inactivity Timeout Period field on the corresponding job queue entry. \\Do you want to continue?';
EnableEventDrivenReshedulingQst: Label 'This will enable the event-based rescheduling of synchronization jobs for this table. \\The synchronization job will be rescheduled within 30-60 seconds after an insertion, change or deletion on the corresponding table. \\In case of no changes during a long period, the synchronization job will be rescheduled as specified in the Inactivity Timeout Period field on the corresponding job queue entry. \\Do you want to continue?';
CompanyFilterRemovedQst: Label 'This will remove the company field filter from Integration Table Filter and make the synchronization engine process %1 entities regardless of their Company field value. Do you want to continue?', Comment = '%1 - a table caption';
CompanyFilterRemovedExtendedMsg: Label '%1 entities will be synchronized regardless of their Company field value. To control which entities get synchronized to this company, set the Integration Table Filter on other fields. We strongly recommend to set the direction of this mapping to ''From Integration''. \\If you set it up to synchronize bidirectionally or to synchronize ''To Integration'', to avoid duplicates being created, use match-based coupling or consolidated filtering across companies instead of just unchecking the Synch. Only Coupled Records checkbox. \\If your number series do not guarantee uniqueness of primary key values across multiple companies, then use a transformation rule in the direction ''To Integration'' to add a prefix to primary key values, to ensure their uniqueness in Dataverse.', Comment = '%1 - a table caption';
CompanyFilterRemovedShortMsg: Label '%1 entities will be synchronized regardless of their Company field value. To control which entities get synchronized to this company, set the Integration Table Filter on other fields.', Comment = '%1 - a table caption';
CompanyFilterResetMsg: Label 'The company field filter on the Integration Table Filter is reset to default.';
CompanyFilterStrengthenedQst: Label 'This will make the synchronization engine process only %1 entities that correspond to the current company. Do you want to continue?', Comment = '%1 - a table caption';
CompanyFilterResetToDefaultQst: Label 'This will reset the company field filter from Integration Table Filter to the default. Do you want to continue?';
CompanyFilterStrengthenedMsg: Label 'The synchronization will consider only %1 entities that correspond to this company. \\To make Business Central process %1 entities that are originally created in %3, the %3 users must set their Company value to match the company %2.', Comment = '%1 - a table caption; %2 - current company name; %3 - Dynamics 365 service name';
InstallLatestSolutionConfirmLbl: Label 'This functionality requires the latest integration solution to be imported on your Dataverse environment. You will be prompted to sign in with your Dataverse administrator account credentials. Do you want to continue?';
OrTok: Label '%1|%2', Locked = true;
ChangeDirectionMultiCompanyMsg: Label 'This mapping is set up for multi-company synchronization. We strongly recommend to set the direction of this mapping to ''From Integration''. \\If you set it up to synchronize bidirectionally or to synchronize ''To Integration'', to avoid duplicates being created, use match-based coupling or consolidated filtering across companies instead of just unchecking the Synch. Only Coupled Records checkbox. \\If your number series do not guarantee uniqueness of primary key values across multiple companies, then use a Transformation Rule in the direction ''To Integration'' to add a prefix to primary key values, to ensure their uniqueness in Dataverse.';
DirectionFieldsErr: Label 'You must set the direction of at least one enabled integration field mapping to ''%1''. Choose the Fields action to edit the integration field mappings.', Comment = '%1 - an option value';
DirectionFieldsNoUIHintErr: Label 'You must set the direction of at least one enabled integration field mapping to ''%1''.', Comment = '%1 - an option value';
MultipleConfigTemplatesLbl: Label '%1 templates', Comment = '%1 - number of templates';
procedure FindFilteredRec(RecordRef: RecordRef; var OutOfMapFilter: Boolean) Found: Boolean
var
TempRecRef: RecordRef;
begin
TempRecRef.Open(RecordRef.Number, true);
CopyRecordReference(RecordRef, TempRecRef, false);
if "Table ID" = RecordRef.Number then
SetRecordRefFilter(TempRecRef)
else
SetIntRecordRefFilter(TempRecRef);
Found := TempRecRef.Find();
OutOfMapFilter := not Found;
TempRecRef.Close();
end;
[Scope('Cloud')]
procedure FindMapping(TableNo: Integer; IntegrationTableNo: Integer): Boolean
begin
SetRange("Table ID", TableNo);
SetRange("Integration Table ID", IntegrationTableNo);
SetRange("Delete After Synchronization", false);
exit(FindFirst());
end;
procedure FindMappingForTable(TableId: Integer): Boolean
begin
SetRange("Table ID", TableId);
SetRange("Delete After Synchronization", false);
exit(FindFirst());
end;
procedure DoesExistForTable(TableId: Integer): Boolean
begin
SetRange("Table ID", TableId);
SetRange("Delete After Synchronization", false);
exit(not IsEmpty());
end;
procedure IsFullSynch(): Boolean
begin
exit("Full Sync is Running" and "Delete After Synchronization");
end;
procedure GetName() Result: Code[20]
begin
if "Delete After Synchronization" then
Result := "Parent Name";
if Result = '' then
Result := Name;
end;
procedure GetDirection(): Integer
var
IntegrationTableMapping: Record "Integration Table Mapping";
begin
IntegrationTableMapping.Get(GetName());
exit(IntegrationTableMapping.Direction);
end;
procedure GetJobLogEntryNo(): Integer
begin
exit(JobLogEntryNo)
end;
procedure GetTempDescription(): Text
var
Separator: Text;
begin
case Direction of
Direction::Bidirectional:
Separator := '<->';
Direction::ToIntegrationTable:
Separator := '->';
Direction::FromIntegrationTable:
Separator := '<-';
end;
exit(
StrSubstNo(
'%1 %2 %3', GetTableCaption("Table ID"), Separator, GetTableCaption("Integration Table ID")));
end;
procedure GetExtendedIntegrationTableCaption(): Text
var
TableCaption: Text;
begin
TableCaption := GetTableExternalName("Integration Table ID");
if TableCaption <> '' then
if "Int. Tbl. Caption Prefix" <> '' then
exit(StrSubstNo('%1 %2', "Int. Tbl. Caption Prefix", TableCaption));
exit(TableCaption);
end;
procedure GetUserFriendlyMappingName(): Text
var
LocalRecordRef: RecordRef;
IntegrationRecordRef: RecordRef;
begin
if (Rec."Table ID" = 0) or (Rec."Integration Table ID" = 0) then
exit('');
LocalRecordRef.Open(Rec."Table ID");
IntegrationRecordRef.Open(Rec."Integration Table ID");
if Rec."Table ID" = Rec."Integration Table ID" then
exit(LocalRecordRef.Caption());
exit(LocalRecordRef.Caption() + ' - ' + IntegrationRecordRef.Caption());
end;
local procedure GetTableCaption(ID: Integer): Text
var
TableMetadata: Record "Table Metadata";
begin
if TableMetadata.Get(ID) then
exit(TableMetadata.Caption);
exit('');
end;
local procedure GetTableExternalName(ID: Integer): Text
var
TableMetadata: Record "Table Metadata";
begin
if TableMetadata.Get(ID) then
exit(TableMetadata.ExternalName);
exit('');
end;
procedure SetTableFilter("Filter": Text)
var
OutStream: OutStream;
begin
"Table Filter".CreateOutStream(OutStream);
OutStream.Write(Filter);
end;
procedure GetTableFilter() Value: Text
var
InStream: InStream;
begin
CalcFields("Table Filter");
"Table Filter".CreateInStream(InStream);
InStream.Read(Value);
end;
procedure SetIntegrationTableFilter(IntTableFilter: Text)
var
OutStream: OutStream;
begin
"Integration Table Filter".CreateOutStream(OutStream);
OutStream.Write(IntTableFilter);
end;
[Scope('OnPrem')]
procedure SuggestToIncludeEntitiesWithNullCompany(var IntTableFilter: Text);
var
Field: Record "Field";
CRMProductName: Codeunit "CRM Product Name";
CompanyIdFieldNo: Integer;
CompanyIdFilterStartPos: Integer;
CompanyIdFilter: Text;
ModifiedCompanyIdFilter: Text;
OrNullGuid: Text;
begin
OrNullGuid := '|{00000000-0000-0000-0000-000000000000}';
Field.SetRange(TableNo, "Integration Table ID");
Field.SetRange(Type, Field.Type::GUID);
Field.SetRange(FieldName, CompanyIdFieldNameTxt);
if not Field.FindFirst() then
exit;
CompanyIdFieldNo := Field."No.";
CompanyIdFilterStartPos := IntTableFilter.IndexOf('Field' + Format(CompanyIdFieldNo) + '=1');
if CompanyIdFilterStartPos <= 0 then
exit;
CompanyIdFilter := CopyStr(IntTableFilter, CompanyIdFilterStartPos);
CompanyIdFilter := CopyStr(CompanyIdFilter, 1, CompanyIdFilter.IndexOf(')'));
if (CompanyIdFilter = '') or (CompanyIdFilter.IndexOf(OrNullGuid) > 0) then
exit;
if not Confirm(StrSubstNo(ConfirmIncludeEntitiesWithNoCompanyQst, CRMProductName.CDSServiceName(), Field."Field Caption")) then begin
Session.LogMessage('0000EG4', StrSubstNo(UserChoseNotToIncludeEntitiesWithEmptyCompanyNameTxt, CRMProductName.CDSServiceName(), Name), Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', TelemetryCategoryTok);
exit;
end;
ModifiedCompanyIdFilter := CompanyIdFilter.Replace(')', OrNullGuid + ')');
IntTableFilter := IntTableFilter.Replace(CompanyIdFilter, ModifiedCompanyIdFilter);
end;
procedure GetIntegrationTableFilter() Value: Text
var
InStream: InStream;
begin
CalcFields("Integration Table Filter");
"Integration Table Filter".CreateInStream(InStream);
InStream.Read(Value);
end;
procedure SetIntTableModifiedOn(ModifiedOn: DateTime)
begin
if (ModifiedOn <> 0DT) and (ModifiedOn > "Synch. Int. Tbl. Mod. On Fltr.") then begin
"Synch. Int. Tbl. Mod. On Fltr." := ModifiedOn;
Modify(true);
end;
end;
procedure SetTableModifiedOn(ModifiedOn: DateTime)
begin
if (ModifiedOn <> 0DT) and (ModifiedOn > "Synch. Modified On Filter") then begin
"Synch. Modified On Filter" := ModifiedOn;
Modify(true);
end;
end;
procedure SetJobLogEntryNo(NewJobLogEntryNo: Integer)
begin
JobLogEntryNo := NewJobLogEntryNo;
end;
procedure ShowLog(JobIDFilter: Text)
begin
ShowLog('', JobIDFilter, '');
end;
procedure ShowSynchronizationLog(var IntegrationTableMapping: Record "Integration Table Mapping")
var
TempIntegrationSynchJob: Record "Integration Synch. Job" temporary;
NameFilter: Text;
begin
NameFilter := GetNameFilter(IntegrationTableMapping);
TempIntegrationSynchJob.SetRange(Type, TempIntegrationSynchJob.Type::Synchronization);
ShowLog(NameFilter, '', TempIntegrationSynchJob.GetFilter(Type));
end;
procedure ShowUncouplingLog(var IntegrationTableMapping: Record "Integration Table Mapping")
var
TempIntegrationSynchJob: Record "Integration Synch. Job" temporary;
NameFilter: Text;
begin
NameFilter := GetNameFilter(IntegrationTableMapping);
TempIntegrationSynchJob.SetRange(Type, TempIntegrationSynchJob.Type::Uncoupling);
ShowLog(NameFilter, '', TempIntegrationSynchJob.GetFilter(Type));
end;
procedure ShowCouplingLog(var IntegrationTableMapping: Record "Integration Table Mapping")
var
TempIntegrationSynchJob: Record "Integration Synch. Job" temporary;
NameFilter: Text;
begin
NameFilter := GetNameFilter(IntegrationTableMapping);
TempIntegrationSynchJob.SetRange(Type, TempIntegrationSynchJob.Type::Coupling);
ShowLog(NameFilter, '', TempIntegrationSynchJob.GetFilter(Type));
end;
procedure SetOriginalJobQueueEntryOnHold(var JobQueueEntry: Record "Job Queue Entry"; var PrevStatus: Option)
var
OriginalIntegrationTableMapping: Record "Integration Table Mapping";
begin
if Rec."Full Sync is Running" then begin
OriginalIntegrationTableMapping.Get(Rec."Parent Name");
JobQueueEntry.SetRange("Record ID to Process", OriginalIntegrationTableMapping.RecordId);
if JobQueueEntry.FindFirst() then begin
PrevStatus := JobQueueEntry.Status;
JobQueueEntry.SetStatus(JobQueueEntry.Status::"On Hold");
end;
end;
end;
procedure SetOriginalJobQueueEntryStatus(var JobQueueEntry: Record "Job Queue Entry"; Status: Option)
var
OriginalIntegrationTableMapping: Record "Integration Table Mapping";
begin
if Rec."Full Sync is Running" then begin
OriginalIntegrationTableMapping.Get(Rec."Parent Name");
OriginalIntegrationTableMapping.CopyModifiedOnFilters(Rec);
if JobQueueEntry.FindFirst() then
JobQueueEntry.SetStatus(Status);
end;
end;
procedure UpdateTableMappingModifiedOn(LatestModifiedOn: array[2] of DateTime)
var
IsChanged: Boolean;
begin
if LatestModifiedOn[DateType::Integration] > Rec."Synch. Modified On Filter" then begin
Rec."Synch. Modified On Filter" := LatestModifiedOn[DateType::Integration];
IsChanged := true;
end;
if LatestModifiedOn[DateType::Local] > Rec."Synch. Int. Tbl. Mod. On Fltr." then begin
Rec."Synch. Int. Tbl. Mod. On Fltr." := LatestModifiedOn[DateType::Local];
IsChanged := true;
end;
if IsChanged then
Rec.Modify(true);
end;
local procedure CopyRecordReference(FromRec: RecordRef; var ToRec: RecordRef; ValidateOnInsert: Boolean)
var
FromField: FieldRef;
ToField: FieldRef;
Counter: Integer;
begin
if FromRec.Number <> ToRec.Number then
exit;
ToRec.Init();
for Counter := 1 to FromRec.FieldCount do begin
FromField := FromRec.FieldIndex(Counter);
if not (FromField.Type in [FieldType::BLOB, FieldType::TableFilter]) then begin
ToField := ToRec.Field(FromField.Number);
ToField.Value := FromField.Value();
end;
end;
ToRec.Insert(ValidateOnInsert);
end;
local procedure ShowLog(NameFilter: Text; JobIDFilter: Text; JobTypeFilter: Text)
var
IntegrationSynchJob: Record "Integration Synch. Job";
begin
if (NameFilter = '') and (Name = '') then
exit;
IntegrationSynchJob.SetCurrentKey("Start Date/Time", ID);
IntegrationSynchJob.Ascending := false;
IntegrationSynchJob.FilterGroup(2);
if NameFilter <> '' then
IntegrationSynchJob.SetFilter("Integration Table Mapping Name", NameFilter)
else
IntegrationSynchJob.SetRange("Integration Table Mapping Name", Name);
IntegrationSynchJob.FilterGroup(0);
if JobIDFilter <> '' then
IntegrationSynchJob.SetFilter(ID, JobIDFilter);
if JobTypeFilter <> '' then
IntegrationSynchJob.SetFilter(Type, JobTypeFilter);
if IntegrationSynchJob.FindFirst() then;
Page.Run(Page::"Integration Synch. Job List", IntegrationSynchJob);
end;
local procedure GetNameFilter(var IntegrationTableMapping: Record "Integration Table Mapping"): Text
var
NameFilter: Text;
begin
if IntegrationTableMapping.FindSet() then
repeat
if Name <> '' then begin
if NameFilter <> '' then
NameFilter += '|';
NameFilter += IntegrationTableMapping.Name;
end;
until IntegrationTableMapping.Next() = 0;
exit(NameFilter);
end;
procedure SynchronizeNow(ResetLastSynchModifiedOnDateTime: Boolean)
begin
SynchronizeNow(ResetLastSynchModifiedOnDateTime, false);
end;
procedure SynchronizeNow(ResetLastSynchModifiedOnDateTime: Boolean; ResetSynchonizationTimestampOnRecords: Boolean)
var
CRMIntegrationRecord: Record "CRM Integration Record";
CRMSetupDefaults: Codeunit "CRM Setup Defaults";
CRMIntegrationManagement: Codeunit "CRM Integration Management";
IsHandled: Boolean;
begin
OnSynchronizeNow(Rec, ResetLastSynchModifiedOnDateTime, ResetSynchonizationTimestampOnRecords, IsHandled);
if IsHandled then
exit;
Codeunit.Run(Codeunit::"CRM Integration Management");
if ResetLastSynchModifiedOnDateTime then begin
Clear("Synch. Modified On Filter");
Clear("Synch. Int. Tbl. Mod. On Fltr.");
Modify();
end;
if ResetSynchonizationTimestampOnRecords then begin
CRMIntegrationManagement.RepairBrokenCouplings(true);
CRMIntegrationRecord.SetRange("Table ID", "Table ID");
case Direction of
Direction::ToIntegrationTable:
CRMIntegrationRecord.ModifyAll("Last Synch. Modified On", 0DT);
Direction::FromIntegrationTable:
CRMIntegrationRecord.ModifyAll("Last Synch. CRM Modified On", 0DT);
end
end;
Commit();
CRMSetupDefaults.CreateJobQueueEntry(Rec);
end;
[Scope('OnPrem')]
procedure SynchronizeOptionNow(ResetLastSynchModifiedOnDateTime: Boolean; ResetSynchonizationTimestampOnRecords: Boolean)
var
CRMOptionMapping: Record "CRM Option Mapping";
CRMSetupDefaults: Codeunit "CRM Setup Defaults";
begin
Codeunit.Run(Codeunit::"CRM Integration Management");
if ResetLastSynchModifiedOnDateTime then begin
Clear("Synch. Modified On Filter");
Clear("Synch. Int. Tbl. Mod. On Fltr.");
Modify();
end;
if ResetSynchonizationTimestampOnRecords then begin
CRMOptionMapping.SetRange("Table ID", "Table ID");
CRMOptionMapping.SetRange("Integration Table ID", "Integration Table ID");
if Direction = Direction::ToIntegrationTable then
CRMOptionMapping.ModifyAll("Last Synch. Modified On", 0DT);
end;
Commit();
CRMSetupDefaults.CreateJobQueueEntry(Rec);
end;
procedure GetRecordRef(ID: Variant; var IntegrationRecordRef: RecordRef): Boolean
var
IDFieldRef: FieldRef;
RecordID: RecordID;
TextKey: Text;
begin
IntegrationRecordRef.Close();
if ID.IsGuid then begin
IntegrationRecordRef.Open("Integration Table ID");
IDFieldRef := IntegrationRecordRef.Field("Integration Table UID Fld. No.");
IDFieldRef.SetFilter(ID);
exit(IntegrationRecordRef.FindFirst());
end;
if ID.IsRecordId then begin
RecordID := ID;
if RecordID.TableNo = "Table ID" then
exit(IntegrationRecordRef.Get(ID));
end;
if ID.IsText then begin
IntegrationRecordRef.Open("Integration Table ID");
IDFieldRef := IntegrationRecordRef.Field("Integration Table UID Fld. No.");
TextKey := ID;
IDFieldRef.SetFilter('%1', TextKey);
exit(IntegrationRecordRef.FindFirst());
end;
end;
procedure SetIntRecordRefFilter(var IntRecordRef: RecordRef)
var
ModifiedOnFieldRef: FieldRef;
TableFilter: Text;
begin
TableFilter := GetIntegrationTableFilter();
if TableFilter <> '' then
IntRecordRef.SetView(TableFilter);
if "Synch. Modified On Filter" <> 0DT then begin
ModifiedOnFieldRef := IntRecordRef.Field("Int. Tbl. Modified On Fld. No.");
ModifiedOnFieldRef.SetFilter('>%1', "Synch. Modified On Filter" - 999);
end;
end;
procedure SetIntRecordRefFilter(var IntRecordRef: RecordRef; TableFilter: Text)
var
ModifiedOnFieldRef: FieldRef;
begin
if TableFilter <> '' then
IntRecordRef.SetView(TableFilter);
if "Synch. Modified On Filter" <> 0DT then begin
ModifiedOnFieldRef := IntRecordRef.Field("Int. Tbl. Modified On Fld. No.");
ModifiedOnFieldRef.SetFilter('>%1', "Synch. Modified On Filter" - 999);
end;
end;
procedure SetRecordRefFilter(var RecordRef: RecordRef)
var
TableFilter: Text;
begin
TableFilter := GetTableFilter();
if TableFilter <> '' then
RecordRef.SetView(TableFilter);
end;
procedure CopyModifiedOnFilters(FromIntegrationTableMapping: Record "Integration Table Mapping")
begin
"Synch. Modified On Filter" := FromIntegrationTableMapping."Synch. Modified On Filter";
"Synch. Int. Tbl. Mod. On Fltr." := FromIntegrationTableMapping."Synch. Int. Tbl. Mod. On Fltr.";
Modify();
end;
[Scope('Cloud')]
procedure CreateRecord(MappingName: Code[20]; TableNo: Integer; IntegrationTableNo: Integer; IntegrationTableUIDFieldNo: Integer; IntegrationTableModifiedFieldNo: Integer; TableConfigTemplateCode: Code[10]; IntegrationTableConfigTemplateCode: Code[10]; SynchOnlyCoupledRecords: Boolean; DirectionArg: Option; Prefix: Text[30])
var
IntegrationTableMapping: Record "Integration Table Mapping";
CDSIntegrationMgt: Codeunit "CDS Integration Mgt.";
UncoupleCodeunitId: Integer;
CouplingCodeunitId: Integer;
begin
if DirectionArg in [IntegrationTableMapping.Direction::ToIntegrationTable, IntegrationTableMapping.Direction::Bidirectional] then
if CDSIntegrationMgt.HasCompanyIdField(IntegrationTableNo) then
UncoupleCodeunitId := Codeunit::"CDS Int. Table Uncouple";
CouplingCodeunitId := Codeunit::"CDS Int. Table Couple";
CreateRecord(MappingName, TableNo, IntegrationTableNo, IntegrationTableUIDFieldNo, IntegrationTableModifiedFieldNo, TableConfigTemplateCode, IntegrationTableConfigTemplateCode, SynchOnlyCoupledRecords, DirectionArg, Prefix, Codeunit::"CRM Integration Table Synch.", UncoupleCodeunitId, CouplingCodeunitId);
end;
[Scope('Cloud')]
procedure CreateRecord(MappingName: Code[20]; TableNo: Integer; IntegrationTableNo: Integer; IntegrationTableUIDFieldNo: Integer; IntegrationTableModifiedFieldNo: Integer; TableConfigTemplateCode: Code[10]; IntegrationTableConfigTemplateCode: Code[10]; SynchOnlyCoupledRecords: Boolean; DirectionArg: Option; Prefix: Text[30]; SynchCodeunitId: Integer; UncoupleCodeunitId: Integer)
var
Field: Record Field;
begin
if Get(MappingName) then
Delete(true);
Init();
Name := MappingName;
"Table ID" := TableNo;
"Integration Table ID" := IntegrationTableNo;
"Synch. Codeunit ID" := SynchCodeunitId;
"Uncouple Codeunit ID" := UncoupleCodeunitId;
Validate("Integration Table UID Fld. No.", IntegrationTableUIDFieldNo);
"Int. Tbl. Modified On Fld. No." := IntegrationTableModifiedFieldNo;
Direction := DirectionArg;
"Int. Tbl. Caption Prefix" := Prefix;
"Synch. Only Coupled Records" := SynchOnlyCoupledRecords;
if "Int. Table UID Field Type" = Field.Type::Option then
"Coupling Codeunit ID" := Codeunit::"CDS Int. Option Couple"
else
"Coupling Codeunit ID" := Codeunit::"CDS Int. Table Couple";
Insert(true);
if TableConfigTemplateCode <> '' then
CreateTableConfigTemplate(Rec, TableConfigTemplateCode);
if IntegrationTableConfigTemplateCode <> '' then
CreateIntTableConfigTemplate(Rec, IntegrationTableConfigTemplateCode);
end;
[Scope('Cloud')]
procedure CreateRecord(MappingName: Code[20]; TableNo: Integer; IntegrationTableNo: Integer; IntegrationTableUIDFieldNo: Integer; IntegrationTableModifiedFieldNo: Integer; TableConfigTemplateCode: Code[10]; IntegrationTableConfigTemplateCode: Code[10]; SynchOnlyCoupledRecords: Boolean; DirectionArg: Option; Prefix: Text[30]; SynchCodeunitId: Integer; UncoupleCodeunitId: Integer; CouplingCodeunitId: Integer)
begin
if Get(MappingName) then
Delete(true);
Init();
Name := MappingName;
"Table ID" := TableNo;
"Integration Table ID" := IntegrationTableNo;
"Synch. Codeunit ID" := SynchCodeunitId;
"Uncouple Codeunit ID" := UncoupleCodeunitId;
Validate("Integration Table UID Fld. No.", IntegrationTableUIDFieldNo);
"Int. Tbl. Modified On Fld. No." := IntegrationTableModifiedFieldNo;
Direction := DirectionArg;
"Int. Tbl. Caption Prefix" := Prefix;
"Synch. Only Coupled Records" := SynchOnlyCoupledRecords;
"Coupling Codeunit ID" := CouplingCodeunitId;
Insert(true);
if TableConfigTemplateCode <> '' then
CreateTableConfigTemplate(Rec, TableConfigTemplateCode);
if IntegrationTableConfigTemplateCode <> '' then
CreateIntTableConfigTemplate(Rec, IntegrationTableConfigTemplateCode);
end;
procedure SetFullSyncStartAndCommit()
begin
Validate("Full Sync is Running", true);
Modify();
Commit();
Get(Name);
end;
procedure SetFullSyncEndAndCommit()
begin
Validate("Full Sync is Running", false);
Modify();
Commit();
Get(Name);
end;
procedure IsFullSyncAllowed(): Boolean
begin
Get(Name);
if not "Full Sync is Running" then
exit(true);
if not IsSessionActive("Full Sync Session ID") then begin
SetFullSyncEndAndCommit();
exit(true);
end;
if Abs(CurrentDateTime - "Last Full Sync Start DateTime") >= OneDayInMiliseconds() then
exit(true);
exit(false)
end;
internal procedure EnableMultiCompanySynchronization()
var
CRMConnectionSetup: Record "CRM Connection Setup";
CDSCompany: Record "CDS Company";
CDSIntegrationMgt: Codeunit "CDS Integration Mgt.";
CDSIntegrationImpl: Codeunit "CDS Integration Impl.";
CRMSetupDefaults: Codeunit "CRM Setup Defaults";
CRMIntegrationManagement: Codeunit "CRM Integration Management";
CRMProductName: Codeunit "CRM Product Name";
IntegrationRecordRef: RecordRef;
CompanyIdFieldRef: FieldRef;
IsHandled: Boolean;
MessageTxt: Text;
begin
OnEnableMultiCompanySynchronization(Rec, IsHandled);
if (IsHandled) then
exit;
if Rec.Type <> Rec.Type::Dataverse then
exit;
Codeunit.Run(Codeunit::"CRM Integration Management");
if CRMIntegrationManagement.IsCRMIntegrationEnabled() then
if CRMIntegrationManagement.CheckSolutionVersionOutdated() then
if CRMConnectionSetup.Get() then
if GuiAllowed() then
if Confirm(InstallLatestSolutionConfirmLbl) then
CRMConnectionSetup.DeployCRMSolution(true)
else
Error('');
case Rec."Table ID" of
Database::"Sales Header",
Database::Opportunity:
begin
IntegrationRecordRef.Open(Rec."Integration Table ID");
if not CDSIntegrationImpl.FindCompanyIdField(IntegrationRecordRef, CompanyIdFieldRef) then
exit;
if not CDSIntegrationMgt.GetCDSCompany(CDSCompany) then
exit;
if GuiAllowed() then
if not Confirm(StrSubstNo(CompanyFilterStrengthenedQst, IntegrationRecordRef.Caption())) then
Error('');
IntegrationRecordRef.SetView(Rec.GetIntegrationTableFilter());
CompanyIdFieldRef.SetRange(CDSCompany.CompanyId);
Rec.SetIntegrationTableFilter(CRMSetupDefaults.GetTableFilterFromView(Rec."Integration Table ID", IntegrationRecordRef.Caption(), IntegrationRecordRef.GetView()));
MessageTxt := StrSubstNo(CompanyFilterStrengthenedMsg, IntegrationRecordRef.Caption(), CompanyName(), CRMProductName.SHORT());
if Rec.Modify() then
if GuiAllowed() then
if MessageTxt <> '' then
Message(MessageTxt);
end;
else begin
IntegrationRecordRef.Open(Rec."Integration Table ID");
if not CDSIntegrationImpl.FindCompanyIdField(IntegrationRecordRef, CompanyIdFieldRef) then
exit;
if GuiAllowed() then
if not Confirm(StrSubstNo(CompanyFilterRemovedQst, IntegrationRecordRef.Caption())) then
Error('');
IntegrationRecordRef.SetView(Rec.GetIntegrationTableFilter());
CompanyIdFieldRef.SetRange();
Rec.SetIntegrationTableFilter(CRMSetupDefaults.GetTableFilterFromView(Rec."Integration Table ID", IntegrationRecordRef.Caption(), IntegrationRecordRef.GetView()));
if Rec.Modify() then
if GuiAllowed() then
if Rec.Direction = Rec.Direction::FromIntegrationTable then
Message(StrSubstNo(CompanyFilterRemovedShortMsg, IntegrationRecordRef.Caption()))
else
Message(StrSubstNo(CompanyFilterRemovedExtendedMsg, IntegrationRecordRef.Caption()));
end;
end;
end;
internal procedure DisableMultiCompanySynchronization()
var
CDSCompany: Record "CDS Company";
CDSIntegrationMgt: Codeunit "CDS Integration Mgt.";
CDSIntegrationImpl: Codeunit "CDS Integration Impl.";
CRMSetupDefaults: Codeunit "CRM Setup Defaults";
IntegrationRecordRef: RecordRef;
CompanyIdFieldRef: FieldRef;
IsHandled: Boolean;
EmptyGuid: Guid;
begin
OnDisableMultiCompanySynchronization(Rec, IsHandled);
if (IsHandled) then
exit;
if Rec.Type <> Rec.Type::Dataverse then
exit;
Codeunit.Run(Codeunit::"CRM Integration Management");
IntegrationRecordRef.Open(Rec."Integration Table ID");
if not CDSIntegrationImpl.FindCompanyIdField(IntegrationRecordRef, CompanyIdFieldRef) then
exit;
if not CDSIntegrationMgt.GetCDSCompany(CDSCompany) then
exit;
if GuiAllowed() then
if not Confirm(StrSubstNo(CompanyFilterResetToDefaultQst)) then
Error('');
IntegrationRecordRef.SetView(Rec.GetIntegrationTableFilter());
CompanyIdFieldRef.SetFilter(StrSubstno(OrTok, CDSCompany.CompanyId, EmptyGuid));
Rec.SetIntegrationTableFilter(CRMSetupDefaults.GetTableFilterFromView(Rec."Integration Table ID", IntegrationRecordRef.Caption(), IntegrationRecordRef.GetView()));
if Rec.Modify() then
if GuiAllowed() then
Message(CompanyFilterResetMsg);
end;
procedure IsMappingEnabled(RequestedDirection: Option Bidirectional,ToIntegrationTable,FromIntegrationTable): Boolean
var
IntegrationFieldMapping: Record "Integration Field Mapping";
IsHandled, Result : Boolean;
begin
OnBeforeIsMappingEnabled(RequestedDirection, Result, IsHandled);
if IsHandled then
exit(Result);
if Rec.Direction <> RequestedDirection then
case RequestedDirection of
RequestedDirection::Bidirectional:
exit(false);
RequestedDirection::FromIntegrationTable:
if Rec.Direction = Rec.Direction::ToIntegrationTable then
exit(false);
RequestedDirection::ToIntegrationTable:
if Rec.Direction = Rec.Direction::FromIntegrationTable then
exit(false);
end;
IntegrationFieldMapping.SetRange("Integration Table Mapping Name", Rec.Name);
case RequestedDirection of
RequestedDirection::Bidirectional:
IntegrationFieldMapping.SetRange(Direction, IntegrationFieldMapping.Direction::Bidirectional);
RequestedDirection::FromIntegrationTable:
IntegrationFieldMapping.SetFilter(Direction, '%1|%2', IntegrationFieldMapping.Direction::FromIntegrationTable, IntegrationFieldMapping.Direction::Bidirectional);
RequestedDirection::ToIntegrationTable:
IntegrationFieldMapping.SetFilter(Direction, '%1|%2', IntegrationFieldMapping.Direction::ToIntegrationTable, IntegrationFieldMapping.Direction::Bidirectional);
end;
IntegrationFieldMapping.SetRange(Status, IntegrationFieldMapping.Status::Enabled);
exit(not IntegrationFieldMapping.IsEmpty());
end;
procedure IsFieldMappingEnabled(FieldNo: Integer; IntegrationTableFieldNo: Integer; RequestedDirection: Option Bidirectional,ToIntegrationTable,FromIntegrationTable): Boolean
var
IntegrationFieldMapping: Record "Integration Field Mapping";
IsHandled, Result : Boolean;
begin
OnBeforeIsFieldMappingEnabled(FieldNo, IntegrationTableFieldNo, RequestedDirection, Result, IsHandled);
if IsHandled then
exit(Result);
if not IsMappingEnabled(RequestedDirection) then
exit(false);
IntegrationFieldMapping.SetRange("Integration Table Mapping Name", Rec.Name);
IntegrationFieldMapping.SetRange("Field No.", FieldNo);
IntegrationFieldMapping.SetRange("Integration Table Field No.", IntegrationTableFieldNo);
case RequestedDirection of
RequestedDirection::Bidirectional:
IntegrationFieldMapping.SetRange(Direction, IntegrationFieldMapping.Direction::Bidirectional);
RequestedDirection::FromIntegrationTable:
IntegrationFieldMapping.SetFilter(Direction, '%1|%2', IntegrationFieldMapping.Direction::FromIntegrationTable, IntegrationFieldMapping.Direction::Bidirectional);
RequestedDirection::ToIntegrationTable:
IntegrationFieldMapping.SetFilter(Direction, '%1|%2', IntegrationFieldMapping.Direction::ToIntegrationTable, IntegrationFieldMapping.Direction::Bidirectional);
end;
IntegrationFieldMapping.SetRange(Status, IntegrationFieldMapping.Status::Enabled);
exit(not IntegrationFieldMapping.IsEmpty());
end;
local procedure OneDayInMiliseconds(): Integer
begin
exit(24 * 60 * 60 * 1000)
end;
procedure GetTableConfigTemplates(IntegrationTableMappingName: Code[20]): Text
var
TableConfigTemplate: Record "Table Config Template";
begin
TableConfigTemplate.SetRange("Integration Table Mapping Name", IntegrationTableMappingName);
case TableConfigTemplate.Count() of
0:
exit('');
1:
begin
TableConfigTemplate.FindFirst();
exit(TableConfigTemplate."Table Config Template Code");
end;
else
exit(StrSubstNo(MultipleConfigTemplatesLbl, Format(TableConfigTemplate.Count())));
end;
end;
procedure GetIntTableConfigTemplates(IntegrationTableMappingName: Code[20]): Text
var
IntegrationTableConfigTemplate: Record "Int. Table Config Template";
begin
IntegrationTableConfigTemplate.SetRange("Integration Table Mapping Name", IntegrationTableMappingName);
case IntegrationTableConfigTemplate.Count() of
0:
exit('');
1:
begin
IntegrationTableConfigTemplate.FindFirst();
exit(IntegrationTableConfigTemplate."Int. Tbl. Config Template Code");
end;
else
exit(StrSubstNo(MultipleConfigTemplatesLbl, Format(IntegrationTableConfigTemplate.Count())));
end;
end;
local procedure CreateTableConfigTemplate(IntegrationTableMapping: Record "Integration Table Mapping"; TableConfigTemplateCode: Code[10])
var
TableConfigTemplate: Record "Table Config Template";
begin
TableConfigTemplate."Integration Table Mapping Name" := IntegrationTableMapping.Name;
TableConfigTemplate.Validate("Table ID", IntegrationTableMapping."Table ID");
TableConfigTemplate.Validate("Integration Table ID", IntegrationTableMapping."Integration Table ID");
TableConfigTemplate.Validate("Table Config Template Code", TableConfigTemplateCode);
TableConfigTemplate.Insert();
end;
local procedure CreateIntTableConfigTemplate(IntegrationTableMapping: Record "Integration Table Mapping"; IntegrationTableConfigTemplateCode: Code[10])
var
IntTableConfigTemplate: Record "Int. Table Config Template";
begin
IntTableConfigTemplate."Integration Table Mapping Name" := IntegrationTableMapping.Name;
IntTableConfigTemplate.Validate("Integration Table ID", IntegrationTableMapping."Integration Table ID");
IntTableConfigTemplate.Validate("Table ID", IntegrationTableMapping."Table ID");
IntTableConfigTemplate.Validate("Int. Tbl. Config Template Code", IntegrationTableConfigTemplateCode);
IntTableConfigTemplate.Insert();
end;
[IntegrationEvent(false, false)]
internal procedure OnIsCreateNewInCaseOfNoMatchControlVisible(var IntegrationTableMapping: Record "Integration Table Mapping"; var CreateNewInCaseOfNoMatchControlVisible: Boolean; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnSynchronizeNow(var IntegrationTableMapping: Record "Integration Table Mapping"; ResetLastSynchModifiedOnDateTime: Boolean; ResetSynchonizationTimestampOnRecords: Boolean; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
internal procedure OnEnableMultiCompanySynchronization(var IntegrationTableMapping: Record "Integration Table Mapping"; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
internal procedure OnDisableMultiCompanySynchronization(var IntegrationTableMapping: Record "Integration Table Mapping"; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeIsMappingEnabled(RequestedDirection: Option Bidirectional,ToIntegrationTable,FromIntegrationTable; var Result: Boolean; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeIsFieldMappingEnabled(FieldNo: Integer; IntegrationTableFieldNo: Integer; RequestedDirection: Option Bidirectional,ToIntegrationTable,FromIntegrationTable; var Result: Boolean; var IsHandled: Boolean)
begin
end;
local procedure CheckDeletionConflictResolutionStrategy()
begin
if Rec."Deletion-Conflict Resolution" = Rec."Deletion-Conflict Resolution"::"Remove Coupling" then
if not Rec."Synch. Only Coupled Records" then
if GuiAllowed() then
if not Confirm(RemoveCouplingStrategyQst) then
Error('');
end;
}