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..b7afc76b637 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 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) 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 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")