From fe0e73f1d49ebcb9205566db74fb9a757cde6e64 Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Tue, 23 Jun 2026 21:41:26 +0200 Subject: [PATCH 1/8] 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> (cherry picked from commit 63cfaf5464873514ee3b9b4969b9e34bb900af34) --- .../Purchase/SubcPurchaseHeader.TableExt.al | 3 +- .../Tests/SubcPurchSubcontTest.Codeunit.al | 73 +++++++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/Apps/W1/Subcontracting/App/src/Purchase/SubcPurchaseHeader.TableExt.al b/src/Apps/W1/Subcontracting/App/src/Purchase/SubcPurchaseHeader.TableExt.al index 8bcd4393c6..daaf18c68d 100644 --- a/src/Apps/W1/Subcontracting/App/src/Purchase/SubcPurchaseHeader.TableExt.al +++ b/src/Apps/W1/Subcontracting/App/src/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/Tests/SubcPurchSubcontTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al index 2335b62fe9..8cd0e88158 100644 --- a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al +++ b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al @@ -707,6 +707,79 @@ codeunit 139991 "Subc. Purch. Subcont. Test" Assert.RecordIsEmpty(PurchaseLine); 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 063770c28bac82e9a3f10a107fcbdeec99d5f89f Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Tue, 23 Jun 2026 23:26:16 +0200 Subject: [PATCH 2/8] 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 8cd0e88158..6c441e980f 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 fe7f6218534ad6d644c001dd41592fdeef2f6c87 Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Wed, 24 Jun 2026 09:59:15 +0200 Subject: [PATCH 3/8] 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 6c441e980f..01a0c4f6f9 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 ef4e265da23e48b5b3e77e246660238462043edb Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Wed, 24 Jun 2026 15:45:39 +0200 Subject: [PATCH 4/8] 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 01a0c4f6f9..4479a25338 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 b2c593230408d99df9f09c3421f4226898914cb8 Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Wed, 24 Jun 2026 15:59:54 +0200 Subject: [PATCH 5/8] 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 4479a25338..5fcbd0b3bc 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 0ac094403b196fc1baef92ac7fe7b38014e0fd18 Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah <41570277+ChethanT@users.noreply.github.com> Date: Wed, 24 Jun 2026 23:37:50 +0200 Subject: [PATCH 6/8] Apply suggestion from @ChethanT --- .../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 5fcbd0b3bc..17b54106b7 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 From 4df2a6f6b803482b21bf3626fff371b0de251726 Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah <41570277+ChethanT@users.noreply.github.com> Date: Wed, 24 Jun 2026 23:39:01 +0200 Subject: [PATCH 7/8] Apply suggestion from @ChethanT --- .../Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al index 17b54106b7..98b7945f5b 100644 --- a/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al +++ b/src/Apps/W1/Subcontracting/Test/Tests/SubcPurchSubcontTest.Codeunit.al @@ -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 cd58b967a198580bbc17aab1c58f8af8976f4994 Mon Sep 17 00:00:00 2001 From: Chethan Thopaiah Date: Thu, 25 Jun 2026 14:42:29 +0200 Subject: [PATCH 8/8] test fix --- .../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;