From 63cfaf5464873514ee3b9b4969b9e34bb900af34 Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Tue, 23 Jun 2026 21:41:26 +0200 Subject: [PATCH 1/7] Bug 640115: Fix Subc. Order FlowField to use Subc. Purchase Line Type The 'Subc. Order' FlowField on Purchase Header was checking base table fields 'Prod. Order No.' and 'Prod. Order Line No.' on Purchase Line. These fields are not reliably populated by the Subcontracting app's purchase order creation flow. Changed the CalcFormula to use 'Subc. Purchase Line Type' = filter(<> None), which is the extension field that the Subcontracting app reliably sets and is already used by the Manufacturing Cue for counting subcontracting lines. Added test SubcOrderFlowFieldIsTrueAfterCreatingSubcontractingPurchaseOrder to verify the FlowField evaluates correctly. Fixes AB#640115 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Purchase/SubcPurchaseHeader.TableExt.al | 3 +- .../Tests/SubcPurchSubcontTest.Codeunit.al | 74 +++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Tableextensions/Purchase/SubcPurchaseHeader.TableExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Tableextensions/Purchase/SubcPurchaseHeader.TableExt.al index 8bcd4393c6..daaf18c68d 100644 --- a/src/Apps/W1/Subcontracting/App/src/Process/Tableextensions/Purchase/SubcPurchaseHeader.TableExt.al +++ b/src/Apps/W1/Subcontracting/App/src/Process/Tableextensions/Purchase/SubcPurchaseHeader.TableExt.al @@ -34,8 +34,7 @@ tableextension 99001509 "Subc. Purchase Header" extends "Purchase Header" { CalcFormula = exist("Purchase Line" where("Document Type" = const(Order), "Document No." = field("No."), - "Prod. Order No." = filter(<> ''), - "Prod. Order Line No." = filter(<> 0))); + "Subc. Purchase Line Type" = filter(<> None))); Caption = 'Subcontracting Order'; Editable = false; FieldClass = FlowField; diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcPurchSubcontTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcPurchSubcontTest.Codeunit.al index f07c0afb34..04e21f5a07 100644 --- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcPurchSubcontTest.Codeunit.al +++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcPurchSubcontTest.Codeunit.al @@ -510,6 +510,80 @@ codeunit 139991 "Subc. Purch. Subcont. Test" PostDirectTransferOrder(ReturnTransferHeader); end; + + [Test] + [HandlerFunctions('DoConfirmCreateProdOrderForSubcontractingProcess')] + procedure SubcOrderFlowFieldIsTrueAfterCreatingSubcontractingPurchaseOrder() + var + FinishedItem: Record Item; + Location: Record Location; + ProdOrderRtngLine: Record "Prod. Order Routing Line"; + ProductionBOMHeader: Record "Production BOM Header"; + ProductionOrder: Record "Production Order"; + PurchaseHeader: Record "Purchase Header"; + PurchaseLine: Record "Purchase Line"; + RoutingHeader: Record "Routing Header"; + RoutingLine: Record "Routing Line"; + Vendor: Record Vendor; + WorkCenter: Record "Work Center"; + ReleasedProdOrderRtng: TestPage "Prod. Order Routing"; + begin + // [SCENARIO 640115] After creating a subcontracting purchase order from a Prod. Order Routing Line, + // the "Subc. Order" FlowField on the Purchase Header must evaluate to true so the order is visible + // in the "Subcontracting Orders" view of the Purchase Order List. + + Initialize(); + + // [GIVEN] A subcontracting work center with vendor and location + CreateAndCalculateNeededWorkCenter(WorkCenter, true); + Vendor.Get(WorkCenter."Subcontractor No."); + LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location); + Vendor."Subc. Location Code" := Location.Code; + Vendor.Modify(); + + // [GIVEN] A routing with a single subcontracting operation + LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial); + LibraryManufacturing.CreateRoutingLineSetup( + RoutingLine, RoutingHeader, WorkCenter."No.", '100', + LibraryRandom.RandInt(5), LibraryRandom.RandInt(5)); + RoutingHeader.Validate(Status, RoutingHeader.Status::Certified); + RoutingHeader.Modify(true); + + // [GIVEN] A finished good item with the routing + LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, WorkCenter."Unit of Measure Code"); + ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified); + ProductionBOMHeader.Modify(true); + LibraryManufacturing.CreateItemManufacturing( + FinishedItem, "Costing Method"::FIFO, LibraryRandom.RandInt(10), + "Reordering Policy"::"Lot-for-Lot", "Flushing Method"::"Pick + Manual", + RoutingHeader."No.", ProductionBOMHeader."No."); + + // [GIVEN] A released production order + SubcWarehouseLibrary.CreateAndRefreshProductionOrder( + ProductionOrder, "Production Order Status"::Released, + ProductionOrder."Source Type"::Item, FinishedItem."No.", LibraryRandom.RandInt(10), Location.Code); + + // [GIVEN] Requisition worksheet template for subcontracting + LibraryMfgManagement.CreateSubcontractingReqWkshTemplateAndNameAndUpdateSetup(); + + // [WHEN] Create subcontracting purchase order from Prod. Order Routing + ProdOrderRtngLine.SetRange("Routing No.", RoutingHeader."No."); + ProdOrderRtngLine.SetRange("Work Center No.", WorkCenter."No."); + ProdOrderRtngLine.FindFirst(); + + ReleasedProdOrderRtng.OpenView(); + ReleasedProdOrderRtng.GoToRecord(ProdOrderRtngLine); + ReleasedProdOrderRtng.CreateSubcontracting.Invoke(); + + // [THEN] A purchase order was created and the "Subc. Order" FlowField is true + PurchaseLine.SetRange("Document Type", PurchaseLine."Document Type"::Order); + PurchaseLine.SetRange("Prod. Order No.", ProductionOrder."No."); + PurchaseLine.FindFirst(); + PurchaseHeader.Get(PurchaseLine."Document Type", PurchaseLine."Document No."); + PurchaseHeader.CalcFields("Subc. Order"); + Assert.IsTrue(PurchaseHeader."Subc. Order", + 'The Subc. Order FlowField must be true for a subcontracting purchase order'); + end; [ModalPageHandler] procedure ItemTrackingLinesSimpleHandler(var ItemTrackingLines: TestPage "Item Tracking Lines") begin From 23e93e6c53a577fbf580bdee8fdb33ac4af61bfc Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Tue, 23 Jun 2026 23:26:16 +0200 Subject: [PATCH 2/7] Fix test: use item Base Unit of Measure for Production BOM Header WorkCenter.'Unit of Measure Code' is a capacity UOM that doesn't exist in the Unit of Measure table. Create the item first, then use its Base Unit of Measure for the Production BOM Header. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Test/Tests/SubcPurchSubcontTest.Codeunit.al | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al index 9471bee478..dc111791b4 100644 --- a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al +++ b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al @@ -746,13 +746,15 @@ codeunit 139991 "Subc. Purch. Subcont. Test" RoutingHeader.Modify(true); // [GIVEN] A finished good item with the routing - LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, WorkCenter."Unit of Measure Code"); - ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified); - ProductionBOMHeader.Modify(true); LibraryManufacturing.CreateItemManufacturing( FinishedItem, "Costing Method"::FIFO, LibraryRandom.RandInt(10), "Reordering Policy"::"Lot-for-Lot", "Flushing Method"::"Pick + Manual", - RoutingHeader."No.", ProductionBOMHeader."No."); + RoutingHeader."No.", ''); + LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, FinishedItem."Base Unit of Measure"); + ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified); + ProductionBOMHeader.Modify(true); + FinishedItem.Validate("Production BOM No.", ProductionBOMHeader."No."); + FinishedItem.Modify(true); // [GIVEN] A released production order SubcWarehouseLibrary.CreateAndRefreshProductionOrder( From 9636ff5efe4e59ce968a9bfb377dbb1157c226c6 Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Wed, 24 Jun 2026 09:59:15 +0200 Subject: [PATCH 3/7] Fix subcontracting purchase order test to use routing helper The test was trying to locate a Prod. Order Routing Line directly, but the existing helper already encapsulates the correct Type = Work Center filter and purchase order creation flow. Reuse it so the test targets the actual subcontracting scenario instead of depending on an incomplete lookup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Test/Tests/SubcPurchSubcontTest.Codeunit.al | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al index dc111791b4..c63bb6b634 100644 --- a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al +++ b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al @@ -713,7 +713,6 @@ codeunit 139991 "Subc. Purch. Subcont. Test" var FinishedItem: Record Item; Location: Record Location; - ProdOrderRtngLine: Record "Prod. Order Routing Line"; ProductionBOMHeader: Record "Production BOM Header"; ProductionOrder: Record "Production Order"; PurchaseHeader: Record "Purchase Header"; @@ -722,7 +721,6 @@ codeunit 139991 "Subc. Purch. Subcont. Test" RoutingLine: Record "Routing Line"; Vendor: Record Vendor; WorkCenter: Record "Work Center"; - ReleasedProdOrderRtng: TestPage "Prod. Order Routing"; begin // [SCENARIO 640115] After creating a subcontracting purchase order from a Prod. Order Routing Line, // the "Subc. Order" FlowField on the Purchase Header must evaluate to true so the order is visible @@ -765,18 +763,10 @@ codeunit 139991 "Subc. Purch. Subcont. Test" LibraryMfgManagement.CreateSubcontractingReqWkshTemplateAndNameAndUpdateSetup(); // [WHEN] Create subcontracting purchase order from Prod. Order Routing - ProdOrderRtngLine.SetRange("Routing No.", RoutingHeader."No."); - ProdOrderRtngLine.SetRange("Work Center No.", WorkCenter."No."); - ProdOrderRtngLine.FindFirst(); - - ReleasedProdOrderRtng.OpenView(); - ReleasedProdOrderRtng.GoToRecord(ProdOrderRtngLine); - ReleasedProdOrderRtng.CreateSubcontracting.Invoke(); + SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRouting( + RoutingHeader."No.", WorkCenter."No.", PurchaseLine); // [THEN] A purchase order was created and the "Subc. Order" FlowField is true - PurchaseLine.SetRange("Document Type", PurchaseLine."Document Type"::Order); - PurchaseLine.SetRange("Prod. Order No.", ProductionOrder."No."); - PurchaseLine.FindFirst(); PurchaseHeader.Get(PurchaseLine."Document Type", PurchaseLine."Document No."); PurchaseHeader.CalcFields("Subc. Order"); Assert.IsTrue(PurchaseHeader."Subc. Order", From 6749c1a40388f150e332b80f1f8a4f70b5018a42 Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Wed, 24 Jun 2026 15:45:39 +0200 Subject: [PATCH 4/7] Fix test helper call for subcontracting PO creation Use SubcWarehouseLibrary.CreateSubcontractingOrderFromProdOrderRouting, which exists on this branch, instead of a non-existent call on SubcontractingMgmtLibrary. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al index c63bb6b634..3243dd6bbf 100644 --- a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al +++ b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al @@ -763,7 +763,7 @@ codeunit 139991 "Subc. Purch. Subcont. Test" LibraryMfgManagement.CreateSubcontractingReqWkshTemplateAndNameAndUpdateSetup(); // [WHEN] Create subcontracting purchase order from Prod. Order Routing - SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRouting( + SubcWarehouseLibrary.CreateSubcontractingOrderFromProdOrderRouting( RoutingHeader."No.", WorkCenter."No.", PurchaseLine); // [THEN] A purchase order was created and the "Subc. Order" FlowField is true From a5286ef80e78aa743109acf22d8640b7f25e9138 Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Wed, 24 Jun 2026 15:59:54 +0200 Subject: [PATCH 5/7] Fix routing-line lookup in Subc. Order flowfield test Select the released Prod. Order Routing Line by production order and work center before invoking CreateSubcontracting. This avoids relying on a routing-no-based lookup that can miss the generated routing line. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Test/Tests/SubcPurchSubcontTest.Codeunit.al | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al index 3243dd6bbf..d025aa434c 100644 --- a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al +++ b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al @@ -713,10 +713,12 @@ codeunit 139991 "Subc. Purch. Subcont. Test" var FinishedItem: Record Item; Location: Record Location; + ProdOrderRtngLine: Record "Prod. Order Routing Line"; ProductionBOMHeader: Record "Production BOM Header"; ProductionOrder: Record "Production Order"; PurchaseHeader: Record "Purchase Header"; PurchaseLine: Record "Purchase Line"; + ReleasedProdOrderRtng: TestPage "Prod. Order Routing"; RoutingHeader: Record "Routing Header"; RoutingLine: Record "Routing Line"; Vendor: Record Vendor; @@ -763,8 +765,18 @@ codeunit 139991 "Subc. Purch. Subcont. Test" LibraryMfgManagement.CreateSubcontractingReqWkshTemplateAndNameAndUpdateSetup(); // [WHEN] Create subcontracting purchase order from Prod. Order Routing - SubcWarehouseLibrary.CreateSubcontractingOrderFromProdOrderRouting( - RoutingHeader."No.", WorkCenter."No.", PurchaseLine); + ProdOrderRtngLine.SetRange(Status, "Production Order Status"::Released); + ProdOrderRtngLine.SetRange("Prod. Order No.", ProductionOrder."No."); + ProdOrderRtngLine.SetRange(Type, ProdOrderRtngLine.Type::"Work Center"); + ProdOrderRtngLine.SetRange("Work Center No.", WorkCenter."No."); + ProdOrderRtngLine.FindFirst(); + ReleasedProdOrderRtng.OpenView(); + ReleasedProdOrderRtng.GoToRecord(ProdOrderRtngLine); + ReleasedProdOrderRtng.CreateSubcontracting.Invoke(); + + PurchaseLine.SetRange("Document Type", PurchaseLine."Document Type"::Order); + PurchaseLine.SetRange("Prod. Order No.", ProductionOrder."No."); + PurchaseLine.FindFirst(); // [THEN] A purchase order was created and the "Subc. Order" FlowField is true PurchaseHeader.Get(PurchaseLine."Document Type", PurchaseLine."Document No."); From d6f218154886a0703021ec21e79e46f08476d9de Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah <41570277+ChethanT@users.noreply.github.com> Date: Wed, 24 Jun 2026 23:32:40 +0200 Subject: [PATCH 6/7] test fix --- .../Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al index d025aa434c..fccf00e27a 100644 --- a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al +++ b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al @@ -718,11 +718,11 @@ codeunit 139991 "Subc. Purch. Subcont. Test" ProductionOrder: Record "Production Order"; PurchaseHeader: Record "Purchase Header"; PurchaseLine: Record "Purchase Line"; - ReleasedProdOrderRtng: TestPage "Prod. Order Routing"; RoutingHeader: Record "Routing Header"; RoutingLine: Record "Routing Line"; Vendor: Record Vendor; WorkCenter: Record "Work Center"; + ReleasedProdOrderRtng: TestPage "Prod. Order Routing"; begin // [SCENARIO 640115] After creating a subcontracting purchase order from a Prod. Order Routing Line, // the "Subc. Order" FlowField on the Purchase Header must evaluate to true so the order is visible @@ -754,6 +754,7 @@ codeunit 139991 "Subc. Purch. Subcont. Test" ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified); ProductionBOMHeader.Modify(true); FinishedItem.Validate("Production BOM No.", ProductionBOMHeader."No."); + FinishedITem.Validate("Routing No.", RoutingHeader."No."); FinishedItem.Modify(true); // [GIVEN] A released production order From 1fe00bd5d9cf89e93e63fbf4a2bd007eed19184e Mon Sep 17 00:00:00 2001 From: alexei-dobriansky <77933119+alexei-dobriansky@users.noreply.github.com> Date: Fri, 26 Jun 2026 10:14:07 +0200 Subject: [PATCH 7/7] fix test --- .../Test/Tests/SubcLocationHandlerTest.Codeunit.al | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Apps/W1/Subcontracting/Test/Tests/SubcLocationHandlerTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/Tests/SubcLocationHandlerTest.Codeunit.al index c1a90353f3..6e7b1a62ae 100644 --- a/src/Apps/W1/Subcontracting/Test/Tests/SubcLocationHandlerTest.Codeunit.al +++ b/src/Apps/W1/Subcontracting/Test/Tests/SubcLocationHandlerTest.Codeunit.al @@ -499,6 +499,9 @@ codeunit 139981 "Subc. Location Handler Test" PurchaseLine."Routing No." := ProdOrderRtngLine."Routing No."; PurchaseLine."Operation No." := ProdOrderRtngLine."Operation No."; PurchaseLine."Routing Reference No." := ProdOrderRtngLine."Routing Reference No."; + // Mirror SetSubcontractingLineType() since fields are assigned directly (no Validate trigger). + // The single routing line created here is the last operation, so the type is LastOperation. + PurchaseLine."Subc. Purchase Line Type" := PurchaseLine."Subc. Purchase Line Type"::LastOperation; PurchaseLine.Modify(); end;