From 0627dfc2f89c7e201d1950dd63b8f5092f1d787c Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Wed, 20 May 2026 13:08:30 +0200 Subject: [PATCH 1/2] Fix excess reservations on subcontracting transfer orders (bugs 634399, 634236) When a subcontracting purchase order quantity is reduced and the production order component has reservations exceeding the new transfer line quantity, block transfer order creation with a clear error message instructing the user to cancel existing reservations first. This prevents inconsistent data states where reservation quantities exceed transfer line quantities, avoiding downstream issues with item tracking and reservation entry corruption. Fixes AB#634399 Fixes AB#634236 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../SubcontractingManagement.Codeunit.al | 24 +- .../Reports/SubcCreateTransfOrder.Report.al | 4 + .../Tests/SubcTransfOrdReservTest.Codeunit.al | 403 ++++++++++++++++++ 3 files changed, 430 insertions(+), 1 deletion(-) create mode 100644 src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransfOrdReservTest.Codeunit.al diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcontractingManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcontractingManagement.Codeunit.al index 2bc34271eb..f9439c0cca 100644 --- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcontractingManagement.Codeunit.al +++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcontractingManagement.Codeunit.al @@ -256,7 +256,7 @@ codeunit 99001505 "Subcontracting Management" TransferLine."Variant Code", TransferLine."Transfer-from Code", true, - 0, + TransferLine."Quantity (Base)", TransferLine."Qty. per Unit of Measure", Database::"Transfer Line", 0, // Direction::Outbound @@ -266,6 +266,28 @@ codeunit 99001505 "Subcontracting Management" TransferLine."Line No."); end; + procedure ComponentHasExcessReservations(ProdOrderComponent: Record "Prod. Order Component"; MaxQtyBase: Decimal): Boolean + begin + exit(GetComponentReservedQtyBase(ProdOrderComponent) > MaxQtyBase); + end; + + procedure GetComponentReservedQtyBase(ProdOrderComponent: Record "Prod. Order Component"): Decimal + var + ReservationEntry: Record "Reservation Entry"; + ProdOrderCompReserve: Codeunit "Prod. Order Comp.-Reserve"; + TotalReservedQtyBase: Decimal; + begin + if not ProdOrderCompReserve.FindReservEntry(ProdOrderComponent, ReservationEntry) then + exit(0); + + if ReservationEntry.FindSet() then + repeat + TotalReservedQtyBase += Abs(ReservationEntry."Quantity (Base)"); + until ReservationEntry.Next() = 0; + + exit(TotalReservedQtyBase); + end; + procedure CreateReservEntryForTransferReceiptToProdOrderComp( TransferLine: Record "Transfer Line"; ProdOrderComponent: Record "Prod. Order Component") diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Reports/SubcCreateTransfOrder.Report.al b/src/Apps/W1/Subcontracting/App/src/Process/Reports/SubcCreateTransfOrder.Report.al index 370679d5f9..2537e15c1a 100644 --- a/src/Apps/W1/Subcontracting/App/src/Process/Reports/SubcCreateTransfOrder.Report.al +++ b/src/Apps/W1/Subcontracting/App/src/Process/Reports/SubcCreateTransfOrder.Report.al @@ -66,6 +66,7 @@ report 99001501 "Subc. Create Transf. Order" Vendor: Record Vendor; PurchOrderNo: Code[20]; LineNo: Integer; + ExcessReservationsErr: Label 'The transfer quantity (%1) is less than the reserved quantity (%2) on the production order component for item %3. Cancel existing reservations on the component before creating a partial transfer.', Comment = '%1=Transfer Quantity, %2=Reserved Quantity, %3=Item No.'; NothingToCreateErr: Label 'Nothing to create. No components or WIP to transfer for the specified subcontracting order.'; OrderNoDoesNotExistInProdOrderErr: Label 'Operation %1 in the subcontracting order %2 does not exist in the routing %3 of the production order %4.', Comment = '%1=Operation No., %2=Purchase Order No., %3=Routing No., %4=Production Order No.'; OrderNoIsNotSubcontractorErr: Label 'Order %1 is not a Subcontractor work.', Comment = '%1=Purchase Order No.'; @@ -229,6 +230,9 @@ report 99001501 "Subc. Create Transf. Order" if ProdOrderComponent."Subc. Orig. Bin Code" = '' then ProdOrderComponent."Subc. Orig. Bin Code" := ProdOrderComponent."Bin Code"; + if SubcontractingManagement.ComponentHasExcessReservations(ProdOrderComponent, TransferLine."Quantity (Base)") then + Error(ExcessReservationsErr, TransferLine."Quantity (Base)", SubcontractingManagement.GetComponentReservedQtyBase(ProdOrderComponent), ProdOrderComponent."Item No."); + SubcontractingManagement.TransferReservationEntryFromProdOrderCompToTransferOrder(TransferLine, ProdOrderComponent); if TransferHeader."Transfer-to Code" <> ProdOrderComponent."Location Code" then begin if Item."Order Tracking Policy" = Item."Order Tracking Policy"::None then diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransfOrdReservTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransfOrdReservTest.Codeunit.al new file mode 100644 index 0000000000..f1c69678dc --- /dev/null +++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransfOrdReservTest.Codeunit.al @@ -0,0 +1,403 @@ +// ------------------------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// ------------------------------------------------------------------------------------------------ +namespace Microsoft.Manufacturing.Subcontracting.Test; + +using Microsoft.Foundation.NoSeries; +using Microsoft.Inventory.Item; +using Microsoft.Inventory.Tracking; +using Microsoft.Inventory.Transfer; +using Microsoft.Manufacturing.Capacity; +using Microsoft.Manufacturing.Document; +using Microsoft.Manufacturing.MachineCenter; +using Microsoft.Manufacturing.ProductionBOM; +using Microsoft.Manufacturing.Setup; +using Microsoft.Manufacturing.Subcontracting; +using Microsoft.Manufacturing.WorkCenter; +using Microsoft.Purchases.Document; +using System.TestLibraries.Utilities; + +codeunit 149915 "Subc. Transf. Ord. Reserv. Test" +{ + // [FEATURE] Subcontracting Transfer Order Reservation Integration Tests + Subtype = Test; + TestPermissions = Disabled; + TestType = IntegrationTest; + + trigger OnRun() + begin + IsInitialized := false; + end; + + [Test] + [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting,HandleTransferOrder')] + procedure FullQuantityTransferTransfersAllReservationsWithoutConfirm() + var + Item: Record Item; + ProdOrderComponent: Record "Prod. Order Component"; + ProductionOrder: Record "Production Order"; + PurchaseHeader: Record "Purchase Header"; + PurchaseLine: Record "Purchase Line"; + TransferLine: Record "Transfer Line"; + WorkCenter: array[2] of Record "Work Center"; + MachineCenter: array[2] of Record "Machine Center"; + begin + // [SCENARIO] Full quantity transfer moves all component reservations to the transfer order without showing the excess cancellation message. + + // [GIVEN] A transfer-subcontracting production order with a transfer component quantity of 30 and matching component reservations + Initialize(); + SetupTransferReservationScenario(Item, WorkCenter, MachineCenter, ProductionOrder, ProdOrderComponent, 10, 3, false); + CreateReservationOnProdOrderComp(ProdOrderComponent, 30, ProdOrderComponent."Location Code"); + + // [WHEN] A subcontracting purchase order is created for the full production quantity and a transfer order is created from it + CreateSubcontractingPurchaseOrderAndReduceQuantity(Item, WorkCenter[2], ProductionOrder, PurchaseHeader, PurchaseLine, 0); + CreateTransferOrder(PurchaseHeader); + FindTransferLine(TransferLine, ProductionOrder, ProdOrderComponent); + + // [THEN] All reservations are transferred to the transfer line and no excess reservation confirm dialog is shown + TransferLine.CalcFields("Reserved Qty. Outbnd. (Base)"); + Assert.AreEqual(30, TransferLine."Quantity (Base)", 'Transfer line base qty mismatch'); + Assert.AreEqual(30, TransferLine."Reserved Qty. Outbnd. (Base)", 'Reserved qty outbound must match transfer qty'); + end; + + [Test] + [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')] + procedure PartialQuantityWithReservationsBlocksTransferCreation() + var + Item: Record Item; + ProdOrderComponent: Record "Prod. Order Component"; + ProductionOrder: Record "Production Order"; + PurchaseHeader: Record "Purchase Header"; + PurchaseLine: Record "Purchase Line"; + TransferLine: Record "Transfer Line"; + WorkCenter: array[2] of Record "Work Center"; + MachineCenter: array[2] of Record "Machine Center"; + begin + // [SCENARIO 634236] Creating a transfer order when the transfer quantity is less than the reserved quantity on the component must be blocked with an error. + + // [GIVEN] A released production order with quantity 10, transfer component quantity per 3, and 30 reserved component quantity + Initialize(); + SetupTransferReservationScenario(Item, WorkCenter, MachineCenter, ProductionOrder, ProdOrderComponent, 10, 3, false); + CreateReservationOnProdOrderComp(ProdOrderComponent, 30, ProdOrderComponent."Location Code"); + + // [WHEN] The subcontracting purchase order quantity is reduced from 10 to 6 before the transfer order is created + CreateSubcontractingPurchaseOrderAndReduceQuantity(Item, WorkCenter[2], ProductionOrder, PurchaseHeader, PurchaseLine, 6); + asserterror CreateTransferOrder(PurchaseHeader); + + // [THEN] Transfer creation is blocked and reservations on the component remain intact + Assert.ExpectedError('Cancel existing reservations on the component before creating a partial transfer'); +#pragma warning disable AA0210 + TransferLine.SetRange("Subc. Prod. Order No.", ProductionOrder."No."); +#pragma warning restore AA0210 + Assert.RecordIsEmpty(TransferLine); + Assert.AreEqual(1, CountProdOrderComponentReservations(ProdOrderComponent), 'Reservations on the component must remain intact when transfer is blocked'); + end; + + [Test] + [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')] + procedure PartialQuantitySerialReservationsBlocksTransferCreation() + var + Item: Record Item; + ProdOrderComponent: Record "Prod. Order Component"; + ProductionOrder: Record "Production Order"; + PurchaseHeader: Record "Purchase Header"; + PurchaseLine: Record "Purchase Line"; + TransferLine: Record "Transfer Line"; + WorkCenter: array[2] of Record "Work Center"; + MachineCenter: array[2] of Record "Machine Center"; + begin + // [SCENARIO 634399] Creating a transfer order with serial-tracked component reservations when the transfer quantity is less than the reserved quantity must be blocked. + + // [GIVEN] A released production order with quantity 3, transfer component quantity per 2, and 6 serial-number component reservations + Initialize(); + SetupTransferReservationScenario(Item, WorkCenter, MachineCenter, ProductionOrder, ProdOrderComponent, 3, 2, true); + CreateSerialReservationsOnProdOrderComp(ProdOrderComponent, 6, ProdOrderComponent."Location Code"); + + // [WHEN] The subcontracting purchase order quantity is reduced from 3 to 2 before the transfer order is created + CreateSubcontractingPurchaseOrderAndReduceQuantity(Item, WorkCenter[2], ProductionOrder, PurchaseHeader, PurchaseLine, 2); + asserterror CreateTransferOrder(PurchaseHeader); + + // [THEN] Transfer creation is blocked and serial reservations on the component remain intact + Assert.ExpectedError('Cancel existing reservations on the component before creating a partial transfer'); +#pragma warning disable AA0210 + TransferLine.SetRange("Subc. Prod. Order No.", ProductionOrder."No."); +#pragma warning restore AA0210 + Assert.RecordIsEmpty(TransferLine); + Assert.AreEqual(6, CountProdOrderComponentReservations(ProdOrderComponent), 'Serial reservations on the component must remain intact when transfer is blocked'); + end; + + [Test] + [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting,HandleTransferOrder')] + procedure PartialQuantityWithoutReservationsAllowsTransferCreation() + var + Item: Record Item; + ProdOrderComponent: Record "Prod. Order Component"; + ProductionOrder: Record "Production Order"; + PurchaseHeader: Record "Purchase Header"; + PurchaseLine: Record "Purchase Line"; + TransferLine: Record "Transfer Line"; + WorkCenter: array[2] of Record "Work Center"; + MachineCenter: array[2] of Record "Machine Center"; + begin + // [SCENARIO] Reducing the subcontracting PO quantity when the component has no reservations must allow transfer creation without error. + + // [GIVEN] A released production order with quantity 10, transfer component quantity per 3, and NO reservations + Initialize(); + SetupTransferReservationScenario(Item, WorkCenter, MachineCenter, ProductionOrder, ProdOrderComponent, 10, 3, false); + + // [WHEN] The subcontracting purchase order quantity is reduced from 10 to 6 and a transfer order is created + CreateSubcontractingPurchaseOrderAndReduceQuantity(Item, WorkCenter[2], ProductionOrder, PurchaseHeader, PurchaseLine, 6); + CreateTransferOrder(PurchaseHeader); + + // [THEN] Transfer line is created with the reduced quantity without error +#pragma warning disable AA0210 + TransferLine.SetRange("Subc. Prod. Order No.", ProductionOrder."No."); +#pragma warning restore AA0210 + TransferLine.FindFirst(); + Assert.AreEqual(18, TransferLine."Quantity (Base)", 'Transfer line base qty should reflect the reduced PO qty'); + end; + + local procedure Initialize() + begin + OpenedTransferOrderNo := ''; + + LibraryTestInitialize.OnTestInitialize(Codeunit::"Subc. Transf. Ord. Reserv. Test"); + LibrarySetupStorage.Restore(); + + SubcontractingMgmtLibrary.Initialize(); + SubcontractingMgmtLibrary.UpdateSubMgmtSetup_ComponentAtLocation("Components at Location"::Purchase); + LibraryVariableStorage.Clear(); + LibraryMfgManagement.Initialize(); + + if IsInitialized then + exit; + + LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Subc. Transf. Ord. Reserv. Test"); + + SubSetupLibrary.InitSetupFields(); + LibraryERMCountryData.CreateVATData(); + SubSetupLibrary.InitialSetupForGenProdPostingGroup(); + + IsInitialized := true; + Commit(); + + LibraryTestInitialize.OnAfterTestSuiteInitialize(Codeunit::"Subc. Transf. Ord. Reserv. Test"); + end; + + local procedure SetupTransferReservationScenario(var Item: Record Item; var WorkCenter: array[2] of Record "Work Center"; var MachineCenter: array[2] of Record "Machine Center"; var ProductionOrder: Record "Production Order"; var ProdOrderComponent: Record "Prod. Order Component"; ProductionQty: Decimal; ComponentQtyPer: Decimal; SerialTrackedComponent: Boolean) + begin + SubcontractingMgmtLibrary.UpdateManufacturingSetupWithSubcontractingLocation(); + SubcontractingMgmtLibrary.SetupInventorySetup(); + + SubcWarehouseLibrary.CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter, true); + SubcWarehouseLibrary.CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter); + SubcWarehouseLibrary.UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2]."No."); + SubcontractingMgmtLibrary.UpdateProdBomWithSubcontractingType(Item, "Subcontracting Type"::Transfer); + UpdateTransferComponentQuantityPer(Item, ComponentQtyPer); + if SerialTrackedComponent then + EnableSerialTrackingOnTransferComponent(Item); + SubcontractingMgmtLibrary.UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]); + + SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder( + ProductionOrder, "Production Order Status"::Released, ProductionOrder."Source Type"::Item, Item."No.", ProductionQty); + SubcWarehouseLibrary.UpdateSubMgmtSetupWithReqWkshTemplate(); + SubcontractingMgmtLibrary.UpdateProdOrderCompWithLocationCode(ProductionOrder."No."); + SubcontractingMgmtLibrary.CreateTransferRoute(WorkCenter[2], ProductionOrder); + FindTransferProdOrderComponent(ProdOrderComponent, ProductionOrder); + end; + + local procedure UpdateTransferComponentQuantityPer(Item: Record Item; ComponentQtyPer: Decimal) + var + ProductionBOMHeader: Record "Production BOM Header"; + ProductionBOMLine: Record "Production BOM Line"; + begin + ProductionBOMHeader.Get(Item."Production BOM No."); + ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::New); + ProductionBOMHeader.Modify(true); + + ProductionBOMLine.SetRange("Production BOM No.", ProductionBOMHeader."No."); + ProductionBOMLine.FindLast(); + ProductionBOMLine.Validate("Quantity per", ComponentQtyPer); + ProductionBOMLine.Modify(true); + + ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified); + ProductionBOMHeader.Modify(true); + end; + + local procedure EnableSerialTrackingOnTransferComponent(Item: Record Item) + var + ComponentItem: Record Item; + ProductionBOMLine: Record "Production BOM Line"; + ItemTrackingCode: Record "Item Tracking Code"; + SerialNoSeries: Record "No. Series"; + SerialNoSeriesLine: Record "No. Series Line"; + begin + ProductionBOMLine.SetRange("Production BOM No.", Item."Production BOM No."); + ProductionBOMLine.FindLast(); + ComponentItem.Get(ProductionBOMLine."No."); + + LibraryUtility.CreateNoSeries(SerialNoSeries, true, true, false); + LibraryUtility.CreateNoSeriesLine( + SerialNoSeriesLine, SerialNoSeries.Code, + PadStr(Format(CurrentDateTime(), 0, 'S'), 19, '0'), + PadStr(Format(CurrentDateTime(), 0, 'S'), 19, '9')); + LibraryItemTracking.CreateItemTrackingCode(ItemTrackingCode, true, false, false); + + ComponentItem.Validate("Item Tracking Code", ItemTrackingCode.Code); + ComponentItem.Validate("Serial Nos.", SerialNoSeries.Code); + ComponentItem.Modify(true); + end; + + local procedure CreateSubcontractingPurchaseOrderAndReduceQuantity(Item: Record Item; WorkCenter: Record "Work Center"; ProductionOrder: Record "Production Order"; var PurchaseHeader: Record "Purchase Header"; var PurchaseLine: Record "Purchase Line"; ReducedQty: Decimal) + begin + SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item."Routing No.", WorkCenter."No."); + + PurchaseLine.SetRange("Document Type", "Purchase Document Type"::Order); +#pragma warning disable AA0210 + PurchaseLine.SetRange("Prod. Order No.", ProductionOrder."No."); +#pragma warning restore AA0210 + PurchaseLine.FindFirst(); + + if ReducedQty <> 0 then begin + PurchaseLine.Validate(Quantity, ReducedQty); + PurchaseLine.Modify(true); + end; + + PurchaseHeader.Get(PurchaseLine."Document Type", PurchaseLine."Document No."); + end; + + local procedure CreateTransferOrder(PurchaseHeader: Record "Purchase Header") + var + PurchaseHeaderPage: TestPage "Purchase Order"; + begin + PurchaseHeaderPage.OpenView(); + PurchaseHeaderPage.GoToRecord(PurchaseHeader); + PurchaseHeaderPage.CreateTransfOrdToSubcontractor.Invoke(); + PurchaseHeaderPage.Close(); + end; + + local procedure FindTransferProdOrderComponent(var ProdOrderComponent: Record "Prod. Order Component"; ProductionOrder: Record "Production Order") + begin + ProdOrderComponent.SetRange(Status, ProductionOrder.Status); + ProdOrderComponent.SetRange("Prod. Order No.", ProductionOrder."No."); +#pragma warning disable AA0210 + ProdOrderComponent.SetRange("Subcontracting Type", ProdOrderComponent."Subcontracting Type"::Transfer); +#pragma warning restore AA0210 + ProdOrderComponent.FindFirst(); + end; + + local procedure FindTransferLine(var TransferLine: Record "Transfer Line"; ProductionOrder: Record "Production Order"; ProdOrderComponent: Record "Prod. Order Component") + begin +#pragma warning disable AA0210 + TransferLine.SetRange("Subc. Prod. Order No.", ProductionOrder."No."); +#pragma warning restore AA0210 + TransferLine.SetRange("Item No.", ProdOrderComponent."Item No."); + TransferLine.SetRange("Subc. Prod. Ord. Comp Line No.", ProdOrderComponent."Line No."); + TransferLine.FindFirst(); + end; + + local procedure CreateReservationOnProdOrderComp(ProdOrderComponent: Record "Prod. Order Component"; Qty: Decimal; LocationCode: Code[10]) + var + ReservationEntry: Record "Reservation Entry"; + EntryNo: Integer; + begin + if ReservationEntry.FindLast() then + EntryNo := ReservationEntry."Entry No." + 1 + else + EntryNo := 1; + + ReservationEntry.Init(); + ReservationEntry."Entry No." := EntryNo; + ReservationEntry.Positive := false; + ReservationEntry."Item No." := ProdOrderComponent."Item No."; + ReservationEntry."Location Code" := LocationCode; + ReservationEntry."Qty. per Unit of Measure" := ProdOrderComponent."Qty. per Unit of Measure"; + ReservationEntry."Reservation Status" := ReservationEntry."Reservation Status"::Reservation; + ReservationEntry."Source Type" := Database::"Prod. Order Component"; + ReservationEntry."Source Subtype" := ProdOrderComponent.Status.AsInteger(); + ReservationEntry."Source ID" := ProdOrderComponent."Prod. Order No."; + ReservationEntry."Source Prod. Order Line" := ProdOrderComponent."Prod. Order Line No."; + ReservationEntry."Source Ref. No." := ProdOrderComponent."Line No."; + ReservationEntry.Quantity := -Qty; + ReservationEntry."Quantity (Base)" := -Qty; + ReservationEntry.Insert(); + end; + + local procedure CreateSerialReservationsOnProdOrderComp(ProdOrderComponent: Record "Prod. Order Component"; Qty: Integer; LocationCode: Code[10]) + var + i: Integer; + begin + for i := 1 to Qty do + CreateSerialReservationOnProdOrderComp(ProdOrderComponent, LocationCode, CopyStr(StrSubstNo('SN%1', i), 1, 50)); + end; + + local procedure CreateSerialReservationOnProdOrderComp(ProdOrderComponent: Record "Prod. Order Component"; LocationCode: Code[10]; SerialNo: Code[50]) + var + ReservationEntry: Record "Reservation Entry"; + EntryNo: Integer; + begin + if ReservationEntry.FindLast() then + EntryNo := ReservationEntry."Entry No." + 1 + else + EntryNo := 1; + + ReservationEntry.Init(); + ReservationEntry."Entry No." := EntryNo; + ReservationEntry.Positive := false; + ReservationEntry."Item No." := ProdOrderComponent."Item No."; + ReservationEntry."Location Code" := LocationCode; + ReservationEntry."Qty. per Unit of Measure" := ProdOrderComponent."Qty. per Unit of Measure"; + ReservationEntry."Reservation Status" := ReservationEntry."Reservation Status"::Reservation; + ReservationEntry."Serial No." := SerialNo; + ReservationEntry."Source Type" := Database::"Prod. Order Component"; + ReservationEntry."Source Subtype" := ProdOrderComponent.Status.AsInteger(); + ReservationEntry."Source ID" := ProdOrderComponent."Prod. Order No."; + ReservationEntry."Source Prod. Order Line" := ProdOrderComponent."Prod. Order Line No."; + ReservationEntry."Source Ref. No." := ProdOrderComponent."Line No."; + ReservationEntry.Quantity := -1; + ReservationEntry."Quantity (Base)" := -1; + ReservationEntry.Insert(); + end; + + local procedure CountProdOrderComponentReservations(ProdOrderComponent: Record "Prod. Order Component"): Integer + var + ReservationEntry: Record "Reservation Entry"; + begin + ReservationEntry.SetRange("Reservation Status", ReservationEntry."Reservation Status"::Reservation); + ReservationEntry.SetRange("Source Type", Database::"Prod. Order Component"); + ReservationEntry.SetRange("Source Subtype", ProdOrderComponent.Status.AsInteger()); + ReservationEntry.SetRange("Source ID", ProdOrderComponent."Prod. Order No."); + ReservationEntry.SetRange("Source Prod. Order Line", ProdOrderComponent."Prod. Order Line No."); + ReservationEntry.SetRange("Source Ref. No.", ProdOrderComponent."Line No."); + exit(ReservationEntry.Count()); + end; + + [PageHandler] + procedure HandleTransferOrder(var TransfOrderPage: TestPage "Transfer Order") + begin + OpenedTransferOrderNo := CopyStr(TransfOrderPage."No.".Value(), 1, MaxStrLen(OpenedTransferOrderNo)); + TransfOrderPage.OK().Invoke(); + end; + + [ConfirmHandler] + procedure DoNotConfirmShowCreatedPurchOrderForSubcontracting(Question: Text[1024]; var Reply: Boolean) + begin + Reply := false; + end; + + var + Assert: Codeunit Assert; + LibraryERMCountryData: Codeunit "Library - ERM Country Data"; + LibraryItemTracking: Codeunit "Library - Item Tracking"; + LibrarySetupStorage: Codeunit "Library - Setup Storage"; + LibraryTestInitialize: Codeunit "Library - Test Initialize"; + LibraryMfgManagement: Codeunit "Subc. Library Mfg. Management"; + LibraryUtility: Codeunit "Library - Utility"; + LibraryVariableStorage: Codeunit "Library - Variable Storage"; + SubcontractingMgmtLibrary: Codeunit "Subc. Management Library"; + SubSetupLibrary: Codeunit "Subc. Setup Library"; + SubcWarehouseLibrary: Codeunit "Subc. Warehouse Library"; + IsInitialized: Boolean; + OpenedTransferOrderNo: Code[20]; +} \ No newline at end of file From a386f161bf91ffec66534695262df8d53d60e5c1 Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Thu, 21 May 2026 23:18:49 +0200 Subject: [PATCH 2/2] renamed test codeunit --- ...it.al => SubcTransOrdReservTest.Codeunit.al} | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) rename src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/{SubcTransfOrdReservTest.Codeunit.al => SubcTransOrdReservTest.Codeunit.al} (98%) diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransfOrdReservTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al similarity index 98% rename from src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransfOrdReservTest.Codeunit.al rename to src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al index f1c69678dc..fbe602172f 100644 --- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransfOrdReservTest.Codeunit.al +++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al @@ -8,23 +8,24 @@ using Microsoft.Foundation.NoSeries; using Microsoft.Inventory.Item; using Microsoft.Inventory.Tracking; using Microsoft.Inventory.Transfer; -using Microsoft.Manufacturing.Capacity; using Microsoft.Manufacturing.Document; using Microsoft.Manufacturing.MachineCenter; using Microsoft.Manufacturing.ProductionBOM; -using Microsoft.Manufacturing.Setup; using Microsoft.Manufacturing.Subcontracting; using Microsoft.Manufacturing.WorkCenter; using Microsoft.Purchases.Document; using System.TestLibraries.Utilities; -codeunit 149915 "Subc. Transf. Ord. Reserv. Test" +codeunit 149915 "Subc. TransOrd. Reserv. Test" { // [FEATURE] Subcontracting Transfer Order Reservation Integration Tests Subtype = Test; TestPermissions = Disabled; TestType = IntegrationTest; + var + SerialNoTok: Label 'SN%1', Comment = '%1 = number'; + trigger OnRun() begin IsInitialized := false; @@ -160,9 +161,7 @@ codeunit 149915 "Subc. Transf. Ord. Reserv. Test" local procedure Initialize() begin - OpenedTransferOrderNo := ''; - - LibraryTestInitialize.OnTestInitialize(Codeunit::"Subc. Transf. Ord. Reserv. Test"); + LibraryTestInitialize.OnTestInitialize(Codeunit::"Subc. TransOrd. Reserv. Test"); LibrarySetupStorage.Restore(); SubcontractingMgmtLibrary.Initialize(); @@ -173,7 +172,7 @@ codeunit 149915 "Subc. Transf. Ord. Reserv. Test" if IsInitialized then exit; - LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Subc. Transf. Ord. Reserv. Test"); + LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Subc. TransOrd. Reserv. Test"); SubSetupLibrary.InitSetupFields(); LibraryERMCountryData.CreateVATData(); @@ -182,7 +181,7 @@ codeunit 149915 "Subc. Transf. Ord. Reserv. Test" IsInitialized := true; Commit(); - LibraryTestInitialize.OnAfterTestSuiteInitialize(Codeunit::"Subc. Transf. Ord. Reserv. Test"); + LibraryTestInitialize.OnAfterTestSuiteInitialize(Codeunit::"Subc. TransOrd. Reserv. Test"); end; local procedure SetupTransferReservationScenario(var Item: Record Item; var WorkCenter: array[2] of Record "Work Center"; var MachineCenter: array[2] of Record "Machine Center"; var ProductionOrder: Record "Production Order"; var ProdOrderComponent: Record "Prod. Order Component"; ProductionQty: Decimal; ComponentQtyPer: Decimal; SerialTrackedComponent: Boolean) @@ -329,7 +328,7 @@ codeunit 149915 "Subc. Transf. Ord. Reserv. Test" i: Integer; begin for i := 1 to Qty do - CreateSerialReservationOnProdOrderComp(ProdOrderComponent, LocationCode, CopyStr(StrSubstNo('SN%1', i), 1, 50)); + CreateSerialReservationOnProdOrderComp(ProdOrderComponent, LocationCode, CopyStr(StrSubstNo(SerialNoTok, i), 1, 50)); end; local procedure CreateSerialReservationOnProdOrderComp(ProdOrderComponent: Record "Prod. Order Component"; LocationCode: Code[10]; SerialNo: Code[50])