-
Notifications
You must be signed in to change notification settings - Fork 371
[Bug 634238] Subcontracting: false 'already created' warning when prod order has multiple lines sharing routing/operation #8121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
46caa46
e9bab7d
6e89f13
41a1e07
804ffc7
7c75a81
5cca658
069c276
d804193
3c1415c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -35,6 +35,7 @@ using Microsoft.Sales.Document; | |||||||||||||||||||||||||||
| using Microsoft.Utilities; | ||||||||||||||||||||||||||||
| using Microsoft.Warehouse.Document; | ||||||||||||||||||||||||||||
| using Microsoft.Warehouse.Structure; | ||||||||||||||||||||||||||||
| using System.TestLibraries.Utilities; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| codeunit 139989 "Subc. Subcontracting Test" | ||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||
|
|
@@ -2526,6 +2527,145 @@ codeunit 139989 "Subc. Subcontracting Test" | |||||||||||||||||||||||||||
| Assert.ExpectedError('Nothing to create. No components or WIP items to return for the specified subcontracting order'); | ||||||||||||||||||||||||||||
| end; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| [Test] | ||||||||||||||||||||||||||||
| [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')] | ||||||||||||||||||||||||||||
| procedure CreateSubcontractingPOForEachProdOrderLineWhenLinesShareRoutingAndOperation() | ||||||||||||||||||||||||||||
| var | ||||||||||||||||||||||||||||
| Item: Record Item; | ||||||||||||||||||||||||||||
| ProductionLocation: array[2] of Record Location; | ||||||||||||||||||||||||||||
| MachineCenter: array[2] of Record "Machine Center"; | ||||||||||||||||||||||||||||
| ProdOrderLine: Record "Prod. Order Line"; | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine: Record "Prod. Order Routing Line"; | ||||||||||||||||||||||||||||
| ProductionOrder: Record "Production Order"; | ||||||||||||||||||||||||||||
| WorkCenter: array[2] of Record "Work Center"; | ||||||||||||||||||||||||||||
| ProdOrderRtng: TestPage "Prod. Order Routing"; | ||||||||||||||||||||||||||||
| I: Integer; | ||||||||||||||||||||||||||||
| ProdOrderLineNo: array[2] of Integer; | ||||||||||||||||||||||||||||
| begin | ||||||||||||||||||||||||||||
| // [SCENARIO 634238] When a Released Production Order has multiple Prod. Order lines sharing the same | ||||||||||||||||||||||||||||
| // Routing/Operation, creating a Subcontracting Order for the second line must not raise the false | ||||||||||||||||||||||||||||
| // "Purchase order(s) have already been created" warning, and must create/show its own Purchase Order. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // [GIVEN] Subcontracting setup with direct transfer (no in-transit route) | ||||||||||||||||||||||||||||
| Initialize(); | ||||||||||||||||||||||||||||
| SubcontractingMgmtLibrary.UpdateManufacturingSetupWithSubcontractingLocation(); | ||||||||||||||||||||||||||||
| Subcontracting := true; | ||||||||||||||||||||||||||||
| UnitCostCalculation := UnitCostCalculation::Units; | ||||||||||||||||||||||||||||
| CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter); | ||||||||||||||||||||||||||||
| UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]); | ||||||||||||||||||||||||||||
| CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter); | ||||||||||||||||||||||||||||
| UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2]."No."); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // [GIVEN] One released production order created directly from item | ||||||||||||||||||||||||||||
| LibraryManufacturing.CreateProductionOrder(ProductionOrder, "Production Order Status"::Released, ProductionOrder."Source Type"::Item, Item."No.", 0); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
ChethanT marked this conversation as resolved.
|
||||||||||||||||||||||||||||
| // [GIVEN] No production order lines exist yet for this order | ||||||||||||||||||||||||||||
| ProdOrderLine.SetRange(Status, ProdOrderLine.Status::Released); | ||||||||||||||||||||||||||||
| ProdOrderLine.SetRange("Prod. Order No.", ProductionOrder."No."); | ||||||||||||||||||||||||||||
| Assert.AreEqual(0, ProdOrderLine.Count(), 'Expected no production order lines to exist before manually creating them'); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // [GIVEN] Two production order lines on the same production order, on different locations | ||||||||||||||||||||||||||||
| LibraryWarehouse.CreateLocationWithInventoryPostingSetup(ProductionLocation[1]); | ||||||||||||||||||||||||||||
| LibraryWarehouse.CreateLocationWithInventoryPostingSetup(ProductionLocation[2]); | ||||||||||||||||||||||||||||
| LibraryManufacturing.CreateProdOrderLine(ProdOrderLine, ProductionOrder.Status, ProductionOrder."No.", Item."No.", '', ProductionLocation[1].Code, LibraryRandom.RandInt(10) + 2); | ||||||||||||||||||||||||||||
| ProdOrderLineNo[1] := ProdOrderLine."Line No."; | ||||||||||||||||||||||||||||
|
ChethanT marked this conversation as resolved.
|
||||||||||||||||||||||||||||
| LibraryManufacturing.CreateProdOrderLine(ProdOrderLine, ProductionOrder.Status, ProductionOrder."No.", Item."No.", '', ProductionLocation[2].Code, LibraryRandom.RandInt(10) + 2); | ||||||||||||||||||||||||||||
| ProdOrderLineNo[2] := ProdOrderLine."Line No."; | ||||||||||||||||||||||||||||
| Assert.AreNotEqual(ProdOrderLineNo[1], ProdOrderLineNo[2], 'Expected two distinct production order lines'); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // [GIVEN] Refresh the production order to update the routing and component lines | ||||||||||||||||||||||||||||
| LibraryManufacturing.RefreshProdOrder(ProductionOrder, false, false, true, true, false); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // [GIVEN] The two production-order lines have transfer components on different locations | ||||||||||||||||||||||||||||
| for I := 1 to 2 do begin | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine.Reset(); | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released); | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine.SetRange("Prod. Order No.", ProductionOrder."No."); | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine.SetRange("Routing Reference No.", ProdOrderLineNo[I]); | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine.SetRange("Work Center No.", WorkCenter[2]."No."); | ||||||||||||||||||||||||||||
| Assert.RecordCount(ProdOrderRoutingLine, 1); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ProdOrderRoutingLine.FindFirst(); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ProdOrderRtng.OpenView(); | ||||||||||||||||||||||||||||
| ProdOrderRtng.GoToRecord(ProdOrderRoutingLine); | ||||||||||||||||||||||||||||
| ProdOrderRtng.CreateSubcontracting.Invoke(); | ||||||||||||||||||||||||||||
|
ChethanT marked this conversation as resolved.
|
||||||||||||||||||||||||||||
| ProdOrderRtng.Close(); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Assert.AreEqual('1 Purchase Order(s) created.\\Do you want to view them?', LibraryVariableStorage.DequeueText(), 'Expected "created" confirmation for each prod order line, not the false "already created" warning'); | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hardcoded label text in test assertionThe assertion compares Recommendation:
Suggested change
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why |
||||||||||||||||||||||||||||
| LibraryVariableStorage.AssertEmpty(); | ||||||||||||||||||||||||||||
| end; | ||||||||||||||||||||||||||||
| end; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| [Test] | ||||||||||||||||||||||||||||
| [HandlerFunctions('ConfirmYesShowSubcontractingPurchOrders,CapturePurchaseOrderPageNo')] | ||||||||||||||||||||||||||||
| procedure CreateSubcontractingPONavigatesToOwnPOWhenLinesShareRoutingAndOperation() | ||||||||||||||||||||||||||||
| var | ||||||||||||||||||||||||||||
| Item: Record Item; | ||||||||||||||||||||||||||||
| ProductionLocation: array[2] of Record Location; | ||||||||||||||||||||||||||||
| MachineCenter: array[2] of Record "Machine Center"; | ||||||||||||||||||||||||||||
| ProdOrderLine: Record "Prod. Order Line"; | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine: Record "Prod. Order Routing Line"; | ||||||||||||||||||||||||||||
| ProductionOrder: Record "Production Order"; | ||||||||||||||||||||||||||||
| PurchaseLine: Record "Purchase Line"; | ||||||||||||||||||||||||||||
| WorkCenter: array[2] of Record "Work Center"; | ||||||||||||||||||||||||||||
| ProdOrderRtng: TestPage "Prod. Order Routing"; | ||||||||||||||||||||||||||||
| I: Integer; | ||||||||||||||||||||||||||||
| ProdOrderLineNo: array[2] of Integer; | ||||||||||||||||||||||||||||
| OpenedPurchaseOrderNo: Code[20]; | ||||||||||||||||||||||||||||
| begin | ||||||||||||||||||||||||||||
| // [SCENARIO 634238] When a Released Production Order has multiple Prod. Order lines sharing routing/operation, | ||||||||||||||||||||||||||||
| // confirming "view them" on the just-created Subcontracting Order must open the PO tied to the invoked | ||||||||||||||||||||||||||||
| // routing line, not the unrelated PO of a sibling line. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // [GIVEN] Subcontracting setup with two prod order lines sharing routing/operation but different Routing Reference No. | ||||||||||||||||||||||||||||
| Initialize(); | ||||||||||||||||||||||||||||
| SubcontractingMgmtLibrary.UpdateManufacturingSetupWithSubcontractingLocation(); | ||||||||||||||||||||||||||||
| Subcontracting := true; | ||||||||||||||||||||||||||||
| UnitCostCalculation := UnitCostCalculation::Units; | ||||||||||||||||||||||||||||
| CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter); | ||||||||||||||||||||||||||||
| UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]); | ||||||||||||||||||||||||||||
| CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter); | ||||||||||||||||||||||||||||
| UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2]."No."); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| LibraryManufacturing.CreateProductionOrder(ProductionOrder, "Production Order Status"::Released, ProductionOrder."Source Type"::Item, Item."No.", 0); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| LibraryWarehouse.CreateLocationWithInventoryPostingSetup(ProductionLocation[1]); | ||||||||||||||||||||||||||||
| LibraryWarehouse.CreateLocationWithInventoryPostingSetup(ProductionLocation[2]); | ||||||||||||||||||||||||||||
| LibraryManufacturing.CreateProdOrderLine(ProdOrderLine, ProductionOrder.Status, ProductionOrder."No.", Item."No.", '', ProductionLocation[1].Code, LibraryRandom.RandInt(10) + 2); | ||||||||||||||||||||||||||||
| ProdOrderLineNo[1] := ProdOrderLine."Line No."; | ||||||||||||||||||||||||||||
| LibraryManufacturing.CreateProdOrderLine(ProdOrderLine, ProductionOrder.Status, ProductionOrder."No.", Item."No.", '', ProductionLocation[2].Code, LibraryRandom.RandInt(10) + 2); | ||||||||||||||||||||||||||||
| ProdOrderLineNo[2] := ProdOrderLine."Line No."; | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing distinct-line guard in second scenario testThe test Recommendation:
Suggested change
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why |
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| LibraryManufacturing.RefreshProdOrder(ProductionOrder, false, false, true, true, false); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // [WHEN] Creating a Subcontracting Order from each routing line and confirming "view them" | ||||||||||||||||||||||||||||
| for I := 1 to 2 do begin | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine.Reset(); | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released); | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine.SetRange("Prod. Order No.", ProductionOrder."No."); | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine.SetRange("Routing Reference No.", ProdOrderLineNo[I]); | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine.SetRange("Work Center No.", WorkCenter[2]."No."); | ||||||||||||||||||||||||||||
| ProdOrderRoutingLine.FindFirst(); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ProdOrderRtng.OpenView(); | ||||||||||||||||||||||||||||
| ProdOrderRtng.GoToRecord(ProdOrderRoutingLine); | ||||||||||||||||||||||||||||
| ProdOrderRtng.CreateSubcontracting.Invoke(); | ||||||||||||||||||||||||||||
| ProdOrderRtng.Close(); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // [THEN] The page handler opens the Purchase Order whose line carries this routing line's Routing Reference No. | ||||||||||||||||||||||||||||
| OpenedPurchaseOrderNo := CopyStr(LibraryVariableStorage.DequeueText(), 1, MaxStrLen(OpenedPurchaseOrderNo)); | ||||||||||||||||||||||||||||
| PurchaseLine.Reset(); | ||||||||||||||||||||||||||||
| PurchaseLine.SetRange("Document Type", PurchaseLine."Document Type"::Order); | ||||||||||||||||||||||||||||
| PurchaseLine.SetRange("Document No.", OpenedPurchaseOrderNo); | ||||||||||||||||||||||||||||
| PurchaseLine.SetRange(Type, PurchaseLine.Type::Item); | ||||||||||||||||||||||||||||
| PurchaseLine.SetRange("Prod. Order No.", ProductionOrder."No."); | ||||||||||||||||||||||||||||
| PurchaseLine.SetRange("Routing Reference No.", ProdOrderLineNo[I]); | ||||||||||||||||||||||||||||
| Assert.IsFalse(PurchaseLine.IsEmpty(), StrSubstNo(PurchOrderRoutingErr, OpenedPurchaseOrderNo, ProdOrderLineNo[I])); | ||||||||||||||||||||||||||||
| LibraryVariableStorage.AssertEmpty(); | ||||||||||||||||||||||||||||
| end; | ||||||||||||||||||||||||||||
| end; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| [Test] | ||||||||||||||||||||||||||||
| [HandlerFunctions('ConfirmYesShowSubcontractingPurchOrders,HandlePurchaseOrderPage,HandlePurchaseLinesPage')] | ||||||||||||||||||||||||||||
| procedure ShowExistingPurchOrdersOpensListWhenAlreadyCreated() | ||||||||||||||||||||||||||||
|
|
@@ -2592,6 +2732,13 @@ codeunit 139989 "Subc. Subcontracting Test" | |||||||||||||||||||||||||||
| PurchaseOrderPage.Close(); | ||||||||||||||||||||||||||||
| end; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| [PageHandler] | ||||||||||||||||||||||||||||
| procedure CapturePurchaseOrderPageNo(var PurchaseOrderPage: TestPage "Purchase Order") | ||||||||||||||||||||||||||||
| begin | ||||||||||||||||||||||||||||
| LibraryVariableStorage.Enqueue(PurchaseOrderPage."No.".Value); | ||||||||||||||||||||||||||||
| PurchaseOrderPage.Close(); | ||||||||||||||||||||||||||||
| end; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| [PageHandler] | ||||||||||||||||||||||||||||
| procedure HandlePurchaseLinesPage(var PurchaseLinesPage: TestPage "Purchase Lines") | ||||||||||||||||||||||||||||
| begin | ||||||||||||||||||||||||||||
|
|
@@ -2623,6 +2770,7 @@ codeunit 139989 "Subc. Subcontracting Test" | |||||||||||||||||||||||||||
| [ConfirmHandler] | ||||||||||||||||||||||||||||
| procedure DoNotConfirmShowCreatedPurchOrderForSubcontracting(Question: Text[1024]; var Reply: Boolean) | ||||||||||||||||||||||||||||
| begin | ||||||||||||||||||||||||||||
| LibraryVariableStorage.Enqueue(Question); | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shared confirm handler now enqueues—breaks existing tests
Recommendation:
Suggested change
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why |
||||||||||||||||||||||||||||
| Reply := false; | ||||||||||||||||||||||||||||
| end; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
@@ -3056,6 +3204,9 @@ codeunit 139989 "Subc. Subcontracting Test" | |||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| SubcontractingMgmtLibrary.Initialize(); | ||||||||||||||||||||||||||||
| SubcontractingMgmtLibrary.UpdateSubMgmtSetup_ComponentAtLocation("Components at Location"::Purchase); | ||||||||||||||||||||||||||||
| UpdateSubMgmtSetupWithReqWkshTemplate(); | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UpdateSubMgmtSetupWithReqWkshTemplate runs on every test init
Recommendation:
Suggested change
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why |
||||||||||||||||||||||||||||
| LibraryVariableStorage.Clear(); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| LibraryMfgManagement.Initialize(); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if IsInitialized then | ||||||||||||||||||||||||||||
|
|
@@ -3184,6 +3335,7 @@ codeunit 139989 "Subc. Subcontracting Test" | |||||||||||||||||||||||||||
| LibraryWarehouse: Codeunit "Library - Warehouse"; | ||||||||||||||||||||||||||||
| LibraryMfgManagement: Codeunit "Subc. Library Mfg. Management"; | ||||||||||||||||||||||||||||
| SubcontractingMgmtLibrary: Codeunit "Subc. Management Library"; | ||||||||||||||||||||||||||||
| LibraryVariableStorage: Codeunit "Library - Variable Storage"; | ||||||||||||||||||||||||||||
| SubSetupLibrary: Codeunit "Subc. Setup Library"; | ||||||||||||||||||||||||||||
| IsInitialized: Boolean; | ||||||||||||||||||||||||||||
| Subcontracting: Boolean; | ||||||||||||||||||||||||||||
|
|
@@ -3193,5 +3345,6 @@ codeunit 139989 "Subc. Subcontracting Test" | |||||||||||||||||||||||||||
| UnitCostCalculation: Option Time,Units; | ||||||||||||||||||||||||||||
| ConfirmDialogCalledCount: Integer; | ||||||||||||||||||||||||||||
| AlreadySpecifiedErr: Label 'You cannot open Tracking Specification because this component is already specified in Transfer Order %1.', Comment = '|%1 = Transfer Order No.'; | ||||||||||||||||||||||||||||
| PurchOrderRoutingErr: Label 'Purchase Order %1 should contain a line tied to Routing Reference No. %2', Comment = '%1 = Purchase Order No., %2 = Routing Reference No.'; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RoutingReferenceNo = 0 silently skips the filter
The guard
(RoutingReferenceNo <> 0)means that if a prod-order routing line genuinely hasRouting Reference No. = 0(e.g. a line created outside the normal production order refresh flow), the filter is not applied andFindFirst()can return a purchase line from the wrong routing context, reopening the original bug for those records.Recommendation:
Routing Reference No. = 0is intentionally excluded, or — if routing lines with value 0 are possible — add a dedicated boolean flag (similar to howOperationNouses an empty-string check which is unambiguous forCodefields) to explicitly indicate whether the caller has set the filter.👍 useful · ❤️ especially valuable · 👎 wrong - reply with why