Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8552212
[Bug] Disable customer asset conversion for CRM products during synch…
tomasevicst Sep 5, 2026
84a9998
[Bug] Remove obsolete Convert to Customer Asset flag and update synch…
tomasevicst Sep 5, 2026
482d353
[Bug] Update obsolete service item synchronization logic and enhance …
tomasevicst Sep 6, 2026
a5191e7
[Bug] Remove obsolete IgnoreServiceItemsByConvertToCustomerAssetFlag …
tomasevicst Sep 6, 2026
e3d1c2a
[Bug] Refactor IgnoreServiceItemsByConvertToCustomerAssetFlag procedu…
tomasevicst Sep 7, 2026
1323d7b
Merge remote-tracking branch 'origin/main' into bugs/649195_FS_Duplic…
tomasevicst Sep 7, 2026
2378ecc
[Bug] Update IgnoreServiceItemsByConvertToCustomerAssetFlag procedure…
tomasevicst Sep 7, 2026
225f4dd
[Bug] Update IgnoreServiceItemsByConvertToCustomerAssetFlag procedure…
tomasevicst Sep 7, 2026
1d615d8
[Bug] Enhance customer asset conversion logic and add tests for modif…
tomasevicst Sep 8, 2026
be17c20
[Bug] Remove obsolete conditional compilation for service item synchr…
tomasevicst Sep 8, 2026
dcf5600
[Bug] Enhance DisableCustomerAssetConversion procedure to handle exis…
tomasevicst Sep 8, 2026
326579a
[Bug] Update OnAfterTransferRecordFields procedure to include Destina…
tomasevicst Sep 9, 2026
f0b6ce4
[Bug] Fix logic in customer asset conversion to correctly check Desti…
tomasevicst Sep 9, 2026
bb07946
[Bug] Add handling for existing CRM products in customer asset conver…
tomasevicst Sep 9, 2026
7acb788
[Bug] Refactor customer asset conversion logic to correctly handle ex…
tomasevicst Sep 9, 2026
b6614f9
[Bug] Simplify CRM product handling in customer asset conversion logi…
tomasevicst Sep 10, 2026
ab1b3a7
[Bug] Update OnAfterTransferRecordFields event subscriber to disable …
tomasevicst Sep 10, 2026
2b915d6
Merge remote-tracking branch 'origin/main' into bugs/649195_FS_Duplic…
tomasevicst Sep 11, 2026
890d0ee
Enhance FS Int. Table Subscriber event subscription and update integr…
tomasevicst Sep 11, 2026
266c0b8
Merge branch 'main' into bugs/649195_FS_Duplicate_Field_Service_Custo…
tomasevicst Sep 17, 2026
bc0d664
Add handling for existing CRM products in customer asset conversion
tomasevicst Sep 17, 2026
1d1420e
Refactor customer asset conversion logic to utilize item management s…
tomasevicst Sep 18, 2026
e894abd
Refactor customer asset conversion procedures by removing redundant C…
tomasevicst Sep 18, 2026
3e4e3c2
Merge branch 'main' into bugs/649195_FS_Duplicate_Field_Service_Custo…
tomasevicst Sep 18, 2026
4d32491
Remove obsolete documentation and workspace files for Sales Order Agent
tomasevicst Sep 18, 2026
b53f402
Remove unused using directive for D365Sales in FS Integration Test Li…
tomasevicst Sep 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ codeunit 6610 "FS Int. Table Subscriber"
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Integration Rec. Synch. Invoke", 'OnAfterTransferRecordFields', '', true, false)]
local procedure OnAfterTransferRecordFields(SourceRecordRef: RecordRef; var DestinationRecordRef: RecordRef; var AdditionalFieldsWereModified: Boolean)
local procedure OnAfterTransferRecordFields(SourceRecordRef: RecordRef; var DestinationRecordRef: RecordRef; var AdditionalFieldsWereModified: Boolean; DestinationIsInserted: Boolean)
var
FSConnectionSetup: Record "FS Connection Setup";
FSWorkOrderProduct: Record "FS Work Order Product";
Expand Down Expand Up @@ -358,6 +358,25 @@ codeunit 6610 "FS Int. Table Subscriber"
end;
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Integration Record Synch.", 'OnBeforeIsFieldModified', '', true, false)]
local procedure OnBeforeIsFieldModified(var SourceFieldRef: FieldRef; var DestinationFieldRef: FieldRef; var Result: Boolean; var IsHandled: Boolean)
var
Item: Record Item;
CRMProduct: Record "CRM Product";
SourceRecordRef: RecordRef;
DestinationRecordRef: RecordRef;
begin
if not IsItemCouplingToCustomerAssetConversion(SourceFieldRef, DestinationFieldRef) then
exit;

SourceRecordRef := SourceFieldRef.Record();
SourceRecordRef.SetTable(Item);
DestinationRecordRef := DestinationFieldRef.Record();
DestinationRecordRef.SetTable(CRMProduct);
Result := CRMProduct.ConvertToCustomerAsset <> GetCustomerAssetConversion(Item."Coupled to Dataverse");
IsHandled := true;
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Integration Record Synch.", 'OnTransferFieldData', '', true, false)]
local procedure OnTransferFieldData(SourceFieldRef: FieldRef; DestinationFieldRef: FieldRef; var NewValue: Variant; var IsValueFound: Boolean; var NeedsConversion: Boolean)
var
Expand All @@ -371,6 +390,7 @@ codeunit 6610 "FS Int. Table Subscriber"
ServiceHeader: Record "Service Header";
ServiceLine: Record "Service Line";
ItemUnitOfMeasure: Record "Item Unit of Measure";
Item: Record Item;
SourceRecordRef: RecordRef;
DestinationRecordRef: RecordRef;
NAVItemUomRecordId: RecordId;
Expand All @@ -392,6 +412,15 @@ codeunit 6610 "FS Int. Table Subscriber"
if SourceFieldRef.Record().Number() = DestinationFieldRef.Record().Number() then
exit;

if IsItemCouplingToCustomerAssetConversion(SourceFieldRef, DestinationFieldRef) then begin
SourceRecordRef := SourceFieldRef.Record();
SourceRecordRef.SetTable(Item);
NewValue := GetCustomerAssetConversion(Item."Coupled to Dataverse");
IsValueFound := true;
NeedsConversion := false;
exit;
end;

if (SourceFieldRef.Record().Number = Database::"Service Header") and
(DestinationFieldRef.Record().Number = Database::"FS Work Order") then
case DestinationFieldRef.Name() of
Expand Down Expand Up @@ -672,6 +701,23 @@ codeunit 6610 "FS Int. Table Subscriber"
exit(MaxQuantity);
end;

local procedure IsItemCouplingToCustomerAssetConversion(SourceFieldRef: FieldRef; DestinationFieldRef: FieldRef): Boolean
var
Item: Record Item;
CRMProduct: Record "CRM Product";
begin
exit(
(SourceFieldRef.Record().Number() = Database::Item) and
(SourceFieldRef.Number() = Item.FieldNo("Coupled to Dataverse")) and
(DestinationFieldRef.Record().Number() = Database::"CRM Product") and
(DestinationFieldRef.Number() = CRMProduct.FieldNo(ConvertToCustomerAsset)));
end;

internal procedure GetCustomerAssetConversion(ItemIsManaged: Boolean): Boolean
begin
exit(not ItemIsManaged);
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"CRM Int. Table. Subscriber", 'OnFindNewValueForCoupledRecordPK', '', true, false)]
local procedure OnFindNewValueForCoupledRecordPK(IntegrationTableMapping: Record "Integration Table Mapping"; SourceFieldRef: FieldRef; DestinationFieldRef: FieldRef; var NewValue: Variant; var IsValueFound: Boolean)
var
Expand Down Expand Up @@ -1444,7 +1490,7 @@ codeunit 6610 "FS Int. Table Subscriber"
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"CRM Setup Defaults", 'OnResetItemProductMappingOnAfterInsertFieldsMapping', '', false, false)]
local procedure AddFieldServiceProductTypeFieldMapping(var Sender: Codeunit "CRM Setup Defaults"; IntegrationTableMappingName: Code[20])
local procedure AddFieldServiceProductMappings(var Sender: Codeunit "CRM Setup Defaults"; IntegrationTableMappingName: Code[20])
var
FSConnectionSetup: Record "FS Connection Setup";
Item: Record Item;
Expand All @@ -1461,6 +1507,14 @@ codeunit 6610 "FS Int. Table Subscriber"
CRMProduct.FieldNo(FieldServiceProductType),
IntegrationFieldMapping.Direction::ToIntegrationTable,
'', false, false);

// Coupled Business Central items are managed by Field Service customer assets.
Sender.InsertIntegrationFieldMapping(
IntegrationTableMappingName,
Item.FieldNo("Coupled to Dataverse"),
CRMProduct.FieldNo(ConvertToCustomerAsset),
IntegrationFieldMapping.Direction::ToIntegrationTable,
'', false, false);
end;

local procedure UpdateCorrelatedJobJournalLine(var SourceRecordRef: RecordRef; var DestinationRecordRef: RecordRef)
Expand Down Expand Up @@ -2518,8 +2572,6 @@ codeunit 6610 "FS Int. Table Subscriber"
IgnoreArchievedServiceOrdersOnQueryPostFilterIgnoreRecord(SourceRecordRef, IgnoreRecord);
Database::"FS Work Order":
IgnoreArchievedCRMWorkOrdersOnQueryPostFilterIgnoreRecord(SourceRecordRef, IgnoreRecord);
Database::"Service Item":
IgnoreServiceItemsByConvertToCustomerAssetFlag(SourceRecordRef, IgnoreRecord);
end;

if FSConnectionSetup.IsEnabled() then
Expand Down Expand Up @@ -2685,6 +2737,8 @@ codeunit 6610 "FS Int. Table Subscriber"
IgnoreRecord := true;
end;

#pragma warning disable AS0105
[Obsolete('Remove calls to this procedure. Service items are always synchronized to Field Service customer assets; item-product synchronization disables customer asset conversion.', '30.0')]
internal procedure IgnoreServiceItemsByConvertToCustomerAssetFlag(SourceRecordRef: RecordRef; var IgnoreRecord: Boolean)
var
FSConnectionSetup: Record "FS Connection Setup";
Expand Down Expand Up @@ -2718,6 +2772,7 @@ codeunit 6610 "FS Int. Table Subscriber"
if not CRMProduct.ConvertToCustomerAsset then
IgnoreRecord := true;
end;
#pragma warning restore AS0105

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Integration Table Synch.", 'OnAfterInitSynchJob', '', true, true)]
local procedure LogTelemetryOnAfterInitSynchJob(ConnectionType: TableConnectionType; IntegrationTableID: Integer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ codeunit 139205 "FS Integration Test Library"
FSIntTableSubscriber.UpdateQuantities(FSBookableResourceBooking, ServiceLine);
end;

procedure GetCustomerAssetConversion(ItemIsManaged: Boolean): Boolean
var
FSIntTableSubscriber: Codeunit "FS Int. Table Subscriber";
begin
exit(FSIntTableSubscriber.GetCustomerAssetConversion(ItemIsManaged));
end;

procedure IgnorePostedJobJournalLinesOnQueryPostFilterIgnoreRecord(SourceRecordRef: RecordRef; var IgnoreRecord: Boolean)
var
FSIntTableSubscriber: Codeunit "FS Int. Table Subscriber";
Expand All @@ -79,12 +86,17 @@ codeunit 139205 "FS Integration Test Library"
FSIntTableSubscriber.IgnoreArchievedCRMWorkOrdersOnQueryPostFilterIgnoreRecord(SourceRecordRef, IgnoreRecord);
end;

/// <summary>
/// Retained for compatibility. Service items are now always synchronized to Field Service customer assets, so this procedure leaves the synchronization decision unchanged.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Breaking\ Changes}$

The obsolete public test-library procedure IgnoreServiceItemsByConvertToCustomerAssetFlag (Microsoft.TestLibraries.DynamicsFieldService, FSIntegrationTestLibrary.Codeunit.al) is correctly marked [Obsolete('...', '30.0')], but its body was replaced with an empty no-op instead of continuing to forward to the previous implementation. During the deprecation window, existing external callers who still invoke this public procedure expecting IgnoreRecord to be set now silently receive unchanged behavior. Guidance on deprecating public members with the Obsolete lifecycle recommends preserving the prior behavior (e.g., keep forwarding to the codeunit's still-present implementation, or otherwise retain the previous decision) until the procedure is actually removed in a later release, rather than emptying it immediately upon obsoletion.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.41.6

/// </summary>
/// <param name="SourceRecordRef">A reference to the service item to evaluate.</param>
/// <param name="IgnoreRecord">The existing synchronization decision, which is left unchanged.</param>
#pragma warning disable AS0105
[Obsolete('Remove calls to this procedure. Service items are always synchronized to Field Service customer assets; item-product synchronization disables customer asset conversion.', '30.0')]
Comment thread
tomasevicst marked this conversation as resolved.
Comment thread
tomasevicst marked this conversation as resolved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Upgrade}$

The public test-library procedure IgnoreServiceItemsByConvertToCustomerAssetFlag is newly marked [Obsolete(...,'30.0')], but its body was simultaneously replaced with a no-op instead of continuing to delegate to the prior logic. Any dependent app or test still calling this procedure during the deprecation window (before 30.0 removal) will silently stop having IgnoreRecord evaluated/set, changing observable runtime behavior while the symbol still compiles. Staged-obsoletion guidance expects the procedure to keep working during the deprecation window and only become an empty/removed stub at or after the tagged removal version.

Suggested fix (apply manually — could not be anchored as a one-click suggestion):

    procedure IgnoreServiceItemsByConvertToCustomerAssetFlag(SourceRecordRef: RecordRef; var IgnoreRecord: Boolean)
    var
        FSIntTableSubscriber: Codeunit "FS Int. Table Subscriber";
    begin
        FSIntTableSubscriber.IgnoreServiceItemsByConvertToCustomerAssetFlag(SourceRecordRef, IgnoreRecord);
    end;

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.39.6

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Breaking\ Changes}$

The public procedure IgnoreServiceItemsByConvertToCustomerAssetFlag on the FS Integration Test Library codeunit was kept and marked [Obsolete(...,'30.0')], but its implementation was emptied instead of preserved. Emptying the body changes the procedure's observable behavior (IgnoreRecord is now always left unchanged) immediately for any remaining caller, rather than preserving prior behavior through the deprecation window until the tag's removal version. Prefer keeping the forwarding call to FSIntTableSubscriber.IgnoreServiceItemsByConvertToCustomerAssetFlag until the obsolete procedure is actually removed.

Suggested fix (apply manually — could not be anchored as a one-click suggestion):

    procedure IgnoreServiceItemsByConvertToCustomerAssetFlag(SourceRecordRef: RecordRef; var IgnoreRecord: Boolean)
    var
        FSIntTableSubscriber: Codeunit "FS Int. Table Subscriber";
    begin
        FSIntTableSubscriber.IgnoreServiceItemsByConvertToCustomerAssetFlag(SourceRecordRef, IgnoreRecord);
    end;

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.40.6

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟠\ High\ Severity\ —\ Upgrade}$

FS Integration Test Library.IgnoreServiceItemsByConvertToCustomerAssetFlag is marked [Obsolete] (pending, target version '30.0') but its body was stripped to a no-op instead of continuing to forward to FS Int. Table Subscriber.IgnoreServiceItemsByConvertToCustomerAssetFlag (which still has its full working implementation, also marked Obsolete-pending but not removed). During the obsolete-pending window a symbol must keep its previous observable behavior so existing callers are not silently broken before their deprecation window elapses. Any remaining caller of the test-library helper now always leaves IgnoreRecord unchanged instead of getting the real computed result, which is a silent behavioral regression, not just a documentation change.

Suggested fix (apply manually — could not be anchored as a one-click suggestion):

    procedure IgnoreServiceItemsByConvertToCustomerAssetFlag(SourceRecordRef: RecordRef; var IgnoreRecord: Boolean)
    var
        FSIntTableSubscriber: Codeunit "FS Int. Table Subscriber";
    begin
        FSIntTableSubscriber.IgnoreServiceItemsByConvertToCustomerAssetFlag(SourceRecordRef, IgnoreRecord);
    end;

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.41.6

procedure IgnoreServiceItemsByConvertToCustomerAssetFlag(SourceRecordRef: RecordRef; var IgnoreRecord: Boolean)
var
FSIntTableSubscriber: Codeunit "FS Int. Table Subscriber";
begin
FSIntTableSubscriber.IgnoreServiceItemsByConvertToCustomerAssetFlag(SourceRecordRef, IgnoreRecord);
end;
#pragma warning restore AS0105

procedure MarkArchivedServiceOrder(ServiceHeader: Record "Service Header")
var
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ using Microsoft.Purchases.Vendor;
using Microsoft.Sales.Customer;
using Microsoft.Service.Archive;
using Microsoft.Service.Document;
using Microsoft.Service.Item;
using Microsoft.Service.Setup;
using Microsoft.Service.Test;
using Microsoft.TestLibraries.DynamicsFieldService;
Expand Down Expand Up @@ -1578,109 +1577,79 @@ codeunit 139204 "FS Integration Test"
end;

[Test]
procedure IgnoreServiceItemWhenConvertToCustomerAssetIsFalse()
[TransactionModel(TransactionModel::AutoCommit)]
procedure ItemSynchronizationDisablesCustomerAssetConversion()
Comment thread
tomasevicst marked this conversation as resolved.
var
Item: Record Item;
TempServiceItem: Record "Service Item" temporary;
CRMProduct: Record "CRM Product";
CRMIntegrationRecord: Record "CRM Integration Record";
RecordRef: RecordRef;
IgnoreRecord: Boolean;
ProductId: Guid;
begin
// [FEATURE] [Service Item Mapping]
// [SCENARIO] Service Item is skipped when linked CRM Product has Convert to Customer Asset = No.
Initialize();
InitSetup(true, '');

Item.Get(CreateItem());
TempServiceItem."Item No." := Item."No.";
RecordRef.GetTable(TempServiceItem);

ProductId := CreateGuid();
CRMProduct.ProductId := ProductId;
CRMProduct.ConvertToCustomerAsset := false;
CRMProduct.Insert(false);

CRMIntegrationRecord.CoupleCRMIDToRecordID(ProductId, Item.RecordId());

FSIntegrationTestLibrary.IgnoreServiceItemsByConvertToCustomerAssetFlag(RecordRef, IgnoreRecord);

Assert.IsTrue(IgnoreRecord, 'Service Item should be ignored when Convert to Customer Asset is false.');
end;

[Test]
procedure DoNotIgnoreServiceItemWhenConvertToCustomerAssetIsTrue()
var
Comment thread
tomasevicst marked this conversation as resolved.
Item: Record Item;
TempServiceItem: Record "Service Item" temporary;
CRMProduct: Record "CRM Product";
CRMIntegrationRecord: Record "CRM Integration Record";
RecordRef: RecordRef;
IgnoreRecord: Boolean;
ProductId: Guid;
IntegrationTableMapping: Record "Integration Table Mapping";
CRMIntegrationTableSynch: Codeunit "CRM Integration Table Synch.";
CRMSetupDefaults: Codeunit "CRM Setup Defaults";
begin
// [FEATURE] [Service Item Mapping]
// [SCENARIO] Service Item is not skipped when linked CRM Product has Convert to Customer Asset = Yes.
// [FEATURE] [Item-Product Mapping]
// [SCENARIO] Synchronizing an item disables native Field Service customer asset creation.
Initialize();
LibraryCRMIntegration.CreateCRMConnectionSetup('', '@@test@@', true);
InitSetup(true, '');

Item.Get(CreateItem());
TempServiceItem."Item No." := Item."No.";
RecordRef.GetTable(TempServiceItem);

ProductId := CreateGuid();
CRMProduct.ProductId := ProductId;
// [GIVEN] A coupled item and product where Convert to Customer Asset is Yes.
CRMSetupDefaults.ResetItemProductMapping('ITEM-PRODUCT', false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Testing}$

The new Item-to-CRM Product sync test (ItemSynchronizationDisablesCustomerAssetConversion) only exercises an already-coupled, pre-existing product via CreateCoupledItemAndProduct, so it never covers the new DestinationIsInserted = true branch added in OnAfterTransferRecordFields (the conditional LoadFields(ConvertToCustomerAsset) path taken when a CRM Product is newly created from an item). Add a test case that synchronizes an uncoupled item so a new CRM Product is inserted, and assert the resulting ConvertToCustomerAsset is correctly initialized/disabled.

Agent judgement — not directly backed by a BCQuality knowledge article.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.41.6

LibraryCRMIntegration.CreateCoupledItemAndProduct(Item, CRMProduct);
CRMProduct.ConvertToCustomerAsset := true;
CRMProduct.Insert(false);
CRMProduct.Modify();

CRMIntegrationRecord.CoupleCRMIDToRecordID(ProductId, Item.RecordId());
IntegrationTableMapping.Get('ITEM-PRODUCT');
Item.CalcFields("Coupled to Dataverse");
Assert.IsTrue(Item."Coupled to Dataverse", 'The item should be identified as managed by its Dataverse coupling.');

FSIntegrationTestLibrary.IgnoreServiceItemsByConvertToCustomerAssetFlag(RecordRef, IgnoreRecord);
// [WHEN] The item is synchronized to the Field Service product.
CRMIntegrationTableSynch.SynchRecord(IntegrationTableMapping, Item.RecordId(), true, false);

Assert.IsFalse(IgnoreRecord, 'Service Item should not be ignored when Convert to Customer Asset is true.');
// [THEN] Native Field Service customer asset creation is disabled.
CRMProduct.Get(CRMProduct.ProductId);
Assert.IsFalse(CRMProduct.ConvertToCustomerAsset, 'Convert to Customer Asset should be disabled.');
end;

[Test]
procedure DoNotIgnoreServiceItemWhenItemNoIsBlank()
var
TempServiceItem: Record "Service Item" temporary;
RecordRef: RecordRef;
IgnoreRecord: Boolean;
[TransactionModel(TransactionModel::AutoRollback)]
procedure CustomerAssetConversionReflectsItemManagement()
begin
// [FEATURE] [Service Item Mapping]
// [SCENARIO] Service Item with blank Item No. is not skipped by this filter.
Initialize();
InitSetup(true, '');

TempServiceItem."Item No." := '';
RecordRef.GetTable(TempServiceItem);
// [FEATURE] [Item-Product Mapping]
// [SCENARIO] Customer asset conversion is disabled only for items managed through synchronization.

FSIntegrationTestLibrary.IgnoreServiceItemsByConvertToCustomerAssetFlag(RecordRef, IgnoreRecord);
// [WHEN] An item is not managed through synchronization.
// [THEN] Native Field Service customer asset conversion remains enabled.
Assert.IsTrue(FSIntegrationTestLibrary.GetCustomerAssetConversion(false), 'An unmanaged item should allow customer asset conversion.');

Assert.IsFalse(IgnoreRecord, 'Service Item with blank Item No. should not be ignored by this filter.');
// [WHEN] An item is managed through synchronization.
// [THEN] Native Field Service customer asset conversion is disabled.
Assert.IsFalse(FSIntegrationTestLibrary.GetCustomerAssetConversion(true), 'A managed item should disable customer asset conversion.');
end;

[Test]
procedure DoNotIgnoreServiceItemWhenItemIsNotCoupled()
[TransactionModel(TransactionModel::AutoCommit)]
Comment thread
tomasevicst marked this conversation as resolved.
procedure ItemProductMappingDisablesCustomerAssetConversion()
var
Item: Record Item;
TempServiceItem: Record "Service Item" temporary;
RecordRef: RecordRef;
IgnoreRecord: Boolean;
CRMProduct: Record "CRM Product";
IntegrationFieldMapping: Record "Integration Field Mapping";
CRMSetupDefaults: Codeunit "CRM Setup Defaults";
begin
// [FEATURE] [Service Item Mapping]
// [SCENARIO] Service Item with uncoupled Item is not skipped by this filter.
// [FEATURE] [Item-Product Mapping]
// [SCENARIO] The item-product mapping derives native Field Service customer asset creation from item management.
Initialize();
InitSetup(true, '');

Item.Get(CreateItem());
TempServiceItem."Item No." := Item."No.";
RecordRef.GetTable(TempServiceItem);

FSIntegrationTestLibrary.IgnoreServiceItemsByConvertToCustomerAssetFlag(RecordRef, IgnoreRecord);
// [WHEN] The default item-product mapping is reset.
CRMSetupDefaults.ResetItemProductMapping('ITEM-PRODUCT', false);

Assert.IsFalse(IgnoreRecord, 'Service Item with uncoupled Item should not be ignored by this filter.');
// [THEN] Convert to Customer Asset is mapped from the item's Dataverse coupling state in the outbound direction.
IntegrationFieldMapping.SetRange("Integration Table Mapping Name", 'ITEM-PRODUCT');
IntegrationFieldMapping.SetRange("Integration Table Field No.", CRMProduct.FieldNo(ConvertToCustomerAsset));
Assert.IsTrue(IntegrationFieldMapping.FindFirst(), 'The Convert to Customer Asset mapping should exist.');
Assert.AreEqual(Item.FieldNo("Coupled to Dataverse"), IntegrationFieldMapping."Field No.", 'The mapping should use the item coupling state.');
Assert.AreEqual(IntegrationFieldMapping.Direction::ToIntegrationTable, IntegrationFieldMapping.Direction, 'The mapping should be outbound.');
Assert.AreEqual('', IntegrationFieldMapping."Constant Value", 'The mapping should not use a constant value.');
end;

local procedure Initialize()
Expand Down
Loading