From 19b8c585350f842a07cd4bb2a2ba25af75bd9011 Mon Sep 17 00:00:00 2001 From: ventselartur Date: Tue, 23 Jun 2026 20:12:06 +0200 Subject: [PATCH] Fix: disable Open TO from PO actions on non-subcontracting lines Bug #638531: [Subcontracting] Open TO from PO action only works from main item line Root Cause: - The "Transfer Order" and "Return Transfer Order" actions in pageextension 99001524 "Subc. PO Subform" call ShowTransferOrdersAndReturnOrder(Rec, ...), which requires the current line's Prod. Order No. and silently exits when it is empty. The actions were gated only at document level (Visible = HasSubcontractingContext), so on a component/non-subcontracting line they stayed enabled but did nothing. Changes: - Add OnAfterGetCurrRecord computing CurrentLineIsSubcontractingLine via Subcontracting Management.IsSubcontractingPurchaseLine(Rec). - Set Enabled = CurrentLineIsSubcontractingLine on action("Transfer Order") and action("Return Transfer Order") so they are disabled on non-subcontracting lines. Test Coverage: - New test TransferOrderActionDisabledOnNonSubcontractingPurchaseLine in codeunit 139989 asserts the action is enabled on a subcontracting line and disabled on a non-subcontracting line on the same order. Verified red without the fix (deterministic across 3 runs) and green with the fix. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../App/src/Purchase/SubcPOSubform.PageExt.al | 9 +++ .../Tests/SubcSubcontractingTest.Codeunit.al | 68 +++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/src/Apps/W1/Subcontracting/App/src/Purchase/SubcPOSubform.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Purchase/SubcPOSubform.PageExt.al index 039907685a..299a4be9e8 100644 --- a/src/Apps/W1/Subcontracting/App/src/Purchase/SubcPOSubform.PageExt.al +++ b/src/Apps/W1/Subcontracting/App/src/Purchase/SubcPOSubform.PageExt.al @@ -64,6 +64,7 @@ pageextension 99001524 "Subc. PO Subform" extends "Purchase Order Subform" { ApplicationArea = Subcontracting; Caption = 'Subcontracting Transfer Order'; + Enabled = CurrentLineIsSubcontractingLine; Image = TransferOrder; ToolTip = 'View the related transfer order.'; trigger OnAction() @@ -75,6 +76,7 @@ pageextension 99001524 "Subc. PO Subform" extends "Purchase Order Subform" { ApplicationArea = Subcontracting; Caption = 'Subcontracting Return Transfer Order'; + Enabled = CurrentLineIsSubcontractingLine; Image = ReturnRelated; ToolTip = 'View the related return transfer order.'; trigger OnAction() @@ -89,7 +91,14 @@ pageextension 99001524 "Subc. PO Subform" extends "Purchase Order Subform" var SubcProdOrderFactboxMgmt: Codeunit "Subc. ProdO. Factbox Mgmt."; SubcPurchFactboxMgmt: Codeunit "Subc. Purch. Factbox Mgmt."; + SubcontractingManagement: Codeunit "Subcontracting Management"; HasSubcontractingContext: Boolean; + CurrentLineIsSubcontractingLine: Boolean; + + trigger OnAfterGetCurrRecord() + begin + CurrentLineIsSubcontractingLine := SubcontractingManagement.IsSubcontractingPurchaseLine(Rec); + end; internal procedure SetIsSubcontracting(IsSubcontractingRelated: Boolean) begin diff --git a/src/Apps/W1/Subcontracting/Test/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/Tests/SubcSubcontractingTest.Codeunit.al index 95c670be18..f78bdce74f 100644 --- a/src/Apps/W1/Subcontracting/Test/Tests/SubcSubcontractingTest.Codeunit.al +++ b/src/Apps/W1/Subcontracting/Test/Tests/SubcSubcontractingTest.Codeunit.al @@ -4227,6 +4227,74 @@ codeunit 139989 "Subc. Subcontracting Test" 'Return Transfer Order No. must match the created return transfer order'); end; + [Test] + [HandlerFunctions('ConfirmHandler')] + procedure TransferOrderActionDisabledOnNonSubcontractingPurchaseLine() + var + Item: Record Item; + MachineCenter: array[2] of Record "Machine Center"; + NonSubcItem: Record Item; + ProductionOrder: Record "Production Order"; + PurchaseHeader: Record "Purchase Header"; + SubcPurchaseLine: Record "Purchase Line"; + NonSubcPurchaseLine: Record "Purchase Line"; + WorkCenter: array[2] of Record "Work Center"; + PurchaseOrderPage: TestPage "Purchase Order"; + begin + // [FEATURE] [Subcontracting] + // [SCENARIO 638531] The "Transfer Order" action on the Purchase Order Subform must be disabled + // for a non-subcontracting line (no Prod. Order No.) and enabled for a subcontracting line. + Initialize(); + SubcontractingMgmtLibrary.SetupInventorySetup(); + SubcontractingMgmtLibrary.UpdateManufacturingSetupWithSubcontractingLocation(); + + // [GIVEN] Work and Machine Centers, an Item with Routing and Prod. BOM configured for Transfer subcontracting + Subcontracting := true; + UnitCostCalculation := UnitCostCalculation::Units; + CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter); + CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter); + UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2]."No."); + SubcontractingMgmtLibrary.UpdateProdBomWithComponentSupplyMethod(Item, "Component Supply Method"::"Transfer to Vendor"); + UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]); + + // [GIVEN] A released production order with its transfer components located + SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder( + ProductionOrder, "Production Order Status"::Released, ProductionOrder."Source Type"::Item, Item."No.", LibraryRandom.RandInt(10) + 5); + UpdateSubMgmtSetupWithReqWkshTemplate(); + SubcontractingMgmtLibrary.UpdateProdOrderCompWithLocationCode(ProductionOrder."No."); + + // [GIVEN] A subcontracting purchase order is created from the routing (with Prod. Order No. set on the subc. line) + SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item."Routing No.", WorkCenter[2]."No."); + + SubcPurchaseLine.SetRange("Document Type", SubcPurchaseLine."Document Type"::Order); + SubcPurchaseLine.SetRange("Prod. Order No.", ProductionOrder."No."); + SubcPurchaseLine.FindFirst(); + PurchaseHeader.Get(SubcPurchaseLine."Document Type", SubcPurchaseLine."Document No."); + + // [GIVEN] A second non-subcontracting line is added to the same purchase order (no Prod. Order No.) + LibraryInventory.CreateItem(NonSubcItem); + LibraryPurchase.CreatePurchaseLine( + NonSubcPurchaseLine, PurchaseHeader, NonSubcPurchaseLine.Type::Item, NonSubcItem."No.", 1); + + // [WHEN] Opening the Purchase Order page + PurchaseOrderPage.OpenView(); + PurchaseOrderPage.GoToRecord(PurchaseHeader); + + // [THEN] "Transfer Order" action is enabled on the subcontracting line (Prod. Order No. is set) + PurchaseOrderPage.PurchLines.GoToRecord(SubcPurchaseLine); + Assert.IsTrue( + PurchaseOrderPage.PurchLines."Transfer Order".Enabled(), + 'Transfer Order action must be enabled for a subcontracting purchase line (Prod. Order No. is set).'); + + // [THEN] "Transfer Order" action is disabled on the non-subcontracting line (no Prod. Order No.) + PurchaseOrderPage.PurchLines.GoToRecord(NonSubcPurchaseLine); + Assert.IsFalse( + PurchaseOrderPage.PurchLines."Transfer Order".Enabled(), + 'Transfer Order action must be disabled for a non-subcontracting purchase line (no Prod. Order No.).'); + + PurchaseOrderPage.Close(); + end; + local procedure CreateUOMCodeSortingAfter(BaseUOMCode: Code[10]): Code[10] var UnitOfMeasure: Record "Unit of Measure";