Skip to content

[FS] Prevent duplicate Field Service customer assets during item synchronization - #11094

Open
tomasevicst wants to merge 39 commits into
mainfrom
bugs/649195_FS_Duplicate_Field_Service_Customer_Asset_Created
Open

tomasevicst wants to merge 39 commits into
mainfrom
bugs/649195_FS_Duplicate_Field_Service_Customer_Asset_Created

Conversation

@tomasevicst

@tomasevicst tomasevicst commented Sep 5, 2026 •

Copy link
Copy Markdown
Contributor

What & why

Business Central and Field Service could both create a Customer Asset for the same item, resulting in duplicates when a Work Order was completed.

This change keeps Business Central as the source for Customer Asset creation by:

  • Setting Convert to Customer Asset to No for Products synchronized from BC Items.
  • Adding the rule to the default Item-Product mapping.
  • Removing the Product flag as a filter for Service Item synchronization.
  • Adding tests for runtime enforcement and mapping configuration.

Linked work

Fixes AB#649195

How I validated this

  • I read the full diff and it contains only changes I intended.
  • I built the affected app(s) locally with no new analyzer warnings.
  • I ran the change in Business Central and confirmed it behaves as expected.
  • I added or updated tests for the new behavior, or explained below why none are needed.

What I tested and the outcome (required — be specific: scenarios, commands, screenshots for UI changes)

Risk & compatibility

Risk is low and limited to coupled Field Service Products. Their Convert to Customer Asset value is overwritten to No during Item synchronization, preventing native Field Service asset creation.

Uncoupled Field Service Products are unaffected. No schema or public API changes are introduced. Existing configurations are covered by runtime enforcement, while reset or newly created mappings receive the constant outbound mapping.

@tomasevicst
tomasevicst requested a review from a team September 5, 2026 09:44
@tomasevicst
tomasevicst requested a review from a team as a code owner September 5, 2026 09:45
@github-actions github-actions Bot added AL: Apps (W1) Add-on apps for W1 Ownership: Needs Review Ownership is Other, low confidence, or needs manual correction Team: Other GitHub request for other area than SCM, Finance or Integration labels Sep 5, 2026
@github-actions github-actions Bot added this to the Version 30.0 milestone Sep 5, 2026
@tomasevicst tomasevicst added the Team: SCM GitHub request for SCM area label Sep 5, 2026
@github-actions github-actions Bot removed the Team: SCM GitHub request for SCM area label Sep 5, 2026
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

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

The removed IgnoreServiceItem* tests, and the new ItemSynchronizationDisablesCustomerAssetConversion test, both call the helper procedure directly rather than exercising the actual dispatch path. Critically, the new 'Item-CRM Product' case added to OnBeforeTransferFieldData (which does DestinationRecordRef.SetTable(CRMProduct) / DisableCustomerAssetConversion(...) / DestinationRecordRef.GetTable(CRMProduct)) is never exercised by any test — no test drives an Item-to-CRMProduct transfer through the RecordRef dispatch to confirm the case is reached and the record is written back correctly. Add an integration-style test that triggers the Item-CRM Product transfer path (e.g. via the subscriber's OnBeforeTransferFieldData or a full sync call) and asserts the resulting CRM Product has ConvertToCustomerAsset = false.

Line mapping was unavailable, so this was posted as an issue comment.

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

Comment thread src/Apps/W1/FieldServiceIntegration/test/src/FSIntegrationTest.Codeunit.al Outdated
…procedure to streamline service item synchronization
…re and update test cases for service item synchronization
Comment thread src/Apps/W1/FieldServiceIntegration/test/src/FSIntegrationTest.Codeunit.al Outdated
Comment thread src/Apps/W1/FieldServiceIntegration/test/src/FSIntegrationTest.Codeunit.al Outdated
@github-actions github-actions Bot added Team: Other GitHub request for other area than SCM, Finance or Integration and removed Team: SCM GitHub request for SCM area labels Sep 21, 2026
@github-actions github-actions Bot added Team: SCM GitHub request for SCM area and removed Team: Other GitHub request for other area than SCM, Finance or Integration Ownership: Needs Review Ownership is Other, low confidence, or needs manual correction labels Sep 21, 2026
@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 1

Recommendation: Accept with Suggestions

What this PR does

This change keeps Business Central as the source for Field Service customer assets for synchronized items. It removes the service-item filter that depended on the Product's Convert to Customer Asset flag, and it adds item-product synchronization logic that turns that flag off for coupled items.

The main behavior looks correct for the reported duplicate-asset scenario. The service-item mapping depends on the item-product mapping, the new item-product transfer path uses the coupling state to derive the Product value, and the tests cover both the mapping setup and a coupled item/product synchronization. The relevant integration event publishers and call sites were checked, including the field-modified and transfer-field hooks used by this change.

Problem-solution fit

Fit: Strong

The reported problem is that both systems can create a customer asset for the same equipment. The change addresses the root cause by always allowing the Business Central service item to synchronize and by disabling native Field Service customer asset conversion on coupled Products.

Suggestions

S1 (🟠 Moderate): Guard field-modified handling when disabled
Add the same FSConnectionSetup.IsEnabled() guard here that OnTransferFieldData uses. If the mapping is still present after Field Service is disabled, this handler can mark the field as modified while the transfer handler exits, so synchronization can fall back to copying the wrong value.

Risk assessment and necessity

Risk: The main regression surface is item-to-Product synchronization and service-item-to-customer-asset synchronization for coupled Field Service data. The change is not financial posting logic and does not change schema, but it changes integration behavior for coupled Products and can affect customers that rely on native Field Service conversion for those Products.

Necessity: The change is needed because the old Product flag could suppress Business Central customer-asset synchronization while still allowing Field Service to create another asset during work order completion. The scope is targeted: it keeps service items synchronizing and moves the conflict prevention to the item-product mapping where the Product flag is maintained.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11094 round=1 by=alexei-dobriansky at=2026-09-21T12:13:08.5984330Z lastSha=c5796a5023449a01544ea4228b5cc8de435d4502 reviewKey=0d24fd740440a636e26d7079fcacd6e978a82a52468ad3a95333da6d590029a7 suggestions=S1@57bf2917

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 2

Recommendation: Accept

What this PR does

The latest change addresses the remaining field-comparison gap from round 1. The field-modified subscriber now uses the same Field Service enabled guard as the transfer subscriber, and the added test verifies that the comparison hook stays unhandled when integration is disabled.

The current diff still fits the reported duplicate-customer-asset scenario. The item-product mapping derives Convert to Customer Asset from the item coupling state, service items are no longer skipped by that Product flag, and the comparison and transfer hooks now stay consistent when Field Service integration is off.

Status of previous suggestions
ID Title Status Author response
S1 Guard field-modified handling when disabled Addressed N/A
New observations (commits since round 1)

None - changes only addressed the previous suggestion.

Risk assessment and necessity

Risk: The regression surface remains item-to-Product synchronization and service-item-to-customer-asset synchronization for coupled Field Service data. The latest change lowers the disabled-integration risk by making field comparison and field transfer follow the same guard.

Necessity: The change is still needed to prevent both systems from creating customer assets for the same equipment. The round-2 change is also necessary because it keeps the new mapping inactive when Field Service integration is disabled.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11094 round=2 by=alexei-dobriansky at=2026-09-22T00:41:21.760Z lastSha=e8302a63d9db4358400aaac00b19e1801fc4ef13 reviewKey=50f4f3d160acbc5279ec1710a9ba3d94a60de2955143cdd254f18927dca0c431 suggestions=S1@57bf2917:addressed parentRound=1

…sset conversion checks and update corresponding test case
@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 3

Recommendation: Accept

What this PR does

The latest change keeps the accepted Field Service customer-asset fix but simplifies how the synchronization hooks read the item managed state. Instead of rebuilding an Item record from the source field, both hooks now use the already-calculated source field value, so the comparison and transfer paths use the same boolean input.

The current PR still fits the reported duplicate-customer-asset scenario. The item-product mapping derives Convert to Customer Asset from the item coupling state, service items are no longer skipped by that Product flag, and the latest commit does not change the intended behavior.

Status of previous suggestions
ID Title Status Author response
S1 Guard field-modified handling when disabled Addressed N/A
New observations (commits since round 2)

None - the latest change is a narrow refactor and test cleanup.

Risk assessment and necessity

Risk: The regression surface remains item-to-Product synchronization and service-item-to-customer-asset synchronization for coupled Field Service data. The latest refactor uses the already-calculated source field value consistently in comparison and transfer hooks, so it does not add a new compatibility or data-integrity risk.

Necessity: The change is still needed to prevent both systems from creating customer assets for the same equipment. The round-3 change is also reasonable because it removes unnecessary record reconstruction and keeps the hook logic focused on the mapped field value.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11094 round=3 by=alexei-dobriansky at=2026-09-22T12:08:52.554Z lastSha=182701ab80312ed8d00efc3b14301303840baa71 reviewKey=798ed7c8d1aafffdd1efe4b647dea9a7fcd9175cd1618cd9cf4002e5e4b041da suggestions=S1@57bf2917:addressed parentRound=2

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 4

Recommendation: Request Changes

What this PR does

The latest change makes the field-modified check read the persisted Product value before deciding whether Convert to Customer Asset changed. That addresses the comparison problem for an existing Product.

The full PR still does not fully close the duplicate-customer-asset scenario. The new mapping derives the Product flag from the Item coupling FlowField, but that FlowField is false during the first Item-to-Product insert because the coupling is created after the Product is inserted.

Status of previous suggestions
ID Title Status Author response
S1 Guard field-modified handling when disabled Addressed N/A
New observations (commits since round 3)

S2 (🔴 High): Initial item sync still enables conversion
On the first Item-to-Product sync, Coupled to Dataverse is still false because the coupling is created only after the new Product is inserted. This writes Convert to Customer Asset as Yes on the new Product, so Field Service can still create a duplicate asset before a later sync corrects it.

Risk assessment and necessity

Risk: The remaining risk is data duplication for Products first created from Business Central Items. The sync engine transfers fields before inserting the Product and before updating the integration coupling, so the initial Product can keep native Field Service customer-asset conversion enabled.

Necessity: The change is needed, but it must disable Field Service customer-asset conversion on the first Product created from a Business Central Item as well as on later syncs of already-coupled Products.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11094 round=4 by=alexei-dobriansky at=2026-09-23T00:22:38.759Z lastSha=7ecda20a187fbc5662ffdd5bb70096d2b8ff255d reviewKey=6190b4dd728b3358f9b211bb444b77d213485b579fe631c1ae7645af82b46a2d suggestions=S1@57bf2917:addressed,S2@2cfc7b19:new parentRound=3

…tem synchronization and add corresponding test case
@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 5

Recommendation: Accept with Suggestions

What this PR does

The latest changes replace the Item coupling-derived mapping with a constant false mapping and enforce the same value after field transfer. The first Item-to-Product synchronization is now handled before the Product is inserted or coupled, and a full synchronization test verifies that the new Product has conversion disabled.

The current diff addresses the duplicate-asset scenario for both new and existing Products. Existing Products are checked against their persisted value before being changed, while Service Items continue to synchronize.

Status of previous suggestions
ID Title Status Author response
S1 Guard field-modified handling when disabled Addressed N/A
S2 Initial item sync still enables conversion Addressed Fixed by the constant mapping, runtime enforcement, and first-sync test.
New observations (commits since round 4)

S3 (🟠 Moderate): Preserve the obsolete helper behavior until removal
This public test-library procedure now silently does nothing, so existing downstream tests can still compile but receive a different IgnoreRecord result. Keep forwarding to the obsolete internal implementation until the procedure is removed. Production will still follow the new design because its dispatch call has already been removed.

Risk assessment and necessity

Risk: The production fix is targeted to Item-to-Product and Service Item synchronization. The remaining risk is limited to downstream test apps that call the public test-library helper and now receive different behavior during its obsoletion window.

Necessity: The change is needed to prevent both systems from creating customer assets for the same equipment. The constant mapping and runtime enforcement now cover both the first Product synchronization and later synchronization of existing Products.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11094 round=5 by=alexei-dobriansky at=2026-09-25T18:16:51.8713876Z lastSha=b06ffe49e23973057d514ceabf327c68529c8ace reviewKey=fc4d0b0d1bd29dff6498c5b6e40669021a6c52f95d42364198982d5f35b904f9 suggestions=S1@57bf2917:addressed,S2@2cfc7b19:addressed,S3@43473f59:new parentRound=4

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 6

Recommendation: Accept with Suggestions

What this PR does

The latest change now disables customer asset conversion immediately before a Product is inserted or modified. For an existing Product, synchronization is forced only when the persisted value is still enabled; the first-sync test now explicitly allows creation of an uncoupled Product.

This keeps the value enforcement in the record-writing path and covers both new and existing Products without changing Service Item synchronization.

Status of previous suggestions
ID Title Status Author response
S1 Guard field-modified handling when disabled Addressed N/A
S2 Initial item sync still enables conversion Addressed N/A
S3 Preserve the obsolete helper behavior until removal Not addressed The public compatibility procedure is unchanged and still leaves IgnoreRecord untouched.
New observations (commits since round 5)

None - the latest commit refines the Product insert and modify paths and updates the first-synchronization test.

Risk assessment and necessity

Risk: The production behavior is now enforced directly before Product writes, and the existing regression tests cover new and coupled Products. The remaining risk is limited to downstream test apps that call the obsolete public test helper and now receive different behavior during its obsoletion window.

Necessity: The change is needed to prevent Field Service and Business Central from creating duplicate customer assets for the same equipment. The current implementation covers initial synchronization and later updates while Service Items continue to synchronize.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11094 round=6 by=alexei-dobriansky at=2026-09-26T00:25:41.9813913Z lastSha=2ec90f95dd1bb3cddf14a3141c56fe18464d3d7e reviewKey=56bc020c1ecedcda4c7394ae1fd50f73f50b9b0221aa4dbf7d502a0c0fc3b180 suggestions=S1@57bf2917:addressed,S2@2cfc7b19:addressed,S3@43473f59:notaddressed parentRound=5

Use the standard mock CRM connection for item-product synchronization tests and assert the synchronization job succeeds before validating coupling and customer asset conversion.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 7

Recommendation: Accept with Suggestions

What this PR does

The latest change uses the standard mock connection for the item-to-Product synchronization tests and now verifies that each synchronization job completes successfully before checking the Product result.

The full change still addresses the duplicate-customer-asset scenario. The integration sync events expose the destination record before insert and modify, so conversion is disabled in the record-writing path for both new and existing Products. The updated tests now exercise those paths and confirm one inserted or modified record with no synchronization failure.

Status of previous suggestions
ID Title Status Author response
S1 Guard field-modified handling when disabled Addressed N/A
S2 Initial item sync still enables conversion Addressed N/A
S3 Preserve the obsolete helper behavior until removal Not addressed The public compatibility procedure still leaves IgnoreRecord unchanged.
New observations (commits since round 6)

None - the latest commit repairs the test connection setup and adds explicit synchronization-job assertions.

Risk assessment and necessity

Risk: The production behavior remains targeted to Item-to-Product and Service Item synchronization. The latest test-only change reduces uncertainty by proving the insert and modify synchronization jobs succeed; the remaining compatibility risk is limited to downstream test apps that call the obsolete public helper during its obsoletion window.

Necessity: The production change is needed to prevent Field Service and Business Central from creating duplicate customer assets for the same equipment. The latest test setup change is also necessary because it makes the regression tests execute the real synchronization path and fail clearly if that path does not complete.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11094 round=7 by=alexei-dobriansky at=2026-09-26T12:09:12.0900571Z lastSha=05155ed85bc89389c621a4674a5268a5a9620c3a reviewKey=88fef53d6dc5db8cb9a8a036532f94af8a62e672318032c2eee9cbd80145e994 suggestions=S1@57bf2917:addressed,S2@2cfc7b19:addressed,S3@43473f59:notaddressed parentRound=6

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 8

Recommendation: Accept with Suggestions

What this PR does

The latest commit replaces the direct FieldRef write with the standard typed Record/RecordRef copy pattern. It also centralizes synchronization-job checks so test failures include the actual synchronization error.

The full fix remains correct. New Products have customer asset conversion disabled before insert. For existing Products, the persisted value triggers a modify when needed, and conversion is disabled before the record is written. The latest refactor preserves this flow and matches the established BaseApp pattern.

Status of previous suggestions
ID Title Status Author response
S1 Guard field-modified handling when disabled Addressed N/A
S2 Initial item sync still enables conversion Addressed N/A
S3 Preserve the obsolete helper behavior until removal Not addressed The public compatibility procedure still leaves IgnoreRecord unchanged.
New observations (commits since round 7)

None - the latest refactor preserves the Product insert and modify behavior and improves synchronization-test diagnostics.

Risk assessment and necessity

Risk: The production behavior remains targeted to Item-to-Product and Service Item synchronization. The typed RecordRef update follows the established integration pattern, and the regression tests cover new and existing Products. The remaining compatibility risk is limited to downstream test apps that call the obsolete public helper during its obsoletion window.

Necessity: The change is needed to prevent Field Service and Business Central from creating duplicate customer assets for the same equipment. The latest refactor is also useful because it keeps record mutation explicit and makes synchronization-test failures easier to diagnose.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11094 round=8 by=alexei-dobriansky at=2026-09-26T18:06:39.1880724Z lastSha=901cfcf621ae45d957cd0bead657f3c8f6e0c760 reviewKey=21f21503e89793b4d7c4613a1874041c46f4dc8f7f76fbec97b7d58a2c1daf87 suggestions=S1@57bf2917:addressed,S2@2cfc7b19:addressed,S3@43473f59:notaddressed parentRound=7

Create Item Unit of Measure couplings required by the Item-Product synchronization dependency before exercising initial and existing product synchronization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 9

Recommendation: Accept with Suggestions

What this PR does

The latest commit couples each Item Unit of Measure to a CRM UoM before running the Item-to-Product synchronization tests. This adds a required synchronization dependency, but the jobs still stop before reaching the Product assertions because the CRM base currency is not initialized.

The production fix remains correct. The constant mapping disables native customer-asset conversion, the insert hook handles new Products, and the modify path checks the persisted value and disables conversion before writing existing Products. The BaseApp publisher timing supports both hooks.

Status of previous suggestions
ID Title Status Author response
S1 Guard field-modified handling when disabled Addressed N/A
S2 Initial item sync still enables conversion Addressed N/A
S3 Preserve the obsolete helper behavior until removal Not addressed The public compatibility procedure still has an empty body.
New observations (commits since round 8)

S4 (🟠 Moderate): Initialize CRM base currency in sync tests
Both item synchronization tests still fail because the mock CRM setup leaves BaseCurrencyId empty. Initialize the CRM base currency before calling SynchRecord; the current CI run reports “The base currency is not defined” in both tests.

Risk assessment and necessity

Risk: The production behavior remains targeted to Item-to-Product and Service Item synchronization, and the BaseApp event sequence supports the insert and modify enforcement. Validation remains incomplete because both behavioral synchronization tests fail during setup. The obsolete public helper also still changes behavior for downstream test apps during its obsoletion window.

Necessity: The production change is needed to prevent Business Central and Field Service from creating duplicate customer assets for the same equipment. The latest UoM setup is necessary, but the tests also need a configured CRM base currency before they can validate the fixed paths.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11094 round=9 by=alexei-dobriansky at=2026-09-27T00:08:14.5054623Z lastSha=f888bf41fbedb858b06b22044ef05ca7c6d3bef5 reviewKey=3900505e166fc6995131935952b5b0a201c30f52909d85ab53ef7796262b3635 suggestions=S1@57bf2917:addressed,S2@2cfc7b19:addressed,S3@43473f59:notaddressed,S4@38693145:new parentRound=8

Create the mock CRM organization and copy its base currency to the CRM connection before running Item-Product synchronization scenarios.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

This branch was successfully deployed

1 active (outdated) deployment
triage — c5796a50 Deployed Sep 21, 2026 by JesperSchulz via Classify team ownership #5286
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AL: Apps (W1) Add-on apps for W1 Team: SCM GitHub request for SCM area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants