microsoft / microsoft/BCApps

Undo of posted subcontracting purchase receipt fails with duplicate Item Entry Relation key

Open
#10,026 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Subcontracting Team: SCM
Dominant language
AL
Stars
683
Forks
459
Avg merge
3d 26m
Merged PRs (30d)
633

Description

AB#644744

Summary

When undoing a posted subcontracting purchase receipt, Business Central can fail with a duplicate-key error while inserting an Item Entry Relation record. In cases where no key collision happens, the undo can silently insert an incorrect relation.

Repro / Affected scenario

Undo a posted subcontracting purchase receipt where the output is tracked or involves more than one output entry, specifically when any of the following apply:

  • Multiple eligible output Item Ledger Entries exist for the receipt.
  • The single output entry is lot-tracked.
  • The single output entry is serial-tracked.

Partial subcontracting receipts are a likely reproducer because they can produce the above entry topology, but are not a strict prerequisite.

Found in build 28.3.

Expected result

Undoing the subcontracting purchase receipt completes successfully, and any Item Entry Relation created during the undo references the correct reversing Item Ledger Entry.

Actual result

The undo fails with a duplicate primary key error when inserting into table 6507 Item Entry Relation. When no collision occurs, the undo may succeed but store an Item Entry No. that does not identify the newly posted reversing Item Ledger Entry, leaving item tracking associated with the wrong entry.

Root cause

Table 6507 Item Entry Relation uses Item Entry No. as its clustered primary key and defines it as a relation to Item Ledger Entry. During subcontracting undo, this key is populated with a Capacity Ledger Entry number instead of an Item Ledger Entry number.

The faulty data flow:

  1. Subcontracting setupMfgUndoPurchRcptLine marks the item journal line as subcontracting. The single-entry shortcut is used only when exactly one output item ledger entry exists and it has neither lot nor serial tracking. Tracked or multiple output entries take the applied-entry-list path.
  2. Overloaded return value – For subcontracting, Item Jnl.-Post Line (codeunit 22) deliberately returns the Capacity Ledger Entry number through ItemJnlLine."Item Shpt. Entry No.". Normal item posting returns the actual Item Ledger Entry number in that field.
  3. Type/contract confusion – On the applied-entry-list path, PostItemJnlLineAppliedToList() in UndoPostingManagement treats Item Shpt. Entry No. as an Item Ledger Entry number and copies it into TempItemEntryRelation."Item Entry No.".
  4. Duplicate insertUndoPurchaseReceiptLine transfers the temporary row to table 6507 with an unconditional Insert(). Nothing converts the capacity entry number into the posted output Item Ledger Entry number.

Because capacity ledger entries and item ledger entries use independent number sequences, the failure is intermittent: the duplicate-key error surfaces only when the newly generated capacity entry number already exists as an Item Entry Relation primary key. When there is no collision, the invalid relation is inserted silently (AL TableRelation is not a database foreign-key constraint, so it does not guarantee referential correctness on insert).

Fix direction

The relation must be populated with the reversing output Item Ledger Entry."Entry No." produced by the specific posting iteration, not the Capacity Ledger Entry number and not the original entry being reversed (TempApplyToItemLedgEntry."Entry No.").

Replacing the subcontracting return value globally is unsafe, because manufacturing posting legitimately reads Item Shpt. Entry No. as a Capacity Ledger Entry reference. Safer approaches:

  • Return the new Item Ledger Entry number separately from the capacity entry number.
  • Expose the posted reversing Item Ledger Entry number explicitly from codeunit 22.
  • Avoid deriving it from sequence state or a "last entry" lookup, especially under modern number allocation and concurrency.

Test coverage gap

The existing subcontracting test UndoPurchaseReceiptForLastOperation uses a single, untracked output entry and therefore takes the single-entry shortcut, which does not exercise the faulty relation insertion. There is no test that combines undo with tracked or multiple output entries. A regression test should cover a tracked or multi-output undo with a pre-existing relation key matching the next capacity entry number.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with MfgUndoPurchRcptLine and the applied-entry path in PostItemJnlLineAppliedToList() in UndoPostingManagement, then trace Item Jnl.-Post Line (codeunit 22) through UndoPurchaseReceiptLine. Compare the existing UndoPurchaseReceiptForLastOperation test with a tracked or multi-output undo. Done means the regression test covers the relation-key collision and the created Item Entry Relation points to the reversing Item Ledger Entry.

Written by the indexing model from the issue text.

Assessment

Domain
backend, databases, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.