Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -311,6 +311,7 @@ codeunit 99000834 "Purch. Line-Reserve"
var
OldReservationEntry: Record "Reservation Entry";
OppositeReservationEntry: Record "Reservation Entry";
ApplyToItemEntryNo: Integer;
NotFullyReserved: Boolean;
IsHandled: Boolean;
begin
Expand Down Expand Up @@ -353,16 +354,23 @@ codeunit 99000834 "Purch. Line-Reserve"
OldReservationEntry.TestItemFields(PurchaseLine."No.", PurchaseLine."Variant Code", PurchaseLine."Location Code");

if CheckApplToItemEntry then begin
ApplyToItemEntryNo := OldReservationEntry."Appl.-to Item Entry";
if OldReservationEntry."Reservation Status" = OldReservationEntry."Reservation Status"::Reservation then begin
OppositeReservationEntry.Get(OldReservationEntry."Entry No.", not OldReservationEntry.Positive);
if OppositeReservationEntry."Source Type" <> Database::"Item Ledger Entry" then
NotFullyReserved := true;
NotFullyReserved := true
else
// Line is fully reserved against an item ledger entry, so the exact cost reversing
// link can be derived from that entry when it was not set on the reservation entry.
if ApplyToItemEntryNo = 0 then
ApplyToItemEntryNo := OppositeReservationEntry."Source Ref. No.";
end else
NotFullyReserved := true;

if OldReservationEntry."Item Tracking" <> OldReservationEntry."Item Tracking"::None then begin
OldReservationEntry.TestField("Appl.-to Item Entry");
CreateReservEntry.SetApplyToEntryNo(OldReservationEntry."Appl.-to Item Entry");
if ApplyToItemEntryNo = 0 then
OldReservationEntry.TestField("Appl.-to Item Entry");
CreateReservEntry.SetApplyToEntryNo(ApplyToItemEntryNo);
CheckApplToItemEntry := false;
end;
end;
Expand Down
4 changes: 2 additions & 2 deletions src/Layers/W1/Tests/SCM/SCMCostingBatch.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ codeunit 137402 "SCM Costing Batch"
end;

[Test]
[HandlerFunctions('StatisticsMessageHandler')]
[HandlerFunctions('AdjustCostItemEntriesHandler,StatisticsMessageHandler')]
[Scope('OnPrem')]
procedure CapacityCostPostedToGLForTwoItemsInOneProductionOrder()
var
Expand Down Expand Up @@ -1075,7 +1075,7 @@ codeunit 137402 "SCM Costing Batch"
end;

[Test]
[HandlerFunctions('StatisticsMessageHandler')]
[HandlerFunctions('AdjustCostItemEntriesHandler,StatisticsMessageHandler')]
[Scope('OnPrem')]
procedure PurchasePostingDoesNotPropagateACYToSourceCurrencyOnGLEntry()
var
Expand Down
105 changes: 105 additions & 0 deletions src/Layers/W1/Tests/SCM/SCMCostingPurchReturnsII.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ codeunit 137032 "SCM Costing Purch Returns II"
LibraryPurchase: Codeunit "Library - Purchase";
LibraryInventory: Codeunit "Library - Inventory";
LibraryCosting: Codeunit "Library - Costing";
LibraryItemTracking: Codeunit "Library - Item Tracking";
LibraryVariableStorage: Codeunit "Library - Variable Storage";
LibraryUtility: Codeunit "Library - Utility";
Assert: Codeunit Assert;
LibraryTestInitialize: Codeunit "Library - Test Initialize";
isInitialized: Boolean;
Expand Down Expand Up @@ -187,6 +190,68 @@ codeunit 137032 "SCM Costing Purch Returns II"
UpdatePurchasesPayablesSetup(BaseExactCostReversingMand, BaseExactCostReversingMand);
end;

[Test]
[HandlerFunctions('ItemTrackingLinesAssignLotPageHandler,PostedPurchaseDocumentLinesModalHandler,ReservationReserveFromCurrentLinePageHandler,ItemTrackingListPageHandler,ConfirmHandler')]
[Scope('OnPrem')]
procedure PurchReturnReserveSpecificLotExactCostReversing()
var
Item: Record Item;
PurchaseHeader: Record "Purchase Header";
PurchaseLine: Record "Purchase Line";
ItemLedgerEntry: Record "Item Ledger Entry";
BaseExactCostReversingMand: Boolean;
VendorNo: Code[20];
LotNo: Code[50];
Quantity: Decimal;
begin
// [SCENARIO] A purchase return created via Get Posted Document Lines to Reverse and then reserved from
// the current line against the receipt item ledger entry (specific lot) posts with Exact Cost Reversing Mandatory.
// [BUG] The Reserve action dropped "Appl.-to Item Entry" on the reservation entry, so posting failed with
// "Appl.-to Item Entry must have a value in Reservation Entry..." and the manual workaround then failed with
// "Applies-to Entry must not be filled out when reservations exist...".

// [GIVEN] Exact Cost Reversing Mandatory and a lot-tracked item.
Initialize();
UpdatePurchasesPayablesSetup(BaseExactCostReversingMand, true);
LibraryItemTracking.CreateLotItem(Item);
Quantity := 1;
LotNo := CopyStr(LibraryUtility.GenerateGUID(), 1, MaxStrLen(LotNo));

// [GIVEN] A posted purchase order (receive + invoice) with a specific lot assigned.
VendorNo := CreateAndPostPurchOrderWithLot(Item."No.", LotNo, Quantity);

// [GIVEN] A purchase return order populated via Get Posted Document Lines to Reverse.
LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader."Document Type"::"Return Order", VendorNo);
UpdatePurchaseHeader(PurchaseHeader);
PurchaseHeader.GetPstdDocLinesToReverse();

// [GIVEN] The return line is reserved from the current line against the receipt entry (specific lot).
PurchaseLine.SetRange("Document Type", PurchaseHeader."Document Type");
PurchaseLine.SetRange("Document No.", PurchaseHeader."No.");
PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);
PurchaseLine.FindFirst();
PurchaseLine.ShowReservation();

// [WHEN] Posting the purchase return order (ship + invoice).
LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, true);

// [THEN] The inbound receipt entry for the lot is fully reversed (exact cost reversing applied to the correct entry).
ItemLedgerEntry.SetRange("Item No.", Item."No.");
ItemLedgerEntry.SetRange("Entry Type", ItemLedgerEntry."Entry Type"::Purchase);
ItemLedgerEntry.SetRange("Lot No.", LotNo);
ItemLedgerEntry.SetRange(Positive, true);
ItemLedgerEntry.FindFirst();
ItemLedgerEntry.TestField("Remaining Quantity", 0);

// [THEN] A return (outbound) entry exists for the same lot.
ItemLedgerEntry.SetRange(Positive, false);
Assert.IsFalse(ItemLedgerEntry.IsEmpty(), 'Expected an outbound return entry for the reserved lot.');

// Tear Down.
UpdatePurchasesPayablesSetup(BaseExactCostReversingMand, BaseExactCostReversingMand);
LibraryVariableStorage.AssertEmpty();
end;

[Test]
[Scope('OnPrem')]
procedure PurchReturnItemAVGFIFO()
Expand Down Expand Up @@ -881,6 +946,22 @@ codeunit 137032 "SCM Costing Purch Returns II"
begin
end;

local procedure CreateAndPostPurchOrderWithLot(ItemNo: Code[20]; LotNo: Code[50]; Quantity: Decimal): Code[20]
var
PurchaseHeader: Record "Purchase Header";
PurchaseLine: Record "Purchase Line";
begin
LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader."Document Type"::Order, '');
LibraryPurchase.CreatePurchaseLine(PurchaseLine, PurchaseHeader, PurchaseLine.Type::Item, ItemNo, Quantity);
PurchaseLine.Validate("Direct Unit Cost", LibraryRandom.RandDec(100, 2) + 50);
PurchaseLine.Modify(true);
LibraryVariableStorage.Enqueue(LotNo); // Enqueue value for ItemTrackingLinesAssignLotPageHandler.
LibraryVariableStorage.Enqueue(Quantity); // Enqueue value for ItemTrackingLinesAssignLotPageHandler.
PurchaseLine.OpenItemTrackingLines();
LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, true);
exit(PurchaseHeader."Buy-from Vendor No.");
end;

[ModalPageHandler]
[Scope('OnPrem')]
procedure PostedPurchaseDocumentLinesModalHandler(var PostedPurchaseDocumentLinesPage: TestPage "Posted Purchase Document Lines")
Expand All @@ -895,5 +976,29 @@ codeunit 137032 "SCM Costing Purch Returns II"
begin
Reply := true;
end;

[ModalPageHandler]
[Scope('OnPrem')]
procedure ItemTrackingLinesAssignLotPageHandler(var ItemTrackingLines: TestPage "Item Tracking Lines")
begin
ItemTrackingLines."Lot No.".SetValue(LibraryVariableStorage.DequeueText());
ItemTrackingLines."Quantity (Base)".SetValue(LibraryVariableStorage.DequeueDecimal());
ItemTrackingLines.OK().Invoke();
end;

[ModalPageHandler]
[Scope('OnPrem')]
procedure ReservationReserveFromCurrentLinePageHandler(var Reservation: TestPage Reservation)
begin
Reservation."Reserve from Current Line".Invoke();
Reservation.OK().Invoke();
end;

[ModalPageHandler]
[Scope('OnPrem')]
procedure ItemTrackingListPageHandler(var ItemTrackingList: TestPage "Item Tracking List")
begin
ItemTrackingList.OK().Invoke();
end;
}

Loading