From c06b08b72485f79e0ec6e68de4cbdac40a81fd04 Mon Sep 17 00:00:00 2001 From: v-dhavalmore Date: Tue, 11 Aug 2026 20:21:11 +0530 Subject: [PATCH 1/4] Changes --- .../History/UndoSalesShipmentLine.Codeunit.al | 6 ++---- .../UndoPurchaseReceiptLine.Codeunit.al | 18 +++++++++++++++++- .../History/UndoSalesShipmentLine.Codeunit.al | 6 ++---- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/Layers/RU/BaseApp/Sales/History/UndoSalesShipmentLine.Codeunit.al b/src/Layers/RU/BaseApp/Sales/History/UndoSalesShipmentLine.Codeunit.al index 22dafd59da0..e2166dee2f3 100644 --- a/src/Layers/RU/BaseApp/Sales/History/UndoSalesShipmentLine.Codeunit.al +++ b/src/Layers/RU/BaseApp/Sales/History/UndoSalesShipmentLine.Codeunit.al @@ -248,12 +248,10 @@ codeunit 5815 "Undo Sales Shipment Line" ItemApplicationEntry.SetBaseLoadFields(); ItemApplicationEntry.SetRange("Item Ledger Entry No.", ItemLedgerEntry."Entry No."); - ItemApplicationEntry.SetRange("Cost Application", true); ItemApplicationEntry.SetRange("Inbound Item Entry No.", ItemLedgerEntry."Applies-to Entry"); ItemApplicationEntry.SetRange("Outbound Item Entry No.", ItemLedgerEntry."Entry No."); - ItemApplicationEntry.FindFirst(); - - ItemJnlPostLine.UnApplyDropShipment(ItemApplicationEntry, RelevantUndoShipmentLedgerEntryNo); + if ItemApplicationEntry.FindFirst() then + ItemJnlPostLine.UnApplyDropShipment(ItemApplicationEntry, RelevantUndoShipmentLedgerEntryNo); end; local procedure FindRelevantNewSalesShptLedgerEntryNo(SalesShptLine: Record "Sales Shipment Line"; NewSalesShptLine: Record "Sales Shipment Line"; ItemLedgerEntry: Record "Item Ledger Entry"): Integer diff --git a/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al b/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al index 64d88cca963..b0a6624d46e 100644 --- a/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al +++ b/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al @@ -629,9 +629,25 @@ codeunit 5813 "Undo Purchase Receipt Line" if (OutboundItemLedgerEntry."Lot No." = '') and (OutboundItemLedgerEntry."Serial No." = '') then SalesShipmentLine.SetRange("Item Shpt. Entry No.", OutboundItemLedgerEntry."Entry No."); - SalesShipmentLine.FindFirst(); + if SalesShipmentLine.FindFirst() then + exit; end; end; + + FindSalesShipmentLineByDropShipmentLink(SalesShipmentLine, PurchRcptLine); + end; + + local procedure FindSalesShipmentLineByDropShipmentLink(var SalesShipmentLine: Record "Sales Shipment Line"; PurchRcptLine: Record "Purch. Rcpt. Line") + begin + SalesShipmentLine.Reset(); + SalesShipmentLine.SetRange("Order No.", PurchRcptLine."Sales Order No."); + SalesShipmentLine.SetRange("Order Line No.", PurchRcptLine."Sales Order Line No."); + SalesShipmentLine.SetRange("Purchase Order No.", PurchRcptLine."Order No."); + SalesShipmentLine.SetRange("Purch. Order Line No.", PurchRcptLine."Order Line No."); + SalesShipmentLine.SetRange("Drop Shipment", true); + SalesShipmentLine.SetRange(Correction, false); + SalesShipmentLine.SetRange(Quantity, PurchRcptLine.Quantity); + SalesShipmentLine.FindFirst(); end; procedure IsUndoSalesShipmentLineForDropShipment(NewUndoSalesShptLineExists: Boolean) diff --git a/src/Layers/W1/BaseApp/Sales/History/UndoSalesShipmentLine.Codeunit.al b/src/Layers/W1/BaseApp/Sales/History/UndoSalesShipmentLine.Codeunit.al index 7baa27bd874..5865ef38899 100644 --- a/src/Layers/W1/BaseApp/Sales/History/UndoSalesShipmentLine.Codeunit.al +++ b/src/Layers/W1/BaseApp/Sales/History/UndoSalesShipmentLine.Codeunit.al @@ -248,12 +248,10 @@ codeunit 5815 "Undo Sales Shipment Line" ItemApplicationEntry.SetBaseLoadFields(); ItemApplicationEntry.SetRange("Item Ledger Entry No.", ItemLedgerEntry."Entry No."); - ItemApplicationEntry.SetRange("Cost Application", true); ItemApplicationEntry.SetRange("Inbound Item Entry No.", ItemLedgerEntry."Applies-to Entry"); ItemApplicationEntry.SetRange("Outbound Item Entry No.", ItemLedgerEntry."Entry No."); - ItemApplicationEntry.FindFirst(); - - ItemJnlPostLine.UnApplyDropShipment(ItemApplicationEntry, RelevantUndoShipmentLedgerEntryNo); + if ItemApplicationEntry.FindFirst() then + ItemJnlPostLine.UnApplyDropShipment(ItemApplicationEntry, RelevantUndoShipmentLedgerEntryNo); end; local procedure FindRelevantNewSalesShptLedgerEntryNo(SalesShptLine: Record "Sales Shipment Line"; NewSalesShptLine: Record "Sales Shipment Line"; ItemLedgerEntry: Record "Item Ledger Entry"): Integer From 57793b007a2012819936f034111790eec98b26d4 Mon Sep 17 00:00:00 2001 From: v-dhavalmore Date: Wed, 12 Aug 2026 10:18:59 +0530 Subject: [PATCH 2/4] Changes --- .../UndoPurchaseReceiptLine.Codeunit.al | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al b/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al index b0a6624d46e..b7afc76b637 100644 --- a/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al +++ b/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al @@ -637,17 +637,17 @@ codeunit 5813 "Undo Purchase Receipt Line" FindSalesShipmentLineByDropShipmentLink(SalesShipmentLine, PurchRcptLine); end; - local procedure FindSalesShipmentLineByDropShipmentLink(var SalesShipmentLine: Record "Sales Shipment Line"; PurchRcptLine: Record "Purch. Rcpt. Line") - begin - SalesShipmentLine.Reset(); - SalesShipmentLine.SetRange("Order No.", PurchRcptLine."Sales Order No."); - SalesShipmentLine.SetRange("Order Line No.", PurchRcptLine."Sales Order Line No."); - SalesShipmentLine.SetRange("Purchase Order No.", PurchRcptLine."Order No."); - SalesShipmentLine.SetRange("Purch. Order Line No.", PurchRcptLine."Order Line No."); - SalesShipmentLine.SetRange("Drop Shipment", true); - SalesShipmentLine.SetRange(Correction, false); - SalesShipmentLine.SetRange(Quantity, PurchRcptLine.Quantity); - SalesShipmentLine.FindFirst(); + local procedure FindSalesShipmentLineByDropShipmentLink(var SalesShipLine: Record "Sales Shipment Line"; PurchReceiptLine: Record "Purch. Rcpt. Line") + begin + SalesShipLine.Reset(); + SalesShipLine.SetRange("Order No.", PurchReceiptLine."Sales Order No."); + SalesShipLine.SetRange("Order Line No.", PurchReceiptLine."Sales Order Line No."); + SalesShipLine.SetRange("Purchase Order No.", PurchReceiptLine."Order No."); + SalesShipLine.SetRange("Purch. Order Line No.", PurchReceiptLine."Order Line No."); + SalesShipLine.SetRange("Drop Shipment", true); + SalesShipLine.SetRange(Correction, false); + SalesShipLine.SetRange(Quantity, PurchReceiptLine.Quantity); + SalesShipLine.FindFirst(); end; procedure IsUndoSalesShipmentLineForDropShipment(NewUndoSalesShptLineExists: Boolean) From 20627a73e2b2e76fcd909cdf600d2c16f521cb3a Mon Sep 17 00:00:00 2001 From: v-dhavalmore Date: Thu, 13 Aug 2026 18:41:37 +0530 Subject: [PATCH 3/4] Automations --- .../SCMRTAMItemTrackingII.Codeunit.al | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/src/Layers/W1/Tests/SCM-Reservation/SCMRTAMItemTrackingII.Codeunit.al b/src/Layers/W1/Tests/SCM-Reservation/SCMRTAMItemTrackingII.Codeunit.al index ecc557b7f0c..4afd386d18e 100644 --- a/src/Layers/W1/Tests/SCM-Reservation/SCMRTAMItemTrackingII.Codeunit.al +++ b/src/Layers/W1/Tests/SCM-Reservation/SCMRTAMItemTrackingII.Codeunit.al @@ -4375,6 +4375,102 @@ codeunit 137059 "SCM RTAM Item Tracking-II" PurchaseLine.TestField("Qty. to Receive", RegularQty); end; + [Test] + [HandlerFunctions('SalesListPageHandler,ConfirmHandler')] + procedure QuantityMustBeRestoredWhenUndoDropShipmentSalesShipmentIsExecutedForNonInventoryItem() + var + Item: Record Item; + SalesLine: Record "Sales Line"; + SalesHeader: Record "Sales Header"; + PurchaseHeader: Record "Purchase Header"; + Quantity: Decimal; + begin + // [SCENARIO 646367] Verify that quantity must be restored when Undo Drop Shipment Sales Shipment is executed for a Non-Inventory item. + Initialize(); + + // [GIVEN] Generate a random quantity. + Quantity := LibraryRandom.RandInt(50); + + // [GIVEN] Create a Non-Inventory item. + CreateNonInventoriableItemWithVendorNo(Item, Item.Type::"Non-Inventory", Quantity); + + // [GIVEN] Create a sales order with drop shipment. + CreateSalesOrderWithPurchasingCode(SalesHeader, SalesLine, Item."No.", '', Quantity, false); + + // [GIVEN] Create a purchase order for drop shipment. + CreatePurchaseHeaderAndGetDropShipment(PurchaseHeader, SalesHeader."Sell-to Customer No."); + + // [GIVEN] Post Sales Document with shipment only. + PostSalesDocument(SalesHeader."Document Type", SalesHeader."No.", true, false); + + // [GIVEN] Verify that the shipment is posted and quantity shipped. + VerifyQuantityForDropShipmentInSalesLine(SalesHeader, Item."No.", Quantity, 0); + + // [GIVEN] Verify that the Receipt is posted and quantity received. + VerifyQuantityForDropShipmentInPurchaseLine(PurchaseHeader, Item."No.", Quantity, 0); + + // [WHEN] Undo Sales Shipment. + UndoSalesShipment(SalesHeader."No."); + + // [THEN] Verify that Qty. to Ship is restored and Quantity Shipped is Zero. + VerifyQuantityForDropShipmentInSalesLine(SalesHeader, Item."No.", 0, Quantity); + + // [THEN] Verify that Qty. to Receive is restored and Quantity Received is Zero. + VerifyQuantityForDropShipmentInPurchaseLine(PurchaseHeader, Item."No.", 0, Quantity); + + // [THEN] Verify that the posted shipment and the linked posted receipt are both corrected. + VerifyUndoneSalesShipmentLine(SalesHeader."No.", Item."No.", Quantity); + VerifyUndonePurchRcptLine(PurchaseHeader."No.", Item."No.", Quantity); + end; + + [Test] + [HandlerFunctions('SalesListPageHandler,ConfirmHandler')] + procedure QuantityMustBeRestoredWhenUndoDropShipmentPurchRcptIsExecutedForServiceItem() + var + Item: Record Item; + SalesLine: Record "Sales Line"; + SalesHeader: Record "Sales Header"; + PurchaseHeader: Record "Purchase Header"; + Quantity: Decimal; + begin + // [SCENARIO 646367] Verify that quantity must be restored when Undo Drop Shipment Purchase Receipt is executed for a Service item. + Initialize(); + + // [GIVEN] Generate a random quantity. + Quantity := LibraryRandom.RandInt(50); + + // [GIVEN] Create a Service item. + CreateNonInventoriableItemWithVendorNo(Item, Item.Type::Service, Quantity); + + // [GIVEN] Create a sales order with drop shipment. + CreateSalesOrderWithPurchasingCode(SalesHeader, SalesLine, Item."No.", '', Quantity, false); + + // [GIVEN] Create a purchase order for drop shipment. + CreatePurchaseHeaderAndGetDropShipment(PurchaseHeader, SalesHeader."Sell-to Customer No."); + + // [GIVEN] Post Sales Document with shipment only. + PostSalesDocument(SalesHeader."Document Type", SalesHeader."No.", true, false); + + // [GIVEN] Verify that the shipment is posted and quantity shipped. + VerifyQuantityForDropShipmentInSalesLine(SalesHeader, Item."No.", Quantity, 0); + + // [GIVEN] Verify that the Receipt is posted and quantity received. + VerifyQuantityForDropShipmentInPurchaseLine(PurchaseHeader, Item."No.", Quantity, 0); + + // [WHEN] Undo Purchase Receipt. + UndoPurchaseReceipt(PurchaseHeader."No."); + + // [THEN] Verify that Qty. to Ship is restored and Quantity Shipped is Zero. + VerifyQuantityForDropShipmentInSalesLine(SalesHeader, Item."No.", 0, Quantity); + + // [THEN] Verify that Qty. to Receive is restored and Quantity Received is Zero. + VerifyQuantityForDropShipmentInPurchaseLine(PurchaseHeader, Item."No.", 0, Quantity); + + // [THEN] Verify that the posted receipt and the linked posted shipment are both corrected. + VerifyUndonePurchRcptLine(PurchaseHeader."No.", Item."No.", Quantity); + VerifyUndoneSalesShipmentLine(SalesHeader."No.", Item."No.", Quantity); + end; + local procedure Initialize() var LibraryERMCountryData: Codeunit "Library - ERM Country Data"; @@ -6213,6 +6309,46 @@ codeunit 137059 "SCM RTAM Item Tracking-II" StrSubstNo(ValueMustBeEqualErr, ItemLedgEntry.FieldCaption("Cost Amount (Actual)"), CostActualAmount, ItemLedgEntry.TableCaption())); end; + local procedure CreateNonInventoriableItemWithVendorNo(var Item: Record Item; ItemType: Enum "Item Type"; UnitCost: Decimal) + begin + LibraryInventory.CreateItem(Item); + Item.Validate(Type, ItemType); + Item.Validate("Vendor No.", LibraryPurchase.CreateVendorNo()); + Item.Validate("Unit Price", LibraryRandom.RandDec(10, 2)); + Item.Validate("Unit Cost", UnitCost); + Item.Validate("Last Direct Cost", Item."Unit Cost"); + Item.Modify(true); + end; + + local procedure VerifyUndoneSalesShipmentLine(SalesOrderNo: Code[20]; ItemNo: Code[20]; ExpectedQuantity: Decimal) + var + SalesShipmentHeader: Record "Sales Shipment Header"; + SalesShipmentLine: Record "Sales Shipment Line"; + begin + FindSalesShipmentHeader(SalesShipmentHeader, SalesOrderNo); + SalesShipmentLine.SetRange("Document No.", SalesShipmentHeader."No."); + SalesShipmentLine.SetRange(Type, SalesShipmentLine.Type::Item); + SalesShipmentLine.SetRange("No.", ItemNo); + SalesShipmentLine.SetRange(Correction, true); + SalesShipmentLine.SetRange(Quantity, -ExpectedQuantity); + Assert.RecordIsNotEmpty(SalesShipmentLine); + end; + + local procedure VerifyUndonePurchRcptLine(PurchOrderNo: Code[20]; ItemNo: Code[20]; ExpectedQuantity: Decimal) + var + PurchRcptHeader: Record "Purch. Rcpt. Header"; + PurchRcptLine: Record "Purch. Rcpt. Line"; + begin + PurchRcptHeader.SetRange("Order No.", PurchOrderNo); + PurchRcptHeader.FindFirst(); + PurchRcptLine.SetRange("Document No.", PurchRcptHeader."No."); + PurchRcptLine.SetRange(Type, PurchRcptLine.Type::Item); + PurchRcptLine.SetRange("No.", ItemNo); + PurchRcptLine.SetRange(Correction, true); + PurchRcptLine.SetRange(Quantity, -ExpectedQuantity); + Assert.RecordIsNotEmpty(PurchRcptLine); + end; + [ModalPageHandler] [Scope('OnPrem')] procedure QuantityToCreatePageHandler(var EnterQuantityToCreate: TestPage "Enter Quantity to Create") From a8be4bad3a57f690a4521155fd22598df62cc6b7 Mon Sep 17 00:00:00 2001 From: v-dhavalmore Date: Fri, 14 Aug 2026 17:32:44 +0530 Subject: [PATCH 4/4] Suggetion Changes --- .../History/UndoPurchaseReceiptLine.Codeunit.al | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al b/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al index b7afc76b637..cc3d1749295 100644 --- a/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al +++ b/src/Layers/W1/BaseApp/Purchases/History/UndoPurchaseReceiptLine.Codeunit.al @@ -71,6 +71,7 @@ codeunit 5813 "Undo Purchase Receipt Line" #pragma warning restore AA0074 NoLinesToReverseErr: Label 'No lines with a quantity available for reversal were found among the selected lines. Select a line with a quantity that has not already been reversed, and try again.'; AlreadyReversedErr: Label 'This receipt has already been reversed.'; + AmbiguousDropShipmentLinkErr: Label 'The posted sales shipment line for drop shipment line %1 in posted purchase receipt %2 cannot be identified, because sales order %3 has more than one matching posted shipment line. Undo the shipment from the posted sales shipment instead.', Comment = '%1 - Purch. Rcpt. Line No., %2 - Purch. Rcpt. Header No., %3 - Sales Order No.'; procedure SetHideDialog(NewHideDialog: Boolean) begin @@ -626,8 +627,13 @@ codeunit 5813 "Undo Purchase Receipt Line" SalesShipmentLine.SetRange("Document No.", OutboundItemLedgerEntry."Document No."); SalesShipmentLine.SetRange("Line No.", OutboundItemLedgerEntry."Document Line No."); - if (OutboundItemLedgerEntry."Lot No." = '') and (OutboundItemLedgerEntry."Serial No." = '') then + if (OutboundItemLedgerEntry."Lot No." = '') and (OutboundItemLedgerEntry."Serial No." = '') then begin SalesShipmentLine.SetRange("Item Shpt. Entry No.", OutboundItemLedgerEntry."Entry No."); + if SalesShipmentLine.FindFirst() then + exit; + + SalesShipmentLine.SetRange("Item Shpt. Entry No."); + end; if SalesShipmentLine.FindFirst() then exit; @@ -647,6 +653,10 @@ codeunit 5813 "Undo Purchase Receipt Line" SalesShipLine.SetRange("Drop Shipment", true); SalesShipLine.SetRange(Correction, false); SalesShipLine.SetRange(Quantity, PurchReceiptLine.Quantity); + + if SalesShipLine.Count() > 1 then + Error(AmbiguousDropShipmentLinkErr, PurchReceiptLine."Line No.", PurchReceiptLine."Document No.", PurchReceiptLine."Sales Order No."); + SalesShipLine.FindFirst(); end;