From 81144c4a607b0bf1987b57c63b9608da3d382908 Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Thu, 28 May 2026 13:45:48 +0200 Subject: [PATCH 01/14] Add new dataset --- dataset/bcbench.jsonl | 3 ++ .../microsoft__BCApps-7953/README.md | 20 +++++++++ .../microsoft__BCApps-8059/README.md | 38 ++++++++++++++++++ .../microsoft__BCApps-8059/error_message.png | Bin 0 -> 118854 bytes .../microsoft__BCApps-8253/README.md | 25 ++++++++++++ 5 files changed, 86 insertions(+) create mode 100644 dataset/problemstatement/microsoft__BCApps-7953/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8059/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8059/error_message.png create mode 100644 dataset/problemstatement/microsoft__BCApps-8253/README.md diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index 54796b9fb..04fef2cd0 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -99,3 +99,6 @@ {"metadata": {"area": "inventory", "image_count": 0}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-178045", "base_commit": "22d8978231eb8792d03f150d61431d485d3c92a9", "created_at": "2024-03-11", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137404, "functionName": ["ConsumptionIsPostedForMultipleILEsOfSameLotNo"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al\nindex 9467380d9f9b..e1036e0420d9 100644\n--- a/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al\n@@ -47,6 +47,7 @@ codeunit 137404 \"SCM Manufacturing\"\n Capacity2: Decimal;\n GLB_ItemTrackingQty: Integer;\n GLB_SerialNo: Code[50];\n+ ItemTrackingMode: Option \" \",\"Assign Lot No.\",\"Select Entries\",\"Update Quantity\",\"Manual Lot No.\"; \n DocumentNoDoesNotExistErr: Label 'Document No. %1 does not exist.', Comment = '%1: Document number (Code)';\n ExpectedQuantityErr: Label 'Quantity must be %1.', Comment = '%1: Quantity (decimal value)';\n ModifyRtngErr: Label 'You cannot modify Routing No. %1 because there is at least one %2 associated with it.';\n@@ -80,6 +81,7 @@ codeunit 137404 \"SCM Manufacturing\"\n DidntExpectWhsePickMsg: Label 'Did not expect a Warehouse Pick Request associated with the Production Order Component Line, since the line doesn''t have a postitive remaining quantity';\n ProdOrderNoHandlerErr: Label 'Prod. Order No. must be %1, actual value is %2.', Comment = '%1: Expected Prod. Order No. Value; %2: Actual Prod. Order No. Value.';\n ProdOrderStatusHandlerErr: Label 'Prod. Order Status must be %1, actual value is %2.', Comment = '%1: Expected Prod. Order Status Value; %2: Actual Prod. Order Status Value.';\n+ ItemLedgerEntryMustBeFoundErr: Label 'Item Ledger Entry must be found.';\n \n [Test]\n [HandlerFunctions('ConfirmHandlerTrue,OutputJournalItemtrackingPageHandler,MessageHandler')]\n@@ -4149,6 +4151,104 @@ codeunit 137404 \"SCM Manufacturing\"\n LibraryInventory.PostItemJournalLine(ItemJournalBatch.\"Journal Template Name\", ItemJournalBatch.Name);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('ItemTrackingAssignLotNoPageHandler,ProductionJournalPageHandlerOnlyConsumption,ConfirmHandlerTrue,MessageHandler')]\n+ procedure ConsumptionIsPostedForMultipleILEsOfSameLotNo()\n+ var\n+ CompItem, ProdItem : Record Item;\n+ Location: Record Location;\n+ UnitOfMeasure: Record \"Unit of Measure\";\n+ ItemUnitOfMeasure: Record \"Item Unit of Measure\";\n+ ItemTrackingCode: Record \"Item Tracking Code\";\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ ProductionOrder: Record \"Production Order\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ LotNo: Code[10];\n+ Quantity: Decimal;\n+ ReleasedProdOrder: TestPage \"Released Production Order\";\n+ begin\n+ // [SCENARIO 501830] Consumption is posted against multiple Item Ledger Entries of same Lot No. when you post Production Journal from a Released Production Order.\n+ Initialize();\n+\n+ // [GIVEN] Create Item Tracking Code.\n+ LibraryItemTracking.CreateItemTrackingCode(ItemTrackingCode, false, true);\n+\n+ // [GIVEN] Create Unit of Measure.\n+ LibraryInventory.CreateUnitOfMeasureCode(UnitOfMeasure);\n+\n+ // [GIVEN] Create Component Item with Unit of Measure.\n+ CreateItemWithUOM(CompItem, UnitOfMeasure, ItemUnitOfMeasure);\n+ CompItem.Validate(\"Replenishment System\", CompItem.\"Replenishment System\"::Purchase);\n+ CompItem.Validate(Reserve, CompItem.Reserve::Always);\n+ CompItem.Validate(\"Flushing Method\", CompItem.\"Flushing Method\"::Manual);\n+ CompItem.Validate(\"Item Tracking Code\", ItemTrackingCode.Code);\n+ CompItem.Modify(true);\n+\n+ // [GIVEN] Create Location with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+\n+ // [GIVEN] Create Production Item with Unit of Measure.\n+ CreateItemWithUOM(ProdItem, UnitOfMeasure, ItemUnitOfMeasure);\n+\n+ // [GIVEN] Generate and save Lot No. and Quantity in two different Variable.\n+ LotNo := Format(LibraryRandom.RandText(4));\n+ Quantity := LibraryRandom.RandIntInRange(35, 35);\n+\n+ // [GIVEN] Create and Post three Item Journal Lines with same Lot No.\n+ CreateAndPostItemJournalLineWithLotNo(CompItem.\"No.\", LibraryRandom.RandIntInRange(5, 5), LotNo, '', Location.Code, true);\n+ CreateAndPostItemJournalLineWithLotNo(CompItem.\"No.\", LibraryRandom.RandIntInRange(10, 10), LotNo, '', Location.Code, true);\n+ CreateAndPostItemJournalLineWithLotNo(CompItem.\"No.\", LibraryRandom.RandIntInRange(20, 20), LotNo, '', Location.Code, true);\n+\n+ // [GIVEN] Create a production BOM for the Production Item.\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ItemUnitOfMeasure.Code);\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader,\n+ ProductionBOMLine,\n+ '',\n+ ProductionBOMLine.Type::Item,\n+ CompItem.\"No.\",\n+ LibraryRandom.RandIntInRange(1, 1));\n+\n+ // [GIVEN] Validate Unit of Measure in Production BOM.\n+ ProductionBOMLine.Validate(\"Unit of Measure Code\", ItemUnitOfMeasure.Code);\n+ ProductionBOMLine.Modify(true);\n+\n+ // [GIVEN] Change Status of Production BOM.\n+ LibraryManufacturing.UpdateProductionBOMStatus(ProductionBOMHeader, ProductionBOMHeader.Status::Certified);\n+\n+ // [GIVEN] Validate Replenishment System and Production BOM No. in Production Item.\n+ ProdItem.Validate(\"Replenishment System\", ProdItem.\"Replenishment System\"::\"Prod. Order\");\n+ ProdItem.Validate(\"Production BOM No.\", ProductionBOMHeader.\"No.\");\n+ ProdItem.Modify(true);\n+\n+ // [GIVEN] Create and Refresh Production Order.\n+ CreateAndRefreshProdOrder(\n+ ProductionOrder,\n+ ProductionOrder.Status::Released,\n+ ProdItem.\"No.\",\n+ Quantity,\n+ Location.Code,\n+ '');\n+\n+ // [GIVEN] Open Released Production Order page and run Production Journal action.\n+ ReleasedProdOrder.OpenEdit();\n+ ReleasedProdOrder.GoToRecord(ProductionOrder);\n+ LibraryVariableStorage.Enqueue(Quantity);\n+ LibraryVariableStorage.Enqueue(ItemTrackingMode::\"Assign Lot No.\");\n+ LibraryVariableStorage.Enqueue(LotNo);\n+ LibraryVariableStorage.Enqueue(Quantity);\n+ ReleasedProdOrder.ProdOrderLines.ProductionJournal.Invoke();\n+\n+ // [WHEN] Find Item Ledger Entry.\n+ ItemLedgerEntry.SetRange(\"Item No.\", CompItem.\"No.\");\n+ ItemLedgerEntry.SetRange(Quantity, -Quantity);\n+\n+ // [VERIFY] Item Ledger Entry is found.\n+ Assert.IsFalse(ItemLedgerEntry.IsEmpty(), ItemLedgerEntryMustBeFoundErr);\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -6772,6 +6872,39 @@ codeunit 137404 \"SCM Manufacturing\"\n ReservationPage.OK().Invoke();\n end;\n \n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure ItemTrackingAssignLotNoPageHandler(var ItemTrackingLines: TestPage \"Item Tracking Lines\")\n+ var\n+ DequeueVariable: Variant;\n+ begin\n+ LibraryVariableStorage.Dequeue(DequeueVariable);\n+ ItemTrackingMode := DequeueVariable;\n+ case ItemTrackingMode of\n+ ItemTrackingMode::\"Assign Lot No.\":\n+ begin\n+ ItemTrackingLines.\"Lot No.\".SetValue(LibraryVariableStorage.DequeueText());\n+ LibraryVariableStorage.Dequeue(DequeueVariable);\n+ ItemTrackingLines.\"Quantity (Base)\".SetValue(DequeueVariable);\n+ end;\n+ end;\n+ ItemTrackingLines.OK().Invoke();\n+ end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure ProductionJournalPageHandlerOnlyConsumption(var ProductionJournal: TestPage \"Production Journal\")\n+ var\n+ EntryType: Enum \"Item Ledger Entry Type\";\n+ begin\n+ Assert.IsTrue(ProductionJournal.FindFirstField(ProductionJournal.\"Entry Type\", EntryType::Output), '');\n+ ProductionJournal.\"Output Quantity\".SetValue(0);\n+ Assert.IsTrue(ProductionJournal.FindFirstField(ProductionJournal.\"Entry Type\", EntryType::Consumption), '');\n+ ProductionJournal.Quantity.SetValue(LibraryVariableStorage.DequeueDecimal());\n+ ProductionJournal.ItemTrackingLines.Invoke();\n+ ProductionJournal.Post.Invoke();\n+ end;\n+\n [PageHandler]\n procedure BOMStructurePageHandler(var BOMStructure: TestPage \"BOM Structure\")\n begin\n@@ -6840,5 +6973,74 @@ codeunit 137404 \"SCM Manufacturing\"\n DT2Time(ExpStartDateTime), DT2Time(ProdOrderLine.\"Starting Date-Time\"), StrSubstNo(WrongDateTimeErr, ProdOrderLine.FieldCaption(\"Starting Time\")));\n until ProdOrderLine.Next() = 0;\n end;\n+\n+ local procedure CreateItemWithUOM(\n+ var Item: Record Item;\n+ var UnitOfMeasure: Record \"Unit of Measure\";\n+ var ItemUnitOfMeasure: Record \"Item Unit of Measure\")\n+ begin\n+ LibraryInventory.CreateItem(Item);\n+\n+ LibraryInventory.CreateItemUnitOfMeasure(\n+ ItemUnitOfMeasure,\n+ Item.\"No.\",\n+ UnitOfMeasure.Code,\n+ LibraryRandom.RandInt(0));\n+\n+ Item.Validate(\"Base Unit of Measure\", UnitOfMeasure.Code);\n+ Item.Modify(true);\n+ end;\n+\n+ local procedure CreateAndPostItemJournalLineWithLotNo(\n+ ItemNo: Code[20];\n+ Quantity: Decimal;\n+ LotNo: Code[50];\n+ BinCode: Code[20];\n+ LocationCode: Code[10];\n+ Tracking: Boolean)\n+ var\n+ ItemJournalLine: Record \"Item Journal Line\";\n+ begin\n+ CreateItemJournalLine(ItemJournalLine, ItemNo, Quantity, BinCode, LocationCode);\n+ if Tracking then begin\n+ LibraryVariableStorage.Enqueue(ItemTrackingMode::\"Assign Lot No.\");\n+ LibraryVariableStorage.Enqueue(LotNo);\n+ LibraryVariableStorage.Enqueue(Quantity);\n+ ItemJournalLine.OpenItemTrackingLines(false);\n+ end;\n+ LibraryInventory.PostItemJournalLine(ItemJournalLine.\"Journal Template Name\", ItemJournalLine.\"Journal Batch Name\");\n+ end;\n+\n+ local procedure CreateItemJournalLine(var ItemJournalLine: Record \"Item Journal Line\"; ItemNo: Code[20]; Quantity: Decimal; BinCode: Code[20]; LocationCode: Code[10])\n+ var\n+ ItemJournalTemplate: Record \"Item Journal Template\";\n+ ItemJournalBatch: Record \"Item Journal Batch\";\n+ begin\n+ LibraryInventory.ClearItemJournal(ItemJournalTemplate, ItemJournalBatch);\n+ LibraryInventory.CreateItemJournalTemplate(ItemJournalTemplate);\n+ LibraryInventory.CreateItemJournalBatch(ItemJournalBatch, ItemJournalTemplate.Name);\n+ LibraryInventory.CreateItemJournalLine(\n+ ItemJournalLine,\n+ ItemJournalBatch.\"Journal Template Name\",\n+ ItemJournalBatch.Name,\n+ ItemJournalLine.\"Entry Type\"::\"Positive Adjmt.\",\n+ ItemNo,\n+ Quantity);\n+\n+ ItemJournalLine.Validate(\"Unit Cost\", LibraryRandom.RandDec(10, 2));\n+ ItemJournalLine.Validate(\"Location Code\", LocationCode);\n+ ItemJournalLine.Validate(\"Bin Code\", BinCode);\n+ ItemJournalLine.Modify(true);\n+ end;\n+\n+ local procedure CreateAndRefreshProdOrder(var ProductionOrder: Record \"Production Order\"; Status: Enum \"Production Order Status\"; SourceNo: Code[20]; Quantity: Decimal; LocationCode: Code[10]; BinCode: Code[20])\n+ begin\n+ LibraryManufacturing.CreateProductionOrder(ProductionOrder, Status, ProductionOrder.\"Source Type\"::Item, SourceNo, Quantity);\n+ ProductionOrder.Validate(\"Location Code\", LocationCode);\n+ ProductionOrder.Validate(\"Bin Code\", BinCode);\n+ ProductionOrder.Modify(true);\n+\n+ LibraryManufacturing.RefreshProdOrder(ProductionOrder, false, true, true, true, false);\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al b/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al\nindex 7e739c297201..ffe0b880ce8d 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al\n@@ -1946,8 +1946,11 @@ codeunit 22 \"Item Jnl.-Post Line\"\n Abs(ItemLedgEntry.\"Remaining Quantity\" - ItemLedgEntry.\"Reserved Quantity\")\n then\n AppliedQty := ItemLedgEntry.\"Remaining Quantity\" - ItemLedgEntry.\"Reserved Quantity\"\n- else\n+ else begin\n AppliedQty := -(OldItemLedgEntry.\"Remaining Quantity\" - OldItemLedgEntry.\"Reserved Quantity\");\n+ if AppliedQty = 0 then\n+ AppliedQty := UpdateAppliedQtyIfConsumptionEntry(ItemLedgEntry, OldItemLedgEntry);\n+ end;\n \n OnApplyItemLedgEntryOnAfterCalcAppliedQty(OldItemLedgEntry, ItemLedgEntry, AppliedQty);\n \n@@ -5908,6 +5911,17 @@ codeunit 22 \"Item Jnl.-Post Line\"\n (ItemJournalLine.\"Applies-to Entry\" <> 0)));\n end;\n \n+ local procedure UpdateAppliedQtyIfConsumptionEntry(ItemLedgerEntry: Record \"Item Ledger Entry\"; OldItemLedgerEntry: Record \"Item Ledger Entry\"): Decimal\n+ begin\n+ if ItemLedgerEntry.\"Entry Type\" <> ItemLedgerEntry.\"Entry Type\"::Consumption then\n+ exit(0);\n+\n+ if (ItemLedgerEntry.\"Remaining Quantity\" + OldItemLedgerEntry.\"Remaining Quantity\") > 0 then\n+ exit(0);\n+\n+ exit(-Abs(OldItemLedgerEntry.\"Reserved Quantity\"));\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnBeforeAllowProdApplication(OldItemLedgerEntry: Record \"Item Ledger Entry\"; ItemLedgerEntry: Record \"Item Ledger Entry\"; var AllowApplication: Boolean)\n begin\n"} {"metadata": {"area": "inventory", "image_count": 7}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-176082", "base_commit": "cb30d50fe1ed2c716c6349370fdc31c6bd0ce956", "created_at": "2024-02-23", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137038, "functionName": ["GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\nindex e0b3ba5f0bf7..ffa98cfbb351 100644\n--- a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n@@ -48,6 +48,7 @@\n UndoneTransLineQtyErr: Label 'Expected Quantity to be 0 after Transfer Shipment was undone';\n DerivedTransLineErr: Label 'Expected no Derived Transfer Line i.e. line with \"Derived From Line No.\" equal to original transfer line.';\n IncorrectSNUndoneErr: Label 'The Serial No. of the item on the transfer shipment line that was undone was different from the SN on the corresponding transfer line.';\n+ ApplToItemEntryErr: Label '%1 must be %2 in %3.', Comment = '%1 is Appl-to Item Entry, %2 is Item Ledger Entry No. and %3 is Transfer Line';\n \n [Test]\n [HandlerFunctions('MessageHandler')]\n@@ -3655,6 +3656,99 @@\n ItemLedgerEntry.TestField(\"Cost Amount (Actual)\", NewCost);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('PostedPurchaseReceiptsModalPageHandler,PostedPurchRcptLinesModalPageHandler')]\n+ procedure GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines()\n+ var\n+ Item: Record Item;\n+ Vendor: Record Vendor;\n+ Location: Record Location;\n+ Location2: Record Location;\n+ Location3: Record Location;\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseHeader2: Record \"Purchase Header\";\n+ PurchaseHeader3: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ PurchaseLine2: Record \"Purchase Line\";\n+ PurchaseLine3: Record \"Purchase Line\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ TransferHeader: Record \"Transfer Header\";\n+ TransferLine: Record \"Transfer Line\";\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ ItemLedgerEntryNo: Integer;\n+ PurchaseReceiptNo: Code[20];\n+ TransferOrder: TestPage \"Transfer Order\";\n+ begin\n+ // [SCENARIO 500597] Get Receipt Lines action on Transfer Order shows list of Posted Purchase Receipts having Transfer-from Code in Location Code of Purch Rcpt Lines and after selecting it populates Appl-to Item Entry field in Transfer Lines.\n+ Initialize();\n+\n+ // [GIVEN] Create an Item and Validate Costing Method.\n+ LibraryInventory.CreateItem(Item);\n+ Item.Validate(\"Costing Method\", Item.\"Costing Method\"::FIFO);\n+ Item.Modify(true);\n+\n+ // [GIVEN] Create two Locations with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location2);\n+\n+ // [GIVEN] Create another Location with Inventory Posting Setup \n+ // And Validate Use As In-Transit.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location3);\n+ Location3.Validate(\"Use As In-Transit\", true);\n+ Location3.Modify(true);\n+\n+ // [GIVEN] Create a Vendor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+\n+ // [GIVEN] Create and Post Purchase Receipt with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader, PurchaseLine, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 2 with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader2, PurchaseLine2, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 3 with Location Code on Line.\n+ PurchaseReceiptNo := CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ PurchaseHeader3,\n+ PurchaseLine3,\n+ Vendor,\n+ Item,\n+ Location);\n+\n+ // [GIVEN] Find and save Item Ledger Entry No. in a Variable.\n+ ItemLedgerEntry.SetRange(\"Document No.\", PurchaseReceiptNo);\n+ ItemLedgerEntry.FindFirst();\n+ ItemLedgerEntryNo := ItemLedgerEntry.\"Entry No.\";\n+\n+ // [GIVEN] Find Purch. Rcpt Line.\n+ FindRandomReceiptLine(PurchaseReceiptNo, PurchRcptLine);\n+\n+ // [GIVEN] Create Transfer Header.\n+ LibraryInventory.CreateTransferHeader(TransferHeader, Location.Code, Location2.Code, Location3.Code);\n+\n+ // [GIVEN] Open Transfer Order page and run Get Receipt Line action.\n+ TransferOrder.OpenEdit();\n+ TransferOrder.GoToRecord(TransferHeader);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchRcptLine.\"No.\");\n+ TransferOrder.GetReceiptLines.Invoke();\n+\n+ // [WHEN] Find Transfer Line.\n+ TransferLine.SetRange(\"Document No.\", TransferHeader.\"No.\");\n+ TransferLine.FindFirst();\n+\n+ // [VERIFY] Appl-to Item Entry and Item Ledger Entry No. are same.\n+ Assert.AreEqual(\n+ ItemLedgerEntryNo,\n+ TransferLine.\"Appl.-to Item Entry\",\n+ StrSubstNo(\n+ ApplToItemEntryErr,\n+ TransferLine.FieldCaption(\"Appl.-to Item Entry\"),\n+ ItemLedgerEntryNo,\n+ TransferLine.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -5168,6 +5262,52 @@\n Assert.AreEqual(LineCount, TransferReceiptLine.Count(), '');\n end;\n \n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchHeader(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location)\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ PurchaseHeader.Validate(\"Location Code\", Location.Code);\n+ PurchaseHeader.Modify(true);\n+\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+ end;\n+\n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location): Code[20]\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Location Code\", Location.Code);\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ exit(LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false));\n+ end;\n+\n [MessageHandler]\n [Scope('OnPrem')]\n procedure MessageHandler(Message: Text[1024])\n@@ -5394,5 +5534,19 @@\n // 0 = Item.Type::Inventory\n Assert.AreEqual('0', ItemList.Filter.GetFilter(\"Type\"), 'Item List contains non-inventory items.');\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure PostedPurchRcptLinesModalPageHandler(var PostedPurchaseReceiptLines: Page \"Posted Purchase Receipt Lines\"; var Response: Action)\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ begin\n+ PurchRcptLine.SetRange(\"Document No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.SetRange(\"No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.FindFirst();\n+ PostedPurchaseReceiptLines.SetRecord(PurchRcptLine);\n+\n+ Response := ACTION::LookupOK;\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\nindex 5fe44b4568d1..c16ab8669925 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n@@ -1304,7 +1304,7 @@ table 5740 \"Transfer Header\"\n TempPurchRcptHeader: Record \"Purch. Rcpt. Header\" temporary;\n PostedPurchaseReceipts: Page \"Posted Purchase Receipts\";\n begin\n- PurchRcptHeader.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ FindPurchRcptHeader(PurchRcptHeader);\n PostedPurchaseReceipts.SetTableView(PurchRcptHeader);\n PostedPurchaseReceipts.LookupMode := true;\n if PostedPurchaseReceipts.RunModal() = ACTION::LookupOK then begin\n@@ -1376,6 +1376,8 @@ table 5740 \"Transfer Header\"\n PurchRcptLine.FilterPstdDocLnItemLedgEntries(ItemLedgerEntry);\n ItemTrackingDocMgt.CopyItemLedgerEntriesToTemp(TempItemLedgerEntry, ItemLedgerEntry);\n ItemTrackingMgt.CopyItemLedgEntryTrkgToTransferLine(TempItemLedgerEntry, TransferLine);\n+ TransferLine.\"Appl.-to Item Entry\" := ItemLedgerEntry.\"Entry No.\";\n+ TransferLine.Modify(true);\n \n OnAfterAddTransferLineFromReceiptLine(TransferLine, PurchRcptLine, TempItemLedgerEntry, Rec);\n end;\n@@ -1546,6 +1548,31 @@ table 5740 \"Transfer Header\"\n end;\n end;\n \n+ local procedure FindPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\")\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ DocumentNo: Code[20];\n+ begin\n+ PurchRcptLine.SetLoadFields(\"Document No.\", \"Location Code\");\n+ PurchRcptLine.SetCurrentKey(\"Document No.\");\n+ PurchRcptLine.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ if PurchRcptLine.FindSet() then\n+ repeat\n+ GetPurchRcptHeader(PurchRcptHeader, PurchRcptLine, DocumentNo);\n+ until PurchRcptLine.Next() = 0;\n+ PurchRcptHeader.MarkedOnly(true);\n+ end;\n+\n+ local procedure GetPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var DocumentNo: Code[20])\n+ begin\n+ if PurchRcptLine.\"Document No.\" = DocumentNo then\n+ exit;\n+\n+ PurchRcptHeader.Get(PurchRcptLine.\"Document No.\");\n+ PurchRcptHeader.Mark(true);\n+ DocumentNo := PurchRcptLine.\"Document No.\";\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnAddTransferLineFromReceiptLineOnBeforeTransferLineInsert(var TransferLine: Record \"Transfer Line\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var TransferHeader: Record \"Transfer Header\")\n begin\n"} {"metadata": {"area": "crm", "image_count": 8}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-174087", "base_commit": "74a0b7c175da3f9a272745bd34453a4712b73e7b", "created_at": "2024-02-02", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\Marketing"], "FAIL_TO_PASS": [{"codeunitID": 136208, "functionName": ["PopulateEvaluationFieldInInteractionLogEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\nindex 4c4c73700d2a..59fff6e2be93 100644\n--- a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n+++ b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n@@ -45,6 +45,7 @@ codeunit 136208 \"Marketing Interaction\"\n LoggedSegemntEntriesCreateMsg: Label 'Logged Segment entry was created';\n AttachmentFileShouldNotBeBlankErr: Label 'Attachment File should not be blank.';\n TxtFileExt: Label 'txt';\n+ EvaluationErr: Label '%1 must be %2 in %3', Comment = '%1 = Evaluation, %2 = Positive, %3 = Interaction Log Entry';\n \n [Test]\n [Scope('OnPrem')]\n@@ -2998,6 +2999,50 @@ codeunit 136208 \"Marketing Interaction\"\n VerifyAttachmentFileIsNotBlankOnInteractionLogEntry(Contact.\"No.\");\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('CreateInteractionFromContactPageHandler')]\n+ procedure PopulateEvaluationFieldInInteractionLogEntry()\n+ var\n+ Contact: Record Contact;\n+ InteractionTemplate: Record \"Interaction Template\";\n+ InteractionLogEntry: Record \"Interaction Log Entry\";\n+ ContactCard: TestPage \"Contact Card\";\n+ InteractionEvaluation: Enum \"Interaction Evaluation\";\n+ begin\n+ // [SCENARIO 498395] When stan creates an Interaction using Create Interaction action from Contact, Evaluation field should be populated in Interaction Log Entry.\n+ Initialize();\n+\n+ // [GIVEN] Create a Contact.\n+ LibraryMarketing.CreateCompanyContact(Contact);\n+\n+ // [GIVEN] Create an Interaction Template and Validate Information Flow.\n+ LibraryMarketing.CreateInteractionTemplate(InteractionTemplate);\n+ InteractionTemplate.Validate(\"Information Flow\", InteractionTemplate.\"Information Flow\"::Outbound);\n+ InteractionTemplate.Modify(true);\n+\n+ // [GIVEN] Open Contact Card and Create Interaction.\n+ ContactCard.OpenEdit();\n+ ContactCard.GoToRecord(Contact);\n+ LibraryVariableStorage.Enqueue(InteractionTemplate.Code);\n+ LibraryVariableStorage.Enqueue(Format(InteractionEvaluation::Positive));\n+ ContactCard.\"Create &Interaction\".Invoke();\n+\n+ // [WHEN] Find Interaction Log Entry.\n+ InteractionLogEntry.SetRange(\"Contact No.\", Contact.\"No.\");\n+ InteractionLogEntry.FindFirst();\n+\n+ // [VERIFY] Interaction Log Entry has Evaluation field populated as Positive.\n+ Assert.AreEqual(\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.Evaluation,\n+ StrSubstNo(\n+ EvaluationErr,\n+ InteractionLogEntry.FieldCaption(Evaluation),\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibrarySales: Codeunit \"Library - Sales\";\n@@ -4309,5 +4354,16 @@ CopyStr(StorageLocation, 1, MaxStrLen(MarketingSetup.\"Attachment Storage Locatio\n CreateInteraction.NextInteraction.Invoke();\n CreateInteraction.Finish.Invoke();\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure CreateInteractionFromContactPageHandler(var CreateInteraction: TestPage \"Create Interaction\")\n+ begin\n+ CreateInteraction.\"Interaction Template Code\".SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.Evaluation.SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.FinishInteraction.Invoke();\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\nindex ff43f4ff6a7b..05a21a6196bf 100644\n--- a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n+++ b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n@@ -694,6 +694,7 @@ page 5077 \"Create Interaction\"\n end;\n Step::\"Step 4\":\n begin\n+ InteractionLogEntry.CopyFromSegment(Rec);\n InteractionLogEntry.Modify();\n CurrPage.Close();\n end;\n"} +{"metadata": {"area": "Peppol", "image_count": 1}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8059", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-08T09:31:42Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\PEPPOL\\App", "src\\Apps\\W1\\PEPPOL\\Test"], "patch": "diff --git a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\nindex 30f5f792bd..c7981a46fa 100644\n--- a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n@@ -798,6 +798,8 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n InvoiceLineNote := DelChr(Format(SalesLine.Type), '<>');\n InvoicedQuantity := Format(SalesLine.Quantity, 0, 9);\n SalesLineLineAmount := SalesLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesLineLineAmount := Round(SalesLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n InvoiceLineExtensionAmount := Format(SalesLineLineAmount, 0, 9);\n LineExtensionAmountCurrencyID := GetSalesDocCurrencyCode(SalesHeader);\n InvoiceLineAccountingCost := '';\n@@ -869,7 +871,10 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n \n InvLnAllowanceChargeIndicator := 'false';\n InvLnAllowanceChargeReason := LineDisAmtTxt;\n- InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ InvLnAllowanceChargeAmount := Format(Round(SalesLine.\"Line Discount Amount\" / (1 + SalesLine.\"VAT %\" / 100), 0.01), 0, 9)\n+ else\n+ InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n InvLnAllowanceChargeAmtCurrID := GetSalesDocCurrencyCode(SalesHeader);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139235, "functionName": ["LineAmountsConsistentWhenPricesInclVATNoDiscount"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\nindex 36931d56ed..cd237011d5 100644\n--- a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n@@ -3349,6 +3349,68 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual('', CustTaxSchemeID, 'Tax Scheme ID should be empty for Tax Category O.');\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ procedure LineAmountsConsistentWhenPricesInclVATNoDiscount()\n+ var\n+ SalesHeader: Record \"Sales Header\";\n+ SalesLine: Record \"Sales Line\";\n+ Customer: Record Customer;\n+ Item: Record Item;\n+ SalesInvoiceHeader: Record \"Sales Invoice Header\";\n+ SalesInvoiceLine: Record \"Sales Invoice Line\";\n+ PEPPOLLineInfoProvider: Interface \"PEPPOL Line Info Provider\";\n+ InvoiceLineID: Text;\n+ InvoiceLineNote: Text;\n+ InvoicedQuantity: Text;\n+ InvoiceLineExtensionAmount: Text;\n+ LineExtensionAmountCurrencyID: Text;\n+ InvoiceLineAccountingCost: Text;\n+ InvoiceLinePriceAmount: Text;\n+ InvLinePriceAmountCurrencyID: Text;\n+ BaseQuantity: Text;\n+ UnitCode: Text;\n+ PriceAmount: Decimal;\n+ LineExtensionAmt: Decimal;\n+ SalesInvoiceNo: Code[20];\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 630795] PEPPOL LineExtensionAmount equals PriceAmount times Quantity when Prices Including VAT is used\n+ Initialize();\n+\n+ // [GIVEN] Customer \"C\" with PEPPOL identifier\n+ LibrarySales.CreateCustomer(Customer);\n+ AddCustPEPPOLIdentifier(Customer.\"No.\");\n+\n+ // [GIVEN] Sales Invoice for \"C\" with \"Prices Including VAT\" = TRUE and Quantity = 7\n+ CreateItemWithPrice(Item, 139);\n+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader.\"Document Type\"::Invoice, Customer.\"No.\");\n+ SalesHeader.Validate(\"Prices Including VAT\", true);\n+ SalesHeader.Modify(true);\n+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item.\"No.\", 7);\n+\n+ // [WHEN] Post the Sales Invoice and retrieve PEPPOL line amounts\n+ SalesInvoiceNo := LibrarySales.PostSalesDocument(SalesHeader, true, true);\n+ SalesInvoiceHeader.Get(SalesInvoiceNo);\n+ SalesHeader.TransferFields(SalesInvoiceHeader);\n+ FindSalesInvoiceLine(SalesInvoiceLine, SalesInvoiceNo);\n+ SalesLine.TransferFields(SalesInvoiceLine);\n+\n+ PEPPOLLineInfoProvider := GetFormat();\n+ PEPPOLLineInfoProvider.GetLineGeneralInfo(\n+ SalesLine, SalesHeader, InvoiceLineID, InvoiceLineNote, InvoicedQuantity,\n+ InvoiceLineExtensionAmount, LineExtensionAmountCurrencyID, InvoiceLineAccountingCost);\n+ PEPPOLLineInfoProvider.GetLinePriceInfo(\n+ SalesLine, SalesHeader, InvoiceLinePriceAmount, InvLinePriceAmountCurrencyID,\n+ BaseQuantity, UnitCode);\n+\n+ // [THEN] LineExtensionAmount equals PriceAmount times Quantity per PEPPOL BIS 3.0\n+ Evaluate(PriceAmount, InvoiceLinePriceAmount, 9);\n+ Evaluate(LineExtensionAmt, InvoiceLineExtensionAmount, 9);\n+ Assert.AreEqual(PriceAmount * SalesInvoiceLine.Quantity, LineExtensionAmt,\n+ 'LineExtensionAmount must equal PriceAmount * Quantity per PEPPOL BIS 3.0');\n+ end;\n+\n var\n local procedure Initialize()\n var\n@@ -3993,6 +4055,8 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual(UnitOfMeasure.\"International Standard Code\", unitCode, '');\n Assert.AreEqual('UNECERec20', unitCodeListID, '');\n SalesInvoiceLineLineAmount := SalesInvoiceLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesInvoiceLineLineAmount := Round(SalesInvoiceLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n Assert.AreEqual(Format(SalesInvoiceLineLineAmount, 0, 9), InvoiceLineExtensionAmount, '');\n Assert.AreEqual(SalesHeader.\"Currency Code\", LineExtensionAmountCurrencyID, '');\n Assert.AreEqual('', InvoiceLineAccountingCost, '');\n"} +{"metadata": {"area": "Manufacturing", "image_count": 0}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "bb325c49266ab81baa1c3c2a1154c182019929d4", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7953", "base_commit": "907fd4ab20c5a3156d2d3dac5787bce3a272bb57", "created_at": "2026-05-04T20:30:22Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\EDocument\\App", "src\\Apps\\W1\\EDocument\\Test"], "patch": "diff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al\nnew file mode 100644\nindex 0000000000..45c2b7121f\n--- /dev/null\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al\n@@ -0,0 +1,20 @@\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+namespace Microsoft.eServices.EDocument;\n+\n+enum 6162 \"E-Doc. Purch.Def. Posting Date\"\n+{\n+ Extensible = false;\n+ Caption = 'Purchase Invoice Posting Date (E-Docs)';\n+\n+ value(0; \"Work Date\")\n+ {\n+ Caption = 'Work Date';\n+ }\n+ value(1; \"Document Date\")\n+ {\n+ Caption = 'Document Date';\n+ }\n+}\ndiff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\nindex 08b2a7a822..556fbad792 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n@@ -21,6 +21,11 @@ pageextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n ApplicationArea = All;\n ToolTip = 'Specifies whether Copilot E-Document line matchings are learned by default (Item References and Text To Account Mappings). This can be overwritten on the matching page.';\n }\n+ field(\"E-Doc. Def. Posting Date\"; Rec.\"E-Doc. Def. Posting Date\")\n+ {\n+ ApplicationArea = All;\n+ ToolTip = 'Specifies how the posting date is set on purchase invoices created from e-documents. Work Date uses the current work date. Document Date uses the document date from the e-document.';\n+ }\n }\n }\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\nindex 24013c63c5..2dc0c9ccec 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n@@ -21,5 +21,10 @@ tableextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n Caption = 'E-Document Learn Copilot Matchings';\n DataClassification = SystemMetadata;\n }\n+ field(6102; \"E-Doc. Def. Posting Date\"; Enum \"E-Doc. Purch.Def. Posting Date\")\n+ {\n+ Caption = 'E-Document Default Posting Date';\n+ DataClassification = CustomerContent;\n+ }\n }\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\nindex b97c6db072..14907342c4 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\n@@ -100,6 +100,7 @@ codeunit 6404 \"E-Doc. Create Purch. Cr. Memo\" implements IEDocumentFinishDraft,\n if EDocumentPurchaseHeader.\"Purchase Order No.\" <> '' then\n PurchaseHeader.\"Vendor Order No.\" := CopyStr(EDocumentPurchaseHeader.\"Purchase Order No.\", 1, MaxStrLen(PurchaseHeader.\"Vendor Order No.\"));\n PurchaseHeader.Insert(true);\n+ EDocPurchaseDocumentHelper.ApplyDefaultPostingDateFromSetup(PurchaseHeader, EDocumentPurchaseHeader);\n PurchaseHeader.Modify();\n \n GLSetup.GetRecordOnce();\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\nindex 0f2b7905d4..f79acb69fe 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n@@ -129,6 +129,7 @@ codeunit 6117 \"E-Doc. Create Purchase Invoice\" implements IEDocumentFinishDraft,\n PurchaseHeader.\"Vendor Order No.\" := CopyStr(EDocumentPurchaseHeader.\"Purchase Order No.\", 1, MaxStrLen(PurchaseHeader.\"Vendor Order No.\"));\n PurchaseHeader.Insert(true);\n \n+ EDocPurchaseDocumentHelper.ApplyDefaultPostingDateFromSetup(PurchaseHeader, EDocumentPurchaseHeader);\n PurchaseHeader.\"Invoice Received Date\" := PurchaseHeader.\"Document Date\";\n PurchaseHeader.Modify();\n \ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\nindex dd97e61275..d21ea96b71 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n@@ -11,6 +11,7 @@ using Microsoft.Finance.Dimension;\n using Microsoft.Foundation.Attachment;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.Posting;\n+using Microsoft.Purchases.Setup;\n \n /// \n /// Shared logic for creating BC purchase documents (invoices and credit memos) from e-document draft data.\n@@ -137,4 +138,16 @@ codeunit 6402 \"E-Doc. Purch. Doc. Helper\"\n Clear(PurchaseHeader.\"E-Document Link\");\n PurchaseHeader.Modify();\n end;\n+\n+ procedure ApplyDefaultPostingDateFromSetup(var PurchaseHeader: Record \"Purchase Header\"; EDocumentPurchaseHeader: Record \"E-Document Purchase Header\")\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ begin\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ if (PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" <> PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\"::\"Document Date\") then\n+ exit;\n+ if EDocumentPurchaseHeader.\"Document Date\" = 0D then\n+ exit;\n+ PurchaseHeader.Validate(\"Posting Date\", EDocumentPurchaseHeader.\"Document Date\");\n+ end;\n }\n", "FAIL_TO_PASS": [{"codeunitID": 139883, "functionName": ["InvoicePostingDateUsesDocumentDateWhenSettingIsDocumentDate", "InvoicePostingDateDefaultsToWorkDateWhenSettingIsWorkDate", "CreditMemoPostingDateDefaultsToWorkDateWhenSettingIsWorkDate", "CreditMemoPostingDateUsesDocumentDateWhenSettingIsDocumentDate"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml\nnew file mode 100644\nindex 0000000000..52cd211620\n--- /dev/null\n+++ b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml\n@@ -0,0 +1,200 @@\n+\n+\n+\turn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0\n+\turn:fdc:peppol.eu:2017:poacc:billing:01:1.0\n+\t103033\n+\t2026-01-22\n+\t2026-02-22\n+\t380\n+\t1\n+\t\n+\t\t2\n+\t\n+\t\n+\t\t103033\n+\t\n+\t\n+\t\t103033\n+\t\t\n+\t\t\n+\t\t\t\n+\t\t\t\t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MzAxMjE5MDBaKS9Nb2REYXRlKEQ6MjAyMjA2MTUxMzEzMDBaKT4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAzIDAgUi9MYW5nKGVuLVVTKS9NZXRhZGF0YSA0IDAgUj4+DQplbmRvYmoNCjMgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWzUgMCBSXT4+DQplbmRvYmoNCjQgMCBvYmoNCjw8L1R5cGUvTWV0YWRhdGEvU3VidHlwZS9YTUwvTGVuZ3RoIDIxIDAgUj4+c3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJQREZOZXQiPgo8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgo8eG1wOkNyZWF0ZURhdGU+MjAxNy0wMS0zMFQxMjoxOTowMFo8L3htcDpDcmVhdGVEYXRlPgo8eG1wOk1vZGlmeURhdGU+MjAyMi0wNi0xNVQxMzoxMzowMFo8L3htcDpNb2RpZnlEYXRlPgo8eG1wOkNyZWF0b3JUb29sPk1pY3Jvc29mdCBPZmZpY2UgV29yZDwveG1wOkNyZWF0b3JUb29sPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KPGRjOmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KPGRjOnRpdGxlPgo8cmRmOkFsdD4KPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5TYWxlcyAtIEludm9pY2U8L3JkZjpsaT4KPC9yZGY6QWx0Pgo8L2RjOnRpdGxlPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6cGRmPSJodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8xLjMvIj4KPHBkZjpQcm9kdWNlcj5Bc3Bvc2UuV29yZHMgZm9yIC5ORVQgMjMuOS4wPC9wZGY6UHJvZHVjZXI+CjwvcmRmOkRlc2NyaXB0aW9uPgo8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJ3Ij8+Cg0KZW5kc3RyZWFtDQplbmRvYmoNCjIxIDAgb2JqDQo4NTQNCmVuZG9iag0KMTYgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCRytTZWdvZVVJLUJvbGQvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nL0ZpcnN0Q2hhciAzMi9MYXN0Q2hhciAxNjMvV2lkdGhzIDE3IDAgUi9Gb250RGVzY3JpcHRvciAxOCAwIFI+Pg0KZW5kb2JqDQoxNyAwIG9iag0KWzI3NiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMjcxIDAgMjcxIDAgNTc1IDU3NSA1NzUgMCA1NzUgNTc1IDAgNTc1IDAgNTc1IDAgMCAwIDAgMCAwIDAgNzAzIDY0MSA2MjQgMCAwIDAgNzExIDAgMCAwIDY0OSA1MTEgOTU3IDAgMCA2MTQgMCAwIDU2MSA1ODYgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNTM4IDAgMCA2MTkgNTQxIDAgNjE5IDYwMiAyODQgMCA1NTkgMjg0IDkxNiA2MDUgNjExIDYyMCA2MTkgMzk4IDAgMzg5IDYwNSAwIDAgMCA1MzggMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDU3NV0NCmVuZG9iag0KMTggMCBvYmoNCjw8L1R5cGUvRm9udERlc2NyaXB0b3IvRm9udE5hbWUvRkFBQUJHK1NlZ29lVUktQm9sZC9TdGVtViA4MC9EZXNjZW50IC0yNTEvQXNjZW50IDEwNzkvQ2FwSGVpZ2h0IDcwMC9GbGFncyAyNjIxNzYvSXRhbGljQW5nbGUgMC9Gb250QkJveFstNTczIC00MzEgMTk5OSAxMjk4XS9Gb250RmlsZTIgMTUgMCBSPj4NCmVuZG9iag0KMTIgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCQytTZWdvZVVJLUxpZ2h0L0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTE4L1dpZHRocyAxMyAwIFIvRm9udERlc2NyaXB0b3IgMTQgMCBSPj4NCmVuZG9iag0KMTMgMCBvYmoNClsyNzQgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDIyMiAwIDIyMiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCA2MjkgNTQ0IDYyMSAwIDAgMCAwIDAgMjI4IDAgMCAwIDAgNzA5IDc2MSAwIDAgNTU1IDQ5NyAwIDY0OCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNDk0IDAgNDQ0IDAgNTA1IDAgNTYwIDUzNSAyMDUgMCAwIDAgODIyIDUzNSA1NjEgMCAwIDMzMCAwIDAgMCA0NTNdDQplbmRvYmoNCjE0IDAgb2JqDQo8PC9UeXBlL0ZvbnREZXNjcmlwdG9yL0ZvbnROYW1lL0ZBQUFCQytTZWdvZVVJLUxpZ2h0L1N0ZW1WIDgwL0Rlc2NlbnQgLTI1MS9Bc2NlbnQgMTA3OS9DYXBIZWlnaHQgNzAwL0ZsYWdzIDMyL0l0YWxpY0FuZ2xlIDAvRm9udEJCb3hbLTU4NyAtMzk2IDE5OTkgMTI5OV0vRm9udEZpbGUyIDExIDAgUj4+DQplbmRvYmoNCjggMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFBSStTZWdvZVVJL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTIxL1dpZHRocyA5IDAgUi9Gb250RGVzY3JpcHRvciAxMCAwIFI+Pg0KZW5kb2JqDQo5IDAgb2JqDQpbMjc0IDAgMCAwIDAgODE4IDAgMCAwIDAgMCA2ODQgMjE3IDQwMCAyMTcgMzkwIDUzOSA1MzkgNTM5IDUzOSA1MzkgNTM5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MODW9nYEFJ/+03vN/EfC/wC1cf8ACIPH+01vN/EfCv7Vx/wiC9HFLTNYMWxuxVMjJqiy2qjoJ5oteR76aBkTnN1AOhLdRqEGNd+9i8S6h9v59vcxrLjbrca2G5UdwtckcdRDV07ZGRP+VjkY5ukjgWlvEd4PFBULn/lQbnWuaon243CsOW0DdXQ0d4jntNby6ahg8MVUL3Ds1L2A9ug7EEart5fvVtaJSx21Elxi1+TqaC62qoY7QAk8ravnHbp7TRr3IOtUvRP1U1kvhQ7LX1jg0u5pzTQN0H5807G6+rVBlPFvLW6qMhkjF0xuzYVBIW/9zervTPAaeOpZbjWvGnoLdfUgnPtB5VeB49U0l33izCpz2ohIe7F7Sx9ttpcO1k1Rzmpmb62GE/1haTjuOWDEbLb8cxay0WPWG1R+DbrPb4GU9NCzUnRkcYDRqSSeHE8TxQc0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIP/2Q0KZW5kc3RyZWFtDQplbmRvYmoNCjIyIDAgb2JqDQoxNTE2OA0KZW5kb2JqDQoxNSAwIG9iag0KPDwvTGVuZ3RoMSAyMyAwIFIvTGVuZ3RoIDI0IDAgUi9GaWx0ZXIvRmxhdGVEZWNvZGU+PnN0cmVhbQ0KeJzsfAl4VFWW8LlvqX1PVVJJBfIqlbAVppJUAokgKcjCEoghCZgCgilIQgKBBBJAVBaHIBpXRFRwaVptRntorWCPHVFbnHZp/XXcp8Vuu22l3RqQ7kb0Q/Jqzr3vVVJhcfz7m+lv5vt4lXffufeee+/Z7jnnPqoAAgBm2AI8VF9eG8hvvDX0Abb8Du/GpSsjnbpb9Q4AMhnvuqXruqWNk9paALjbAQw5LZ3LVs6seX8ZgOkQ1hcta9/Q8tD8f3oMICUdwHWktTnSdB9kcACX4HQwoRUbnBbdp1gvwnpW68ruqx5/0erF+iKs39fesTQC5KHrsf4t1veujFzVyT9t/hAg5x6sS6siK5s/tq57A+v9AGOyOju6umNzYT3AfEqv1LmmuXPFX9J1WD8DIFwCvNDPPQMi6MQ9YhA58ChP/i1o4Rw6kTPqOAE/HH8EcmKH4MhmnEVPSZ1TK0kggTk2IL4jzyVm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\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t103033\n+\t\t\n+\t\t\n+\t\t\t\n+\t\t\t\t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MzAxMjE5MDBaKS9Nb2REYXRlKEQ6MjAyMjA2MTUxMzEzMDBaKT4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAzIDAgUi9MYW5nKGVuLVVTKS9NZXRhZGF0YSA0IDAgUj4+DQplbmRvYmoNCjMgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWzUgMCBSXT4+DQplbmRvYmoNCjQgMCBvYmoNCjw8L1R5cGUvTWV0YWRhdGEvU3VidHlwZS9YTUwvTGVuZ3RoIDIxIDAgUj4+c3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJQREZOZXQiPgo8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgo8eG1wOkNyZWF0ZURhdGU+MjAxNy0wMS0zMFQxMjoxOTowMFo8L3htcDpDcmVhdGVEYXRlPgo8eG1wOk1vZGlmeURhdGU+MjAyMi0wNi0xNVQxMzoxMzowMFo8L3htcDpNb2RpZnlEYXRlPgo8eG1wOkNyZWF0b3JUb29sPk1pY3Jvc29mdCBPZmZpY2UgV29yZDwveG1wOkNyZWF0b3JUb29sPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KPGRjOmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KPGRjOnRpdGxlPgo8cmRmOkFsdD4KPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5TYWxlcyAtIEludm9pY2U8L3JkZjpsaT4KPC9yZGY6QWx0Pgo8L2RjOnRpdGxlPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6cGRmPSJodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8xLjMvIj4KPHBkZjpQcm9kdWNlcj5Bc3Bvc2UuV29yZHMgZm9yIC5ORVQgMjMuOS4wPC9wZGY6UHJvZHVjZXI+CjwvcmRmOkRlc2NyaXB0aW9uPgo8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJ3Ij8+Cg0KZW5kc3RyZWFtDQplbmRvYmoNCjIxIDAgb2JqDQo4NTQNCmVuZG9iag0KMTYgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCRytTZWdvZVVJLUJvbGQvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nL0ZpcnN0Q2hhciAzMi9MYXN0Q2hhciAxNjMvV2lkdGhzIDE3IDAgUi9Gb250RGVzY3JpcHRvciAxOCAwIFI+Pg0KZW5kb2JqDQoxNyAwIG9iag0KWzI3NiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMjcxIDAgMjcxIDAgNTc1IDU3NSA1NzUgMCA1NzUgNTc1IDAgNTc1IDAgNTc1IDAgMCAwIDAgMCAwIDAgNzAzIDY0MSA2MjQgMCAwIDAgNzExIDAgMCAwIDY0OSA1MTEgOTU3IDAgMCA2MTQgMCAwIDU2MSA1ODYgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNTM4IDAgMCA2MTkgNTQxIDAgNjE5IDYwMiAyODQgMCA1NTkgMjg0IDkxNiA2MDUgNjExIDYyMCA2MTkgMzk4IDAgMzg5IDYwNSAwIDAgMCA1MzggMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDU3NV0NCmVuZG9iag0KMTggMCBvYmoNCjw8L1R5cGUvRm9udERlc2NyaXB0b3IvRm9udE5hbWUvRkFBQUJHK1NlZ29lVUktQm9sZC9TdGVtViA4MC9EZXNjZW50IC0yNTEvQXNjZW50IDEwNzkvQ2FwSGVpZ2h0IDcwMC9GbGFncyAyNjIxNzYvSXRhbGljQW5nbGUgMC9Gb250QkJveFstNTczIC00MzEgMTk5OSAxMjk4XS9Gb250RmlsZTIgMTUgMCBSPj4NCmVuZG9iag0KMTIgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCQytTZWdvZVVJLUxpZ2h0L0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTE4L1dpZHRocyAxMyAwIFIvRm9udERlc2NyaXB0b3IgMTQgMCBSPj4NCmVuZG9iag0KMTMgMCBvYmoNClsyNzQgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDIyMiAwIDIyMiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCA2MjkgNTQ0IDYyMSAwIDAgMCAwIDAgMjI4IDAgMCAwIDAgNzA5IDc2MSAwIDAgNTU1IDQ5NyAwIDY0OCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNDk0IDAgNDQ0IDAgNTA1IDAgNTYwIDUzNSAyMDUgMCAwIDAgODIyIDUzNSA1NjEgMCAwIDMzMCAwIDAgMCA0NTNdDQplbmRvYmoNCjE0IDAgb2JqDQo8PC9UeXBlL0ZvbnREZXNjcmlwdG9yL0ZvbnROYW1lL0ZBQUFCQytTZWdvZVVJLUxpZ2h0L1N0ZW1WIDgwL0Rlc2NlbnQgLTI1MS9Bc2NlbnQgMTA3OS9DYXBIZWlnaHQgNzAwL0ZsYWdzIDMyL0l0YWxpY0FuZ2xlIDAvRm9udEJCb3hbLTU4NyAtMzk2IDE5OTkgMTI5OV0vRm9udEZpbGUyIDExIDAgUj4+DQplbmRvYmoNCjggMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFBSStTZWdvZVVJL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTIxL1dpZHRocyA5IDAgUi9Gb250RGVzY3JpcHRvciAxMCAwIFI+Pg0KZW5kb2JqDQo5IDAgb2JqDQpbMjc0IDAgMCAwIDAgODE4IDAgMCAwIDAgMCA2ODQgMjE3IDQwMCAyMTcgMzkwIDUzOSA1MzkgNTM5IDUzOSA1MzkgNTM5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MODW9nYEFJ/+03vN/EfC/wC1cf8ACIPH+01vN/EfCv7Vx/wiC9HFLTNYMWxuxVMjJqiy2qjoJ5oteR76aBkTnN1AOhLdRqEGNd+9i8S6h9v59vcxrLjbrca2G5UdwtckcdRDV07ZGRP+VjkY5ukjgWlvEd4PFBULn/lQbnWuaon243CsOW0DdXQ0d4jntNby6ahg8MVUL3Ds1L2A9ug7EEart5fvVtaJSx21Elxi1+TqaC62qoY7QAk8ravnHbp7TRr3IOtUvRP1U1kvhQ7LX1jg0u5pzTQN0H5807G6+rVBlPFvLW6qMhkjF0xuzYVBIW/9zervTPAaeOpZbjWvGnoLdfUgnPtB5VeB49U0l33izCpz2ohIe7F7Sx9ttpcO1k1Rzmpmb62GE/1haTjuOWDEbLb8cxay0WPWG1R+DbrPb4GU9NCzUnRkcYDRqSSeHE8TxQc0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIP/2Q0KZW5kc3RyZWFtDQplbmRvYmoNCjIyIDAgb2JqDQoxNTE2OA0KZW5kb2JqDQoxNSAwIG9iag0KPDwvTGVuZ3RoMSAyMyAwIFIvTGVuZ3RoIDI0IDAgUi9GaWx0ZXIvRmxhdGVEZWNvZGU+PnN0cmVhbQ0KeJzsfAl4VFWW8LlvqX1PVVJJBfIqlbAVppJUAokgKcjCEoghCZgCgilIQgKBBBJAVBaHIBpXRFRwaVptRntorWCPHVFbnHZp/XXcp8Vuu22l3RqQ7kb0Q/Jqzr3vVVJhcfz7m+lv5vt4lXffufeee+/Z7jnnPqoAAgBm2AI8VF9eG8hvvDX0Abb8Du/GpSsjnbpb9Q4AMhnvuqXruqWNk9paALjbAQw5LZ3LVs6seX8ZgOkQ1hcta9/Q8tD8f3oMICUdwHWktTnSdB9kcACX4HQwoRUbnBbdp1gvwnpW68ruqx5/0erF+iKs39fesTQC5KHrsf4t1veujFzVyT9t/hAg5x6sS6siK5s/tq57A+v9AGOyOju6umNzYT3AfEqv1LmmuXPFX9J1WD8DIFwCvNDPPQMi6MQ9YhA58ChP/i1o4Rw6kTPqOAE/HH8EcmKH4MhmnEVPSZ1TK0kggTk2IL4jzyVm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\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t1234567890128\n+\t\t\t\n+\t\t\t\tCRONUS International\n+\t\t\t\n+\t\t\t\n+\t\t\t\tMain Street, 14\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tGB123456789\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tCRONUS International\n+\t\t\t\t123456789\n+\t\t\t\n+\t\t\t\n+\t\t\t\tJim Olive\n+\t\t\t\tJO@contoso.com\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t789456278\n+\t\t\t\n+\t\t\t\t8712345000004\n+\t\t\t\n+\t\t\t\n+\t\t\t\tThe Cannon Group PLC\n+\t\t\t\n+\t\t\t\n+\t\t\t\t192 Market Square\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tGB789456278\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tThe Cannon Group PLC\n+\t\t\t\t789456278\n+\t\t\t\n+\t\t\t\n+\t\t\t\tMr. Andy Teal\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t2026-01-22\n+\t\t\n+\t\t\t8712345000004\n+\t\t\t\n+\t\t\t\t192 Market Square\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t31\n+\t\t\n+\t\t\tGB12CPBK08929965044991\n+\t\t\t\n+\t\t\t\tBG99999\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t1 Month/2% 8 days\n+\t\n+\t\n+\t\t1000\n+\t\t\n+\t\t\t4000\n+\t\t\t1000\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t14000\n+\t\t14000\n+\t\t14140\n+\t\t0\n+\t\t0.00\n+\t\t0\n+\t\t14140\n+\t\n+\t\n+\t\t10000\n+\t\tItem\n+\t\t1\n+\t\t4000\n+\t\t\n+\t\t\tBicycle\n+\t\t\t\n+\t\t\t\t1000\n+\t\t\t\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\t\n+\t\t\t4000.00\n+\t\t\t1\n+\t\t\n+\t\n+\t\n+\t\t20000\n+\t\tItem\n+\t\t2\n+\t\t10000\n+\t\t\n+\t\t\tBicycle v2\n+\t\t\t\n+\t\t\t\t2000\n+\t\t\t\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\t\n+\t\t\t5000.00\n+\t\t\t2\n+\t\t\n+\t\n+\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\nindex 8a391d8117..7d3502ca5c 100644\n--- a/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\n+++ b/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\n@@ -21,6 +21,7 @@ using Microsoft.Inventory.Location;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.History;\n using Microsoft.Purchases.Payables;\n+using Microsoft.Purchases.Setup;\n using Microsoft.Purchases.Vendor;\n using Microsoft.Sales.Customer;\n using System.IO;\n@@ -884,6 +885,138 @@ codeunit 139883 \"E-Doc Process Test\"\n Assert.RecordCount(PurchaseLine, 2);\n end;\n \n+ [Test]\n+ procedure InvoicePostingDateDefaultsToWorkDateWhenSettingIsWorkDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Work Date\" (default), the created purchase invoice Posting Date equals WorkDate\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Work Date\" (default)\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL invoice (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-0.xml', TempEDocImportParams), 'The e-document should be processed');\n+\n+ // [THEN] Posting Date is WorkDate, not the document date\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(1, 1, 2027), PurchaseHeader.\"Posting Date\", 'Posting Date should be WorkDate when setting is Work Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure InvoicePostingDateUsesDocumentDateWhenSettingIsDocumentDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Document Date\", the created purchase invoice Posting Date equals the e-document's Document Date\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Document Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Document Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL invoice (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-no-currency.xml', TempEDocImportParams), 'The e-document should be processed');\n+\n+ // [THEN] Posting Date equals the Document Date from the PEPPOL file\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(22, 1, 2026), PurchaseHeader.\"Posting Date\", 'Posting Date should be Document Date when setting is Document Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure CreditMemoPostingDateDefaultsToWorkDateWhenSettingIsWorkDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Work Date\", the created purchase credit memo Posting Date equals WorkDate\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Work Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL credit note (IssueDate = 2026-02-15) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-creditnote-0.xml', TempEDocImportParams), 'The credit note e-document should be processed');\n+\n+ // [THEN] Posting Date is WorkDate\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(1, 1, 2027), PurchaseHeader.\"Posting Date\", 'Posting Date should be WorkDate when setting is Work Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure CreditMemoPostingDateUsesDocumentDateWhenSettingIsDocumentDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Document Date\", the created purchase credit memo Posting Date equals the e-document's Document Date\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Document Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Document Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL credit note (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-no-currency.xml', TempEDocImportParams), 'The credit note e-document should be processed');\n+\n+ // [THEN] Posting Date equals the Document Date from the PEPPOL file\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(22, 1, 2026), PurchaseHeader.\"Posting Date\", 'Posting Date should be Document Date when setting is Document Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n local procedure Initialize(Integration: Enum \"Service Integration\")\n var\n TransformationRule: Record \"Transformation Rule\";\n@@ -893,6 +1026,7 @@ codeunit 139883 \"E-Doc Process Test\"\n EDocPurchLineFieldSetup: Record \"ED Purchase Line Field Setup\";\n PurchInvHeader: Record \"Purch. Inv. Header\";\n VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n GLSetup: Record \"General Ledger Setup\";\n Currency: Record Currency;\n LibraryERM: Codeunit \"Library - ERM\";\n@@ -902,6 +1036,10 @@ codeunit 139883 \"E-Doc Process Test\"\n Clear(EDocImplState);\n EDocPurchLineFieldSetup.DeleteAll();\n \n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n PurchInvHeader.DeleteAll();\n VendorLedgerEntry.DeleteAll();\n \n"} diff --git a/dataset/problemstatement/microsoft__BCApps-7953/README.md b/dataset/problemstatement/microsoft__BCApps-7953/README.md new file mode 100644 index 000000000..8a34022b3 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-7953/README.md @@ -0,0 +1,20 @@ +# Bug 623926: Add configurable default posting date for e-document purchases + +## Why + +When the Payables Agent (or manual processing) creates purchase invoices and credit memos from incoming e-documents, the posting date always defaults to the current work date — ignoring the document date present in the e-document. This forces users to manually correct the posting date to match the original invoice date, which is error-prone and inconvenient. + +## Summary + +- **Added** `E-Doc. Default Posting Date` enum with "Work Date" (default) and "Document Date" options +- **Added** corresponding field to the Purchases & Payables Setup table and page extensions, allowing users to configure the behavior +- **Added** `ApplyDefaultPostingDateFromSetup` procedure in `EDocPurchDocHelper` — called during both invoice and credit memo creation to set the posting date from the e-document's document date when the setting is "Document Date" +- **Added** 4 tests covering invoice and credit memo scenarios for both posting date options, plus a new PEPPOL test resource XML + +[AB#623926](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/623926) + + + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-8059/README.md b/dataset/problemstatement/microsoft__BCApps-8059/README.md new file mode 100644 index 000000000..6fdaf7b36 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8059/README.md @@ -0,0 +1,38 @@ +# Title: [master][All-e]Peppol E-Invoice cannot be validated when price incl VAT is used in a document +## Repro Steps: +1. Go to Company Information and add a SWIFT Code (you need to created a new one, but it can be any number) +2. Go to E-Document Services and open the E-DOCUMENTS + Document Format should be PEPPOL BIS 3.0 +3. In the E-Document Service use buton "Configure documents to export" and add the sales invoice +4. Go to Electronic Document Formats and make sure you have the setup for PEPPOL BIS3 / Sales Invoice / Codeunit 1610 +5. Go to Workflows and make sure you have the default workflow for "Send E-Documents to one Service" enabled +6. Go to Document Sending Profiles, check E-DOCUMENTS and make sure this uses + Electronic Document = E-Document Workflow + E-Document Workflow = MS-EDOCSTOS-01 (the one from step 5) +7. Open Customer Card 10000 and change the following: + Document Sending Profile = E-DOCUMENTS + VAT Registration No = GB123456789 +8. Create a new Sales Invoice for customer 10000 + Posting / Document Date = (use the suggested ones) + Your Reference = TEST + Price Incl VAT = YES +9. Now add a new line to the sales invoice: + 1x item 1896-S +10. Post the Sales invoice with option Post and Send +11. Go to E-Documents  + The newest entry should be the one that we just created by posting the sales invoice with post and send + Highlight that entry, then go to Actions -> E-Document Logs +12. From the E-Document Logs you can download the e-invoice with button Export File, an XML file is now exported +13. Open a Peppol Validator (e.g. [Free Online Peppol Validator. Validate UBL & XML Invoices Instantly](https://peppolvalidator.com/)), upload and validate the e-invoice downloaded in step 12 + +**Expected Outcome:** +The file should validate without error messages + +**Actual Outcome:** +The file cannot be validated without error messages: +![Image](./error_message.png) + +**Troubleshooting Actions Taken:** +When you post a sales invoice that does not have option Price incl VAT enabled, the created e-document can be validated without error message. + +## Description: diff --git a/dataset/problemstatement/microsoft__BCApps-8059/error_message.png b/dataset/problemstatement/microsoft__BCApps-8059/error_message.png new file mode 100644 index 0000000000000000000000000000000000000000..7ca52550722f4494aa61669821ffafc7c5f11bb2 GIT binary patch literal 118854 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 literal 0 HcmV?d00001 diff --git a/dataset/problemstatement/microsoft__BCApps-8253/README.md b/dataset/problemstatement/microsoft__BCApps-8253/README.md new file mode 100644 index 000000000..8e16f6d58 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8253/README.md @@ -0,0 +1,25 @@ +# (Bug 633226): [Subcontracting] Standard Task not propagated from Routing to Prod. Order Routing or Subcontracting Worksheet; prices not picked up + +## Summary + +The Subcontracting Worksheet flow was dropping `Standard Task Code` between the Prod. Order Routing Line and the Requisition Line, the field on the worksheet was read-only, and Subcontractor Prices keyed on a Standard Task were therefore never applied. This change: + +- Propagates `Standard Task Code` from `Prod. Order Routing Line` to `Requisition Line` in both worksheet-population paths (Calculate Subcontracts… on the worksheet, and direct PO creation from a Prod. Order Routing line). +- Makes the `Standard Task Code` field editable on the Subcontracting Worksheet so users can override it. +- Causes the standard-task-bound subcontractor price to flow through to the Subcontracting Purchase Order's `Direct Unit Cost`. + +The bug enumerated four symptoms (Routing → Prod. Order Routing, Prod. Order Routing → Worksheet, field not editable, prices not picked up). Routing → Prod. Order Routing was already handled by `Prod. Order Routing Line.CopyFromRoutingLine`; no change there. The remaining three are addressed below. + +## Changes + +### `SubcCalcSubcontractsExt.Codeunit.al` +Extended the existing `OnAfterTransferProdOrderRoutingLine` subscriber on report `Subc. Calculate Subcontracts` to also `Validate("Standard Task Code", ProdOrderRoutingLine."Standard Task Code")` on the new requisition line. Using `Validate` (not direct assignment) fires the field's OnValidate trigger in `Subc. RequisitionLine`, which calls `UpdateSubcontractorPrice` → `Subc. Price Management.GetSubcPriceForReqLine`. The price lookup already filters `Subcontractor Price` by `RequisitionLine."Standard Task Code"` exactly, so the standard-task-bound price is applied immediately. + +### `SubcPurchaseOrderCreator.Codeunit.al` +Same fix in `InsertReqWkshLine`, which is the alternate worksheet-line builder used when a Subcontracting PO is created directly from a Prod. Order Routing Line (bypassing the worksheet UI). + +### `SubcSubcontractingWorksheet.Page.al` +Removed `Editable = false` from the `Standard Task Code` field and added a tooltip clarifying that editing the value re-applies the matching subcontractor price. The field's OnValidate already triggers price re-lookup, so manual edits/clears on the worksheet immediately update `Direct Unit Cost`. + +Fixes [AB#633226](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/633226) + From 4dfa1d4a851ddbbdcfadbe6283f943e282c638ca Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Thu, 28 May 2026 14:01:57 +0200 Subject: [PATCH 02/14] Upload new dataset --- dataset/bcbench.jsonl | 9 +++++--- .../microsoft__BCApps-7414/README.md | 19 +++++++++++++++ .../microsoft__BCApps-7831/README.md | 20 ++++++++++++++++ .../microsoft__BCApps-8251/README.md | 23 +++++++++++++++++++ 4 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 dataset/problemstatement/microsoft__BCApps-7414/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-7831/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8251/README.md diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index 04fef2cd0..001c5febb 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -99,6 +99,9 @@ {"metadata": {"area": "inventory", "image_count": 0}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-178045", "base_commit": "22d8978231eb8792d03f150d61431d485d3c92a9", "created_at": "2024-03-11", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137404, "functionName": ["ConsumptionIsPostedForMultipleILEsOfSameLotNo"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al\nindex 9467380d9f9b..e1036e0420d9 100644\n--- a/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al\n@@ -47,6 +47,7 @@ codeunit 137404 \"SCM Manufacturing\"\n Capacity2: Decimal;\n GLB_ItemTrackingQty: Integer;\n GLB_SerialNo: Code[50];\n+ ItemTrackingMode: Option \" \",\"Assign Lot No.\",\"Select Entries\",\"Update Quantity\",\"Manual Lot No.\"; \n DocumentNoDoesNotExistErr: Label 'Document No. %1 does not exist.', Comment = '%1: Document number (Code)';\n ExpectedQuantityErr: Label 'Quantity must be %1.', Comment = '%1: Quantity (decimal value)';\n ModifyRtngErr: Label 'You cannot modify Routing No. %1 because there is at least one %2 associated with it.';\n@@ -80,6 +81,7 @@ codeunit 137404 \"SCM Manufacturing\"\n DidntExpectWhsePickMsg: Label 'Did not expect a Warehouse Pick Request associated with the Production Order Component Line, since the line doesn''t have a postitive remaining quantity';\n ProdOrderNoHandlerErr: Label 'Prod. Order No. must be %1, actual value is %2.', Comment = '%1: Expected Prod. Order No. Value; %2: Actual Prod. Order No. Value.';\n ProdOrderStatusHandlerErr: Label 'Prod. Order Status must be %1, actual value is %2.', Comment = '%1: Expected Prod. Order Status Value; %2: Actual Prod. Order Status Value.';\n+ ItemLedgerEntryMustBeFoundErr: Label 'Item Ledger Entry must be found.';\n \n [Test]\n [HandlerFunctions('ConfirmHandlerTrue,OutputJournalItemtrackingPageHandler,MessageHandler')]\n@@ -4149,6 +4151,104 @@ codeunit 137404 \"SCM Manufacturing\"\n LibraryInventory.PostItemJournalLine(ItemJournalBatch.\"Journal Template Name\", ItemJournalBatch.Name);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('ItemTrackingAssignLotNoPageHandler,ProductionJournalPageHandlerOnlyConsumption,ConfirmHandlerTrue,MessageHandler')]\n+ procedure ConsumptionIsPostedForMultipleILEsOfSameLotNo()\n+ var\n+ CompItem, ProdItem : Record Item;\n+ Location: Record Location;\n+ UnitOfMeasure: Record \"Unit of Measure\";\n+ ItemUnitOfMeasure: Record \"Item Unit of Measure\";\n+ ItemTrackingCode: Record \"Item Tracking Code\";\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ ProductionOrder: Record \"Production Order\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ LotNo: Code[10];\n+ Quantity: Decimal;\n+ ReleasedProdOrder: TestPage \"Released Production Order\";\n+ begin\n+ // [SCENARIO 501830] Consumption is posted against multiple Item Ledger Entries of same Lot No. when you post Production Journal from a Released Production Order.\n+ Initialize();\n+\n+ // [GIVEN] Create Item Tracking Code.\n+ LibraryItemTracking.CreateItemTrackingCode(ItemTrackingCode, false, true);\n+\n+ // [GIVEN] Create Unit of Measure.\n+ LibraryInventory.CreateUnitOfMeasureCode(UnitOfMeasure);\n+\n+ // [GIVEN] Create Component Item with Unit of Measure.\n+ CreateItemWithUOM(CompItem, UnitOfMeasure, ItemUnitOfMeasure);\n+ CompItem.Validate(\"Replenishment System\", CompItem.\"Replenishment System\"::Purchase);\n+ CompItem.Validate(Reserve, CompItem.Reserve::Always);\n+ CompItem.Validate(\"Flushing Method\", CompItem.\"Flushing Method\"::Manual);\n+ CompItem.Validate(\"Item Tracking Code\", ItemTrackingCode.Code);\n+ CompItem.Modify(true);\n+\n+ // [GIVEN] Create Location with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+\n+ // [GIVEN] Create Production Item with Unit of Measure.\n+ CreateItemWithUOM(ProdItem, UnitOfMeasure, ItemUnitOfMeasure);\n+\n+ // [GIVEN] Generate and save Lot No. and Quantity in two different Variable.\n+ LotNo := Format(LibraryRandom.RandText(4));\n+ Quantity := LibraryRandom.RandIntInRange(35, 35);\n+\n+ // [GIVEN] Create and Post three Item Journal Lines with same Lot No.\n+ CreateAndPostItemJournalLineWithLotNo(CompItem.\"No.\", LibraryRandom.RandIntInRange(5, 5), LotNo, '', Location.Code, true);\n+ CreateAndPostItemJournalLineWithLotNo(CompItem.\"No.\", LibraryRandom.RandIntInRange(10, 10), LotNo, '', Location.Code, true);\n+ CreateAndPostItemJournalLineWithLotNo(CompItem.\"No.\", LibraryRandom.RandIntInRange(20, 20), LotNo, '', Location.Code, true);\n+\n+ // [GIVEN] Create a production BOM for the Production Item.\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ItemUnitOfMeasure.Code);\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader,\n+ ProductionBOMLine,\n+ '',\n+ ProductionBOMLine.Type::Item,\n+ CompItem.\"No.\",\n+ LibraryRandom.RandIntInRange(1, 1));\n+\n+ // [GIVEN] Validate Unit of Measure in Production BOM.\n+ ProductionBOMLine.Validate(\"Unit of Measure Code\", ItemUnitOfMeasure.Code);\n+ ProductionBOMLine.Modify(true);\n+\n+ // [GIVEN] Change Status of Production BOM.\n+ LibraryManufacturing.UpdateProductionBOMStatus(ProductionBOMHeader, ProductionBOMHeader.Status::Certified);\n+\n+ // [GIVEN] Validate Replenishment System and Production BOM No. in Production Item.\n+ ProdItem.Validate(\"Replenishment System\", ProdItem.\"Replenishment System\"::\"Prod. Order\");\n+ ProdItem.Validate(\"Production BOM No.\", ProductionBOMHeader.\"No.\");\n+ ProdItem.Modify(true);\n+\n+ // [GIVEN] Create and Refresh Production Order.\n+ CreateAndRefreshProdOrder(\n+ ProductionOrder,\n+ ProductionOrder.Status::Released,\n+ ProdItem.\"No.\",\n+ Quantity,\n+ Location.Code,\n+ '');\n+\n+ // [GIVEN] Open Released Production Order page and run Production Journal action.\n+ ReleasedProdOrder.OpenEdit();\n+ ReleasedProdOrder.GoToRecord(ProductionOrder);\n+ LibraryVariableStorage.Enqueue(Quantity);\n+ LibraryVariableStorage.Enqueue(ItemTrackingMode::\"Assign Lot No.\");\n+ LibraryVariableStorage.Enqueue(LotNo);\n+ LibraryVariableStorage.Enqueue(Quantity);\n+ ReleasedProdOrder.ProdOrderLines.ProductionJournal.Invoke();\n+\n+ // [WHEN] Find Item Ledger Entry.\n+ ItemLedgerEntry.SetRange(\"Item No.\", CompItem.\"No.\");\n+ ItemLedgerEntry.SetRange(Quantity, -Quantity);\n+\n+ // [VERIFY] Item Ledger Entry is found.\n+ Assert.IsFalse(ItemLedgerEntry.IsEmpty(), ItemLedgerEntryMustBeFoundErr);\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -6772,6 +6872,39 @@ codeunit 137404 \"SCM Manufacturing\"\n ReservationPage.OK().Invoke();\n end;\n \n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure ItemTrackingAssignLotNoPageHandler(var ItemTrackingLines: TestPage \"Item Tracking Lines\")\n+ var\n+ DequeueVariable: Variant;\n+ begin\n+ LibraryVariableStorage.Dequeue(DequeueVariable);\n+ ItemTrackingMode := DequeueVariable;\n+ case ItemTrackingMode of\n+ ItemTrackingMode::\"Assign Lot No.\":\n+ begin\n+ ItemTrackingLines.\"Lot No.\".SetValue(LibraryVariableStorage.DequeueText());\n+ LibraryVariableStorage.Dequeue(DequeueVariable);\n+ ItemTrackingLines.\"Quantity (Base)\".SetValue(DequeueVariable);\n+ end;\n+ end;\n+ ItemTrackingLines.OK().Invoke();\n+ end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure ProductionJournalPageHandlerOnlyConsumption(var ProductionJournal: TestPage \"Production Journal\")\n+ var\n+ EntryType: Enum \"Item Ledger Entry Type\";\n+ begin\n+ Assert.IsTrue(ProductionJournal.FindFirstField(ProductionJournal.\"Entry Type\", EntryType::Output), '');\n+ ProductionJournal.\"Output Quantity\".SetValue(0);\n+ Assert.IsTrue(ProductionJournal.FindFirstField(ProductionJournal.\"Entry Type\", EntryType::Consumption), '');\n+ ProductionJournal.Quantity.SetValue(LibraryVariableStorage.DequeueDecimal());\n+ ProductionJournal.ItemTrackingLines.Invoke();\n+ ProductionJournal.Post.Invoke();\n+ end;\n+\n [PageHandler]\n procedure BOMStructurePageHandler(var BOMStructure: TestPage \"BOM Structure\")\n begin\n@@ -6840,5 +6973,74 @@ codeunit 137404 \"SCM Manufacturing\"\n DT2Time(ExpStartDateTime), DT2Time(ProdOrderLine.\"Starting Date-Time\"), StrSubstNo(WrongDateTimeErr, ProdOrderLine.FieldCaption(\"Starting Time\")));\n until ProdOrderLine.Next() = 0;\n end;\n+\n+ local procedure CreateItemWithUOM(\n+ var Item: Record Item;\n+ var UnitOfMeasure: Record \"Unit of Measure\";\n+ var ItemUnitOfMeasure: Record \"Item Unit of Measure\")\n+ begin\n+ LibraryInventory.CreateItem(Item);\n+\n+ LibraryInventory.CreateItemUnitOfMeasure(\n+ ItemUnitOfMeasure,\n+ Item.\"No.\",\n+ UnitOfMeasure.Code,\n+ LibraryRandom.RandInt(0));\n+\n+ Item.Validate(\"Base Unit of Measure\", UnitOfMeasure.Code);\n+ Item.Modify(true);\n+ end;\n+\n+ local procedure CreateAndPostItemJournalLineWithLotNo(\n+ ItemNo: Code[20];\n+ Quantity: Decimal;\n+ LotNo: Code[50];\n+ BinCode: Code[20];\n+ LocationCode: Code[10];\n+ Tracking: Boolean)\n+ var\n+ ItemJournalLine: Record \"Item Journal Line\";\n+ begin\n+ CreateItemJournalLine(ItemJournalLine, ItemNo, Quantity, BinCode, LocationCode);\n+ if Tracking then begin\n+ LibraryVariableStorage.Enqueue(ItemTrackingMode::\"Assign Lot No.\");\n+ LibraryVariableStorage.Enqueue(LotNo);\n+ LibraryVariableStorage.Enqueue(Quantity);\n+ ItemJournalLine.OpenItemTrackingLines(false);\n+ end;\n+ LibraryInventory.PostItemJournalLine(ItemJournalLine.\"Journal Template Name\", ItemJournalLine.\"Journal Batch Name\");\n+ end;\n+\n+ local procedure CreateItemJournalLine(var ItemJournalLine: Record \"Item Journal Line\"; ItemNo: Code[20]; Quantity: Decimal; BinCode: Code[20]; LocationCode: Code[10])\n+ var\n+ ItemJournalTemplate: Record \"Item Journal Template\";\n+ ItemJournalBatch: Record \"Item Journal Batch\";\n+ begin\n+ LibraryInventory.ClearItemJournal(ItemJournalTemplate, ItemJournalBatch);\n+ LibraryInventory.CreateItemJournalTemplate(ItemJournalTemplate);\n+ LibraryInventory.CreateItemJournalBatch(ItemJournalBatch, ItemJournalTemplate.Name);\n+ LibraryInventory.CreateItemJournalLine(\n+ ItemJournalLine,\n+ ItemJournalBatch.\"Journal Template Name\",\n+ ItemJournalBatch.Name,\n+ ItemJournalLine.\"Entry Type\"::\"Positive Adjmt.\",\n+ ItemNo,\n+ Quantity);\n+\n+ ItemJournalLine.Validate(\"Unit Cost\", LibraryRandom.RandDec(10, 2));\n+ ItemJournalLine.Validate(\"Location Code\", LocationCode);\n+ ItemJournalLine.Validate(\"Bin Code\", BinCode);\n+ ItemJournalLine.Modify(true);\n+ end;\n+\n+ local procedure CreateAndRefreshProdOrder(var ProductionOrder: Record \"Production Order\"; Status: Enum \"Production Order Status\"; SourceNo: Code[20]; Quantity: Decimal; LocationCode: Code[10]; BinCode: Code[20])\n+ begin\n+ LibraryManufacturing.CreateProductionOrder(ProductionOrder, Status, ProductionOrder.\"Source Type\"::Item, SourceNo, Quantity);\n+ ProductionOrder.Validate(\"Location Code\", LocationCode);\n+ ProductionOrder.Validate(\"Bin Code\", BinCode);\n+ ProductionOrder.Modify(true);\n+\n+ LibraryManufacturing.RefreshProdOrder(ProductionOrder, false, true, true, true, false);\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al b/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al\nindex 7e739c297201..ffe0b880ce8d 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al\n@@ -1946,8 +1946,11 @@ codeunit 22 \"Item Jnl.-Post Line\"\n Abs(ItemLedgEntry.\"Remaining Quantity\" - ItemLedgEntry.\"Reserved Quantity\")\n then\n AppliedQty := ItemLedgEntry.\"Remaining Quantity\" - ItemLedgEntry.\"Reserved Quantity\"\n- else\n+ else begin\n AppliedQty := -(OldItemLedgEntry.\"Remaining Quantity\" - OldItemLedgEntry.\"Reserved Quantity\");\n+ if AppliedQty = 0 then\n+ AppliedQty := UpdateAppliedQtyIfConsumptionEntry(ItemLedgEntry, OldItemLedgEntry);\n+ end;\n \n OnApplyItemLedgEntryOnAfterCalcAppliedQty(OldItemLedgEntry, ItemLedgEntry, AppliedQty);\n \n@@ -5908,6 +5911,17 @@ codeunit 22 \"Item Jnl.-Post Line\"\n (ItemJournalLine.\"Applies-to Entry\" <> 0)));\n end;\n \n+ local procedure UpdateAppliedQtyIfConsumptionEntry(ItemLedgerEntry: Record \"Item Ledger Entry\"; OldItemLedgerEntry: Record \"Item Ledger Entry\"): Decimal\n+ begin\n+ if ItemLedgerEntry.\"Entry Type\" <> ItemLedgerEntry.\"Entry Type\"::Consumption then\n+ exit(0);\n+\n+ if (ItemLedgerEntry.\"Remaining Quantity\" + OldItemLedgerEntry.\"Remaining Quantity\") > 0 then\n+ exit(0);\n+\n+ exit(-Abs(OldItemLedgerEntry.\"Reserved Quantity\"));\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnBeforeAllowProdApplication(OldItemLedgerEntry: Record \"Item Ledger Entry\"; ItemLedgerEntry: Record \"Item Ledger Entry\"; var AllowApplication: Boolean)\n begin\n"} {"metadata": {"area": "inventory", "image_count": 7}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-176082", "base_commit": "cb30d50fe1ed2c716c6349370fdc31c6bd0ce956", "created_at": "2024-02-23", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137038, "functionName": ["GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\nindex e0b3ba5f0bf7..ffa98cfbb351 100644\n--- a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n@@ -48,6 +48,7 @@\n UndoneTransLineQtyErr: Label 'Expected Quantity to be 0 after Transfer Shipment was undone';\n DerivedTransLineErr: Label 'Expected no Derived Transfer Line i.e. line with \"Derived From Line No.\" equal to original transfer line.';\n IncorrectSNUndoneErr: Label 'The Serial No. of the item on the transfer shipment line that was undone was different from the SN on the corresponding transfer line.';\n+ ApplToItemEntryErr: Label '%1 must be %2 in %3.', Comment = '%1 is Appl-to Item Entry, %2 is Item Ledger Entry No. and %3 is Transfer Line';\n \n [Test]\n [HandlerFunctions('MessageHandler')]\n@@ -3655,6 +3656,99 @@\n ItemLedgerEntry.TestField(\"Cost Amount (Actual)\", NewCost);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('PostedPurchaseReceiptsModalPageHandler,PostedPurchRcptLinesModalPageHandler')]\n+ procedure GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines()\n+ var\n+ Item: Record Item;\n+ Vendor: Record Vendor;\n+ Location: Record Location;\n+ Location2: Record Location;\n+ Location3: Record Location;\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseHeader2: Record \"Purchase Header\";\n+ PurchaseHeader3: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ PurchaseLine2: Record \"Purchase Line\";\n+ PurchaseLine3: Record \"Purchase Line\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ TransferHeader: Record \"Transfer Header\";\n+ TransferLine: Record \"Transfer Line\";\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ ItemLedgerEntryNo: Integer;\n+ PurchaseReceiptNo: Code[20];\n+ TransferOrder: TestPage \"Transfer Order\";\n+ begin\n+ // [SCENARIO 500597] Get Receipt Lines action on Transfer Order shows list of Posted Purchase Receipts having Transfer-from Code in Location Code of Purch Rcpt Lines and after selecting it populates Appl-to Item Entry field in Transfer Lines.\n+ Initialize();\n+\n+ // [GIVEN] Create an Item and Validate Costing Method.\n+ LibraryInventory.CreateItem(Item);\n+ Item.Validate(\"Costing Method\", Item.\"Costing Method\"::FIFO);\n+ Item.Modify(true);\n+\n+ // [GIVEN] Create two Locations with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location2);\n+\n+ // [GIVEN] Create another Location with Inventory Posting Setup \n+ // And Validate Use As In-Transit.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location3);\n+ Location3.Validate(\"Use As In-Transit\", true);\n+ Location3.Modify(true);\n+\n+ // [GIVEN] Create a Vendor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+\n+ // [GIVEN] Create and Post Purchase Receipt with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader, PurchaseLine, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 2 with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader2, PurchaseLine2, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 3 with Location Code on Line.\n+ PurchaseReceiptNo := CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ PurchaseHeader3,\n+ PurchaseLine3,\n+ Vendor,\n+ Item,\n+ Location);\n+\n+ // [GIVEN] Find and save Item Ledger Entry No. in a Variable.\n+ ItemLedgerEntry.SetRange(\"Document No.\", PurchaseReceiptNo);\n+ ItemLedgerEntry.FindFirst();\n+ ItemLedgerEntryNo := ItemLedgerEntry.\"Entry No.\";\n+\n+ // [GIVEN] Find Purch. Rcpt Line.\n+ FindRandomReceiptLine(PurchaseReceiptNo, PurchRcptLine);\n+\n+ // [GIVEN] Create Transfer Header.\n+ LibraryInventory.CreateTransferHeader(TransferHeader, Location.Code, Location2.Code, Location3.Code);\n+\n+ // [GIVEN] Open Transfer Order page and run Get Receipt Line action.\n+ TransferOrder.OpenEdit();\n+ TransferOrder.GoToRecord(TransferHeader);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchRcptLine.\"No.\");\n+ TransferOrder.GetReceiptLines.Invoke();\n+\n+ // [WHEN] Find Transfer Line.\n+ TransferLine.SetRange(\"Document No.\", TransferHeader.\"No.\");\n+ TransferLine.FindFirst();\n+\n+ // [VERIFY] Appl-to Item Entry and Item Ledger Entry No. are same.\n+ Assert.AreEqual(\n+ ItemLedgerEntryNo,\n+ TransferLine.\"Appl.-to Item Entry\",\n+ StrSubstNo(\n+ ApplToItemEntryErr,\n+ TransferLine.FieldCaption(\"Appl.-to Item Entry\"),\n+ ItemLedgerEntryNo,\n+ TransferLine.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -5168,6 +5262,52 @@\n Assert.AreEqual(LineCount, TransferReceiptLine.Count(), '');\n end;\n \n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchHeader(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location)\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ PurchaseHeader.Validate(\"Location Code\", Location.Code);\n+ PurchaseHeader.Modify(true);\n+\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+ end;\n+\n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location): Code[20]\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Location Code\", Location.Code);\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ exit(LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false));\n+ end;\n+\n [MessageHandler]\n [Scope('OnPrem')]\n procedure MessageHandler(Message: Text[1024])\n@@ -5394,5 +5534,19 @@\n // 0 = Item.Type::Inventory\n Assert.AreEqual('0', ItemList.Filter.GetFilter(\"Type\"), 'Item List contains non-inventory items.');\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure PostedPurchRcptLinesModalPageHandler(var PostedPurchaseReceiptLines: Page \"Posted Purchase Receipt Lines\"; var Response: Action)\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ begin\n+ PurchRcptLine.SetRange(\"Document No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.SetRange(\"No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.FindFirst();\n+ PostedPurchaseReceiptLines.SetRecord(PurchRcptLine);\n+\n+ Response := ACTION::LookupOK;\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\nindex 5fe44b4568d1..c16ab8669925 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n@@ -1304,7 +1304,7 @@ table 5740 \"Transfer Header\"\n TempPurchRcptHeader: Record \"Purch. Rcpt. Header\" temporary;\n PostedPurchaseReceipts: Page \"Posted Purchase Receipts\";\n begin\n- PurchRcptHeader.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ FindPurchRcptHeader(PurchRcptHeader);\n PostedPurchaseReceipts.SetTableView(PurchRcptHeader);\n PostedPurchaseReceipts.LookupMode := true;\n if PostedPurchaseReceipts.RunModal() = ACTION::LookupOK then begin\n@@ -1376,6 +1376,8 @@ table 5740 \"Transfer Header\"\n PurchRcptLine.FilterPstdDocLnItemLedgEntries(ItemLedgerEntry);\n ItemTrackingDocMgt.CopyItemLedgerEntriesToTemp(TempItemLedgerEntry, ItemLedgerEntry);\n ItemTrackingMgt.CopyItemLedgEntryTrkgToTransferLine(TempItemLedgerEntry, TransferLine);\n+ TransferLine.\"Appl.-to Item Entry\" := ItemLedgerEntry.\"Entry No.\";\n+ TransferLine.Modify(true);\n \n OnAfterAddTransferLineFromReceiptLine(TransferLine, PurchRcptLine, TempItemLedgerEntry, Rec);\n end;\n@@ -1546,6 +1548,31 @@ table 5740 \"Transfer Header\"\n end;\n end;\n \n+ local procedure FindPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\")\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ DocumentNo: Code[20];\n+ begin\n+ PurchRcptLine.SetLoadFields(\"Document No.\", \"Location Code\");\n+ PurchRcptLine.SetCurrentKey(\"Document No.\");\n+ PurchRcptLine.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ if PurchRcptLine.FindSet() then\n+ repeat\n+ GetPurchRcptHeader(PurchRcptHeader, PurchRcptLine, DocumentNo);\n+ until PurchRcptLine.Next() = 0;\n+ PurchRcptHeader.MarkedOnly(true);\n+ end;\n+\n+ local procedure GetPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var DocumentNo: Code[20])\n+ begin\n+ if PurchRcptLine.\"Document No.\" = DocumentNo then\n+ exit;\n+\n+ PurchRcptHeader.Get(PurchRcptLine.\"Document No.\");\n+ PurchRcptHeader.Mark(true);\n+ DocumentNo := PurchRcptLine.\"Document No.\";\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnAddTransferLineFromReceiptLineOnBeforeTransferLineInsert(var TransferLine: Record \"Transfer Line\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var TransferHeader: Record \"Transfer Header\")\n begin\n"} {"metadata": {"area": "crm", "image_count": 8}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-174087", "base_commit": "74a0b7c175da3f9a272745bd34453a4712b73e7b", "created_at": "2024-02-02", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\Marketing"], "FAIL_TO_PASS": [{"codeunitID": 136208, "functionName": ["PopulateEvaluationFieldInInteractionLogEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\nindex 4c4c73700d2a..59fff6e2be93 100644\n--- a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n+++ b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n@@ -45,6 +45,7 @@ codeunit 136208 \"Marketing Interaction\"\n LoggedSegemntEntriesCreateMsg: Label 'Logged Segment entry was created';\n AttachmentFileShouldNotBeBlankErr: Label 'Attachment File should not be blank.';\n TxtFileExt: Label 'txt';\n+ EvaluationErr: Label '%1 must be %2 in %3', Comment = '%1 = Evaluation, %2 = Positive, %3 = Interaction Log Entry';\n \n [Test]\n [Scope('OnPrem')]\n@@ -2998,6 +2999,50 @@ codeunit 136208 \"Marketing Interaction\"\n VerifyAttachmentFileIsNotBlankOnInteractionLogEntry(Contact.\"No.\");\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('CreateInteractionFromContactPageHandler')]\n+ procedure PopulateEvaluationFieldInInteractionLogEntry()\n+ var\n+ Contact: Record Contact;\n+ InteractionTemplate: Record \"Interaction Template\";\n+ InteractionLogEntry: Record \"Interaction Log Entry\";\n+ ContactCard: TestPage \"Contact Card\";\n+ InteractionEvaluation: Enum \"Interaction Evaluation\";\n+ begin\n+ // [SCENARIO 498395] When stan creates an Interaction using Create Interaction action from Contact, Evaluation field should be populated in Interaction Log Entry.\n+ Initialize();\n+\n+ // [GIVEN] Create a Contact.\n+ LibraryMarketing.CreateCompanyContact(Contact);\n+\n+ // [GIVEN] Create an Interaction Template and Validate Information Flow.\n+ LibraryMarketing.CreateInteractionTemplate(InteractionTemplate);\n+ InteractionTemplate.Validate(\"Information Flow\", InteractionTemplate.\"Information Flow\"::Outbound);\n+ InteractionTemplate.Modify(true);\n+\n+ // [GIVEN] Open Contact Card and Create Interaction.\n+ ContactCard.OpenEdit();\n+ ContactCard.GoToRecord(Contact);\n+ LibraryVariableStorage.Enqueue(InteractionTemplate.Code);\n+ LibraryVariableStorage.Enqueue(Format(InteractionEvaluation::Positive));\n+ ContactCard.\"Create &Interaction\".Invoke();\n+\n+ // [WHEN] Find Interaction Log Entry.\n+ InteractionLogEntry.SetRange(\"Contact No.\", Contact.\"No.\");\n+ InteractionLogEntry.FindFirst();\n+\n+ // [VERIFY] Interaction Log Entry has Evaluation field populated as Positive.\n+ Assert.AreEqual(\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.Evaluation,\n+ StrSubstNo(\n+ EvaluationErr,\n+ InteractionLogEntry.FieldCaption(Evaluation),\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibrarySales: Codeunit \"Library - Sales\";\n@@ -4309,5 +4354,16 @@ CopyStr(StorageLocation, 1, MaxStrLen(MarketingSetup.\"Attachment Storage Locatio\n CreateInteraction.NextInteraction.Invoke();\n CreateInteraction.Finish.Invoke();\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure CreateInteractionFromContactPageHandler(var CreateInteraction: TestPage \"Create Interaction\")\n+ begin\n+ CreateInteraction.\"Interaction Template Code\".SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.Evaluation.SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.FinishInteraction.Invoke();\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\nindex ff43f4ff6a7b..05a21a6196bf 100644\n--- a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n+++ b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n@@ -694,6 +694,7 @@ page 5077 \"Create Interaction\"\n end;\n Step::\"Step 4\":\n begin\n+ InteractionLogEntry.CopyFromSegment(Rec);\n InteractionLogEntry.Modify();\n CurrPage.Close();\n end;\n"} -{"metadata": {"area": "Peppol", "image_count": 1}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8059", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-08T09:31:42Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\PEPPOL\\App", "src\\Apps\\W1\\PEPPOL\\Test"], "patch": "diff --git a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\nindex 30f5f792bd..c7981a46fa 100644\n--- a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n@@ -798,6 +798,8 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n InvoiceLineNote := DelChr(Format(SalesLine.Type), '<>');\n InvoicedQuantity := Format(SalesLine.Quantity, 0, 9);\n SalesLineLineAmount := SalesLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesLineLineAmount := Round(SalesLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n InvoiceLineExtensionAmount := Format(SalesLineLineAmount, 0, 9);\n LineExtensionAmountCurrencyID := GetSalesDocCurrencyCode(SalesHeader);\n InvoiceLineAccountingCost := '';\n@@ -869,7 +871,10 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n \n InvLnAllowanceChargeIndicator := 'false';\n InvLnAllowanceChargeReason := LineDisAmtTxt;\n- InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ InvLnAllowanceChargeAmount := Format(Round(SalesLine.\"Line Discount Amount\" / (1 + SalesLine.\"VAT %\" / 100), 0.01), 0, 9)\n+ else\n+ InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n InvLnAllowanceChargeAmtCurrID := GetSalesDocCurrencyCode(SalesHeader);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139235, "functionName": ["LineAmountsConsistentWhenPricesInclVATNoDiscount"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\nindex 36931d56ed..cd237011d5 100644\n--- a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n@@ -3349,6 +3349,68 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual('', CustTaxSchemeID, 'Tax Scheme ID should be empty for Tax Category O.');\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ procedure LineAmountsConsistentWhenPricesInclVATNoDiscount()\n+ var\n+ SalesHeader: Record \"Sales Header\";\n+ SalesLine: Record \"Sales Line\";\n+ Customer: Record Customer;\n+ Item: Record Item;\n+ SalesInvoiceHeader: Record \"Sales Invoice Header\";\n+ SalesInvoiceLine: Record \"Sales Invoice Line\";\n+ PEPPOLLineInfoProvider: Interface \"PEPPOL Line Info Provider\";\n+ InvoiceLineID: Text;\n+ InvoiceLineNote: Text;\n+ InvoicedQuantity: Text;\n+ InvoiceLineExtensionAmount: Text;\n+ LineExtensionAmountCurrencyID: Text;\n+ InvoiceLineAccountingCost: Text;\n+ InvoiceLinePriceAmount: Text;\n+ InvLinePriceAmountCurrencyID: Text;\n+ BaseQuantity: Text;\n+ UnitCode: Text;\n+ PriceAmount: Decimal;\n+ LineExtensionAmt: Decimal;\n+ SalesInvoiceNo: Code[20];\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 630795] PEPPOL LineExtensionAmount equals PriceAmount times Quantity when Prices Including VAT is used\n+ Initialize();\n+\n+ // [GIVEN] Customer \"C\" with PEPPOL identifier\n+ LibrarySales.CreateCustomer(Customer);\n+ AddCustPEPPOLIdentifier(Customer.\"No.\");\n+\n+ // [GIVEN] Sales Invoice for \"C\" with \"Prices Including VAT\" = TRUE and Quantity = 7\n+ CreateItemWithPrice(Item, 139);\n+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader.\"Document Type\"::Invoice, Customer.\"No.\");\n+ SalesHeader.Validate(\"Prices Including VAT\", true);\n+ SalesHeader.Modify(true);\n+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item.\"No.\", 7);\n+\n+ // [WHEN] Post the Sales Invoice and retrieve PEPPOL line amounts\n+ SalesInvoiceNo := LibrarySales.PostSalesDocument(SalesHeader, true, true);\n+ SalesInvoiceHeader.Get(SalesInvoiceNo);\n+ SalesHeader.TransferFields(SalesInvoiceHeader);\n+ FindSalesInvoiceLine(SalesInvoiceLine, SalesInvoiceNo);\n+ SalesLine.TransferFields(SalesInvoiceLine);\n+\n+ PEPPOLLineInfoProvider := GetFormat();\n+ PEPPOLLineInfoProvider.GetLineGeneralInfo(\n+ SalesLine, SalesHeader, InvoiceLineID, InvoiceLineNote, InvoicedQuantity,\n+ InvoiceLineExtensionAmount, LineExtensionAmountCurrencyID, InvoiceLineAccountingCost);\n+ PEPPOLLineInfoProvider.GetLinePriceInfo(\n+ SalesLine, SalesHeader, InvoiceLinePriceAmount, InvLinePriceAmountCurrencyID,\n+ BaseQuantity, UnitCode);\n+\n+ // [THEN] LineExtensionAmount equals PriceAmount times Quantity per PEPPOL BIS 3.0\n+ Evaluate(PriceAmount, InvoiceLinePriceAmount, 9);\n+ Evaluate(LineExtensionAmt, InvoiceLineExtensionAmount, 9);\n+ Assert.AreEqual(PriceAmount * SalesInvoiceLine.Quantity, LineExtensionAmt,\n+ 'LineExtensionAmount must equal PriceAmount * Quantity per PEPPOL BIS 3.0');\n+ end;\n+\n var\n local procedure Initialize()\n var\n@@ -3993,6 +4055,8 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual(UnitOfMeasure.\"International Standard Code\", unitCode, '');\n Assert.AreEqual('UNECERec20', unitCodeListID, '');\n SalesInvoiceLineLineAmount := SalesInvoiceLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesInvoiceLineLineAmount := Round(SalesInvoiceLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n Assert.AreEqual(Format(SalesInvoiceLineLineAmount, 0, 9), InvoiceLineExtensionAmount, '');\n Assert.AreEqual(SalesHeader.\"Currency Code\", LineExtensionAmountCurrencyID, '');\n Assert.AreEqual('', InvoiceLineAccountingCost, '');\n"} -{"metadata": {"area": "Manufacturing", "image_count": 0}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "bb325c49266ab81baa1c3c2a1154c182019929d4", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7953", "base_commit": "907fd4ab20c5a3156d2d3dac5787bce3a272bb57", "created_at": "2026-05-04T20:30:22Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\EDocument\\App", "src\\Apps\\W1\\EDocument\\Test"], "patch": "diff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al\nnew file mode 100644\nindex 0000000000..45c2b7121f\n--- /dev/null\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al\n@@ -0,0 +1,20 @@\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+namespace Microsoft.eServices.EDocument;\n+\n+enum 6162 \"E-Doc. Purch.Def. Posting Date\"\n+{\n+ Extensible = false;\n+ Caption = 'Purchase Invoice Posting Date (E-Docs)';\n+\n+ value(0; \"Work Date\")\n+ {\n+ Caption = 'Work Date';\n+ }\n+ value(1; \"Document Date\")\n+ {\n+ Caption = 'Document Date';\n+ }\n+}\ndiff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\nindex 08b2a7a822..556fbad792 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n@@ -21,6 +21,11 @@ pageextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n ApplicationArea = All;\n ToolTip = 'Specifies whether Copilot E-Document line matchings are learned by default (Item References and Text To Account Mappings). This can be overwritten on the matching page.';\n }\n+ field(\"E-Doc. Def. Posting Date\"; Rec.\"E-Doc. Def. Posting Date\")\n+ {\n+ ApplicationArea = All;\n+ ToolTip = 'Specifies how the posting date is set on purchase invoices created from e-documents. Work Date uses the current work date. Document Date uses the document date from the e-document.';\n+ }\n }\n }\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\nindex 24013c63c5..2dc0c9ccec 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n@@ -21,5 +21,10 @@ tableextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n Caption = 'E-Document Learn Copilot Matchings';\n DataClassification = SystemMetadata;\n }\n+ field(6102; \"E-Doc. Def. Posting Date\"; Enum \"E-Doc. Purch.Def. Posting Date\")\n+ {\n+ Caption = 'E-Document Default Posting Date';\n+ DataClassification = CustomerContent;\n+ }\n }\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\nindex b97c6db072..14907342c4 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\n@@ -100,6 +100,7 @@ codeunit 6404 \"E-Doc. Create Purch. Cr. Memo\" implements IEDocumentFinishDraft,\n if EDocumentPurchaseHeader.\"Purchase Order No.\" <> '' then\n PurchaseHeader.\"Vendor Order No.\" := CopyStr(EDocumentPurchaseHeader.\"Purchase Order No.\", 1, MaxStrLen(PurchaseHeader.\"Vendor Order No.\"));\n PurchaseHeader.Insert(true);\n+ EDocPurchaseDocumentHelper.ApplyDefaultPostingDateFromSetup(PurchaseHeader, EDocumentPurchaseHeader);\n PurchaseHeader.Modify();\n \n GLSetup.GetRecordOnce();\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\nindex 0f2b7905d4..f79acb69fe 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n@@ -129,6 +129,7 @@ codeunit 6117 \"E-Doc. Create Purchase Invoice\" implements IEDocumentFinishDraft,\n PurchaseHeader.\"Vendor Order No.\" := CopyStr(EDocumentPurchaseHeader.\"Purchase Order No.\", 1, MaxStrLen(PurchaseHeader.\"Vendor Order No.\"));\n PurchaseHeader.Insert(true);\n \n+ EDocPurchaseDocumentHelper.ApplyDefaultPostingDateFromSetup(PurchaseHeader, EDocumentPurchaseHeader);\n PurchaseHeader.\"Invoice Received Date\" := PurchaseHeader.\"Document Date\";\n PurchaseHeader.Modify();\n \ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\nindex dd97e61275..d21ea96b71 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n@@ -11,6 +11,7 @@ using Microsoft.Finance.Dimension;\n using Microsoft.Foundation.Attachment;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.Posting;\n+using Microsoft.Purchases.Setup;\n \n /// \n /// Shared logic for creating BC purchase documents (invoices and credit memos) from e-document draft data.\n@@ -137,4 +138,16 @@ codeunit 6402 \"E-Doc. Purch. Doc. Helper\"\n Clear(PurchaseHeader.\"E-Document Link\");\n PurchaseHeader.Modify();\n end;\n+\n+ procedure ApplyDefaultPostingDateFromSetup(var PurchaseHeader: Record \"Purchase Header\"; EDocumentPurchaseHeader: Record \"E-Document Purchase Header\")\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ begin\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ if (PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" <> PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\"::\"Document Date\") then\n+ exit;\n+ if EDocumentPurchaseHeader.\"Document Date\" = 0D then\n+ exit;\n+ PurchaseHeader.Validate(\"Posting Date\", EDocumentPurchaseHeader.\"Document Date\");\n+ end;\n }\n", "FAIL_TO_PASS": [{"codeunitID": 139883, "functionName": ["InvoicePostingDateUsesDocumentDateWhenSettingIsDocumentDate", "InvoicePostingDateDefaultsToWorkDateWhenSettingIsWorkDate", "CreditMemoPostingDateDefaultsToWorkDateWhenSettingIsWorkDate", "CreditMemoPostingDateUsesDocumentDateWhenSettingIsDocumentDate"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml\nnew file mode 100644\nindex 0000000000..52cd211620\n--- /dev/null\n+++ b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml\n@@ -0,0 +1,200 @@\n+\n+\n+\turn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0\n+\turn:fdc:peppol.eu:2017:poacc:billing:01:1.0\n+\t103033\n+\t2026-01-22\n+\t2026-02-22\n+\t380\n+\t1\n+\t\n+\t\t2\n+\t\n+\t\n+\t\t103033\n+\t\n+\t\n+\t\t103033\n+\t\t\n+\t\t\n+\t\t\t\n+\t\t\t\t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MzAxMjE5MDBaKS9Nb2REYXRlKEQ6MjAyMjA2MTUxMzEzMDBaKT4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAzIDAgUi9MYW5nKGVuLVVTKS9NZXRhZGF0YSA0IDAgUj4+DQplbmRvYmoNCjMgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWzUgMCBSXT4+DQplbmRvYmoNCjQgMCBvYmoNCjw8L1R5cGUvTWV0YWRhdGEvU3VidHlwZS9YTUwvTGVuZ3RoIDIxIDAgUj4+c3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJQREZOZXQiPgo8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgo8eG1wOkNyZWF0ZURhdGU+MjAxNy0wMS0zMFQxMjoxOTowMFo8L3htcDpDcmVhdGVEYXRlPgo8eG1wOk1vZGlmeURhdGU+MjAyMi0wNi0xNVQxMzoxMzowMFo8L3htcDpNb2RpZnlEYXRlPgo8eG1wOkNyZWF0b3JUb29sPk1pY3Jvc29mdCBPZmZpY2UgV29yZDwveG1wOkNyZWF0b3JUb29sPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KPGRjOmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KPGRjOnRpdGxlPgo8cmRmOkFsdD4KPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5TYWxlcyAtIEludm9pY2U8L3JkZjpsaT4KPC9yZGY6QWx0Pgo8L2RjOnRpdGxlPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6cGRmPSJodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8xLjMvIj4KPHBkZjpQcm9kdWNlcj5Bc3Bvc2UuV29yZHMgZm9yIC5ORVQgMjMuOS4wPC9wZGY6UHJvZHVjZXI+CjwvcmRmOkRlc2NyaXB0aW9uPgo8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJ3Ij8+Cg0KZW5kc3RyZWFtDQplbmRvYmoNCjIxIDAgb2JqDQo4NTQNCmVuZG9iag0KMTYgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCRytTZWdvZVVJLUJvbGQvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nL0ZpcnN0Q2hhciAzMi9MYXN0Q2hhciAxNjMvV2lkdGhzIDE3IDAgUi9Gb250RGVzY3JpcHRvciAxOCAwIFI+Pg0KZW5kb2JqDQoxNyAwIG9iag0KWzI3NiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMjcxIDAgMjcxIDAgNTc1IDU3NSA1NzUgMCA1NzUgNTc1IDAgNTc1IDAgNTc1IDAgMCAwIDAgMCAwIDAgNzAzIDY0MSA2MjQgMCAwIDAgNzExIDAgMCAwIDY0OSA1MTEgOTU3IDAgMCA2MTQgMCAwIDU2MSA1ODYgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNTM4IDAgMCA2MTkgNTQxIDAgNjE5IDYwMiAyODQgMCA1NTkgMjg0IDkxNiA2MDUgNjExIDYyMCA2MTkgMzk4IDAgMzg5IDYwNSAwIDAgMCA1MzggMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDU3NV0NCmVuZG9iag0KMTggMCBvYmoNCjw8L1R5cGUvRm9udERlc2NyaXB0b3IvRm9udE5hbWUvRkFBQUJHK1NlZ29lVUktQm9sZC9TdGVtViA4MC9EZXNjZW50IC0yNTEvQXNjZW50IDEwNzkvQ2FwSGVpZ2h0IDcwMC9GbGFncyAyNjIxNzYvSXRhbGljQW5nbGUgMC9Gb250QkJveFstNTczIC00MzEgMTk5OSAxMjk4XS9Gb250RmlsZTIgMTUgMCBSPj4NCmVuZG9iag0KMTIgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCQytTZWdvZVVJLUxpZ2h0L0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTE4L1dpZHRocyAxMyAwIFIvRm9udERlc2NyaXB0b3IgMTQgMCBSPj4NCmVuZG9iag0KMTMgMCBvYmoNClsyNzQgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDIyMiAwIDIyMiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCA2MjkgNTQ0IDYyMSAwIDAgMCAwIDAgMjI4IDAgMCAwIDAgNzA5IDc2MSAwIDAgNTU1IDQ5NyAwIDY0OCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNDk0IDAgNDQ0IDAgNTA1IDAgNTYwIDUzNSAyMDUgMCAwIDAgODIyIDUzNSA1NjEgMCAwIDMzMCAwIDAgMCA0NTNdDQplbmRvYmoNCjE0IDAgb2JqDQo8PC9UeXBlL0ZvbnREZXNjcmlwdG9yL0ZvbnROYW1lL0ZBQUFCQytTZWdvZVVJLUxpZ2h0L1N0ZW1WIDgwL0Rlc2NlbnQgLTI1MS9Bc2NlbnQgMTA3OS9DYXBIZWlnaHQgNzAwL0ZsYWdzIDMyL0l0YWxpY0FuZ2xlIDAvRm9udEJCb3hbLTU4NyAtMzk2IDE5OTkgMTI5OV0vRm9udEZpbGUyIDExIDAgUj4+DQplbmRvYmoNCjggMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFBSStTZWdvZVVJL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTIxL1dpZHRocyA5IDAgUi9Gb250RGVzY3JpcHRvciAxMCAwIFI+Pg0KZW5kb2JqDQo5IDAgb2JqDQpbMjc0IDAgMCAwIDAgODE4IDAgMCAwIDAgMCA2ODQgMjE3IDQwMCAyMTcgMzkwIDUzOSA1MzkgNTM5IDUzOSA1MzkgNTM5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MODW9nYEFJ/+03vN/EfC/wC1cf8ACIPH+01vN/EfCv7Vx/wiC9HFLTNYMWxuxVMjJqiy2qjoJ5oteR76aBkTnN1AOhLdRqEGNd+9i8S6h9v59vcxrLjbrca2G5UdwtckcdRDV07ZGRP+VjkY5ukjgWlvEd4PFBULn/lQbnWuaon243CsOW0DdXQ0d4jntNby6ahg8MVUL3Ds1L2A9ug7EEart5fvVtaJSx21Elxi1+TqaC62qoY7QAk8ravnHbp7TRr3IOtUvRP1U1kvhQ7LX1jg0u5pzTQN0H5807G6+rVBlPFvLW6qMhkjF0xuzYVBIW/9zervTPAaeOpZbjWvGnoLdfUgnPtB5VeB49U0l33izCpz2ohIe7F7Sx9ttpcO1k1Rzmpmb62GE/1haTjuOWDEbLb8cxay0WPWG1R+DbrPb4GU9NCzUnRkcYDRqSSeHE8TxQc0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIP/2Q0KZW5kc3RyZWFtDQplbmRvYmoNCjIyIDAgb2JqDQoxNTE2OA0KZW5kb2JqDQoxNSAwIG9iag0KPDwvTGVuZ3RoMSAyMyAwIFIvTGVuZ3RoIDI0IDAgUi9GaWx0ZXIvRmxhdGVEZWNvZGU+PnN0cmVhbQ0KeJzsfAl4VFWW8LlvqX1PVVJJBfIqlbAVppJUAokgKcjCEoghCZgCgilIQgKBBBJAVBaHIBpXRFRwaVptRntorWCPHVFbnHZp/XXcp8Vuu22l3RqQ7kb0Q/Jqzr3vVVJhcfz7m+lv5vt4lXffufeee+/Z7jnnPqoAAgBm2AI8VF9eG8hvvDX0Abb8Du/GpSsjnbpb9Q4AMhnvuqXruqWNk9paALjbAQw5LZ3LVs6seX8ZgOkQ1hcta9/Q8tD8f3oMICUdwHWktTnSdB9kcACX4HQwoRUbnBbdp1gvwnpW68ruqx5/0erF+iKs39fesTQC5KHrsf4t1veujFzVyT9t/hAg5x6sS6siK5s/tq57A+v9AGOyOju6umNzYT3AfEqv1LmmuXPFX9J1WD8DIFwCvNDPPQMi6MQ9YhA58ChP/i1o4Rw6kTPqOAE/HH8EcmKH4MhmnEVPSZ1TK0kggTk2IL4jzyVm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\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t103033\n+\t\t\n+\t\t\n+\t\t\t\n+\t\t\t\t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MzAxMjE5MDBaKS9Nb2REYXRlKEQ6MjAyMjA2MTUxMzEzMDBaKT4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAzIDAgUi9MYW5nKGVuLVVTKS9NZXRhZGF0YSA0IDAgUj4+DQplbmRvYmoNCjMgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWzUgMCBSXT4+DQplbmRvYmoNCjQgMCBvYmoNCjw8L1R5cGUvTWV0YWRhdGEvU3VidHlwZS9YTUwvTGVuZ3RoIDIxIDAgUj4+c3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJQREZOZXQiPgo8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgo8eG1wOkNyZWF0ZURhdGU+MjAxNy0wMS0zMFQxMjoxOTowMFo8L3htcDpDcmVhdGVEYXRlPgo8eG1wOk1vZGlmeURhdGU+MjAyMi0wNi0xNVQxMzoxMzowMFo8L3htcDpNb2RpZnlEYXRlPgo8eG1wOkNyZWF0b3JUb29sPk1pY3Jvc29mdCBPZmZpY2UgV29yZDwveG1wOkNyZWF0b3JUb29sPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KPGRjOmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KPGRjOnRpdGxlPgo8cmRmOkFsdD4KPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5TYWxlcyAtIEludm9pY2U8L3JkZjpsaT4KPC9yZGY6QWx0Pgo8L2RjOnRpdGxlPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6cGRmPSJodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8xLjMvIj4KPHBkZjpQcm9kdWNlcj5Bc3Bvc2UuV29yZHMgZm9yIC5ORVQgMjMuOS4wPC9wZGY6UHJvZHVjZXI+CjwvcmRmOkRlc2NyaXB0aW9uPgo8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJ3Ij8+Cg0KZW5kc3RyZWFtDQplbmRvYmoNCjIxIDAgb2JqDQo4NTQNCmVuZG9iag0KMTYgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCRytTZWdvZVVJLUJvbGQvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nL0ZpcnN0Q2hhciAzMi9MYXN0Q2hhciAxNjMvV2lkdGhzIDE3IDAgUi9Gb250RGVzY3JpcHRvciAxOCAwIFI+Pg0KZW5kb2JqDQoxNyAwIG9iag0KWzI3NiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMjcxIDAgMjcxIDAgNTc1IDU3NSA1NzUgMCA1NzUgNTc1IDAgNTc1IDAgNTc1IDAgMCAwIDAgMCAwIDAgNzAzIDY0MSA2MjQgMCAwIDAgNzExIDAgMCAwIDY0OSA1MTEgOTU3IDAgMCA2MTQgMCAwIDU2MSA1ODYgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNTM4IDAgMCA2MTkgNTQxIDAgNjE5IDYwMiAyODQgMCA1NTkgMjg0IDkxNiA2MDUgNjExIDYyMCA2MTkgMzk4IDAgMzg5IDYwNSAwIDAgMCA1MzggMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDU3NV0NCmVuZG9iag0KMTggMCBvYmoNCjw8L1R5cGUvRm9udERlc2NyaXB0b3IvRm9udE5hbWUvRkFBQUJHK1NlZ29lVUktQm9sZC9TdGVtViA4MC9EZXNjZW50IC0yNTEvQXNjZW50IDEwNzkvQ2FwSGVpZ2h0IDcwMC9GbGFncyAyNjIxNzYvSXRhbGljQW5nbGUgMC9Gb250QkJveFstNTczIC00MzEgMTk5OSAxMjk4XS9Gb250RmlsZTIgMTUgMCBSPj4NCmVuZG9iag0KMTIgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCQytTZWdvZVVJLUxpZ2h0L0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTE4L1dpZHRocyAxMyAwIFIvRm9udERlc2NyaXB0b3IgMTQgMCBSPj4NCmVuZG9iag0KMTMgMCBvYmoNClsyNzQgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDIyMiAwIDIyMiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCA2MjkgNTQ0IDYyMSAwIDAgMCAwIDAgMjI4IDAgMCAwIDAgNzA5IDc2MSAwIDAgNTU1IDQ5NyAwIDY0OCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNDk0IDAgNDQ0IDAgNTA1IDAgNTYwIDUzNSAyMDUgMCAwIDAgODIyIDUzNSA1NjEgMCAwIDMzMCAwIDAgMCA0NTNdDQplbmRvYmoNCjE0IDAgb2JqDQo8PC9UeXBlL0ZvbnREZXNjcmlwdG9yL0ZvbnROYW1lL0ZBQUFCQytTZWdvZVVJLUxpZ2h0L1N0ZW1WIDgwL0Rlc2NlbnQgLTI1MS9Bc2NlbnQgMTA3OS9DYXBIZWlnaHQgNzAwL0ZsYWdzIDMyL0l0YWxpY0FuZ2xlIDAvRm9udEJCb3hbLTU4NyAtMzk2IDE5OTkgMTI5OV0vRm9udEZpbGUyIDExIDAgUj4+DQplbmRvYmoNCjggMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFBSStTZWdvZVVJL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTIxL1dpZHRocyA5IDAgUi9Gb250RGVzY3JpcHRvciAxMCAwIFI+Pg0KZW5kb2JqDQo5IDAgb2JqDQpbMjc0IDAgMCAwIDAgODE4IDAgMCAwIDAgMCA2ODQgMjE3IDQwMCAyMTcgMzkwIDUzOSA1MzkgNTM5IDUzOSA1MzkgNTM5IDUzOSA1MzkgNTM5IDUzOSAwIDAgMCAwIDAgMCAwIDY0NSA1NzMgMCA3MDEgNTA2IDQ4OCA2ODYgMCAwIDM1NyA1ODAgNDcxIDg5OCA3NDggMCA1NjAgNzU0IDU5OCA1MzEgNTI0IDY4NyA2MjEgOTM0IDAgMCAwIDAgMCAwIDAgMCAwIDUwOSA1ODggNDYyIDU4OSA1MjMgMCA1ODkgNTY2IDI0MiAwIDQ5NyAyNDIgODYxIDU2NiA1ODYgNTg4IDAgMzQ4IDQyNCAzMzkgNTY2IDAgMCA0NTkgNDg0XQ0KZW5kb2JqDQoxMCAwIG9iag0KPDwvVHlwZS9Gb250RGVzY3JpcHRvci9Gb250TmFtZS9GQUFBQUkrU2Vnb2VVSS9TdGVtViA4MC9EZXNjZW50IC0yNTEvQXNjZW50IDEwNzkvQ2FwSGVpZ2h0IDcwMC9GbGFncyAzMi9JdGFsaWNBbmdsZSAwL0ZvbnRCQm94Wy01NzMgLTQxMSAxOTk5IDEyOThdL0ZvbnRGaWxlMiA3IDAgUj4+DQplbmRvYmoNCjE5IDAgb2JqDQo8PC9UeXBlL1hPYmplY3QvU3VidHlwZS9JbWFnZS9XaWR0aCA2MDAvSGVpZ2h0IDMwMC9Db2xvclNwYWNlL0RldmljZVJHQi9CaXRzUGVyQ29tcG9uZW50IDgvTGVuZ3RoIDIyIDAgUi9GaWx0ZXIvRENURGVjb2RlPj5zdHJlYW0NCv/Y/+AAEEpGSUYAAQEBAAAAAAAA/+4ADkFkb2JlAGQAAAAAAf/bAEMAAgICAgICAgICAgMCAgIDBAMCAgMEBQQEBAQEBQYFBQUFBQUGBgcHCAcHBgkJCgoJCQwMDAwMDAwMDAwMDAwMDP/bAEMBAwMDBQQFCQYGCQ0LCQsNDw4ODg4PDwwMDAwMDw8MDAwMDAwPDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDP/AABEIASwCWAMBEQACEQEDEQH/xAAeAAEAAgICAwEAAAAAAAAAAAAACAkHCgUGAQIEA//EAFMQAAEDAwIDBAQICQoEAgsAAAEAAgMEBQYRByESCDFBEwlRYSJ2gTIjsxS0NzhxQlJiFbUWNleRobHBktPUdRgZ8DOTJHKC0kNTg6OUVWUmRhf/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8Av8QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAJ04ngB2lBg/IeobbPHq+W3OuVReKincWVD7bD40THDgW+K5zGO/wDISEHbsJ3RwzcASMx66c9dCzxJ7VUsMNSxgIBdyHg4DUalpIHegyEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICCPGY9SWE4xX1Frt1PU5NW0rnR1EtIWMpWvbwLRM4nmIPaWtI9aDkMD6g8Lza4QWaSOox68VbuSjp6zkdDM89jI5mHTmPcHBuvYNTwQZ3QYG6jsluGObbTttsr6ee/10NqkqIzo5kMscssoB/ObEWH1FBW3xQcvYb3ccbvFuvtpnNNcLZM2amlBPa08Wu001a4ahw7wSEFvdvq23Cgoq9jDGytp46hsbuJaJGhwB/Bqg4nKsps+G2OtyG+1BgoKFo5gwc0kj3HRkcbdRzOceAGvrJABKCGd26scokrXGxY1a6W3hxDI68z1Ezm68CXRSQtaSO7Q6ekoM27T782vcOrFiudC2xZIWF9NA2QyQVQYOZ/hOIBa5oGpadeHEE8dAkAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgxTvbfK3HtsMquFve+KrfDFSRzs7YxVTMge7UfFIY86H06IKuP50Hs1zmOa9jix7CHMcDoQRxBBQWy7b3mryHA8TvNe8yV1dbYHVkx7XytbyPefW4tJQcLu/gsu4WEV1kpC1t1ppGV1nLzysNRCHAMce7nY9zNT2a6oKwLlbLjZ62ott1oprdX0jyyppKhhZIwj0goO77bbcXrcW/U1voaeVlqilab1d+UiKnh1BcOY8C9w4Nb2k+rUgLU4IYqaGGngYIoKdjY4Y29jWMGjQPwAIIhdW9TVtt+D0bHO+gT1FfNUt/FM0TIGxE+sNkfp8KCEn9aDsmG1VVRZdi9VQvcyshutG6nLOLubxmaDQduvYR3oLeUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEHW8vxqkzDGbzjVc8x093pzD4wHMY5AQ+OQA9pY9odp6kFXeZ7fZVglxnob9bJooY3kU10jY51JOzXQPjl0048OB0I7wEHIYFtflef3Gmp7XbpYbY6Rorr7MwtpoY9fadzHQPdp2NadT6hxAWjWe1UditNsstvYY6G1UsVJSMPE+HCwMbqe86DiUHJIOLuNjst3MZu1noroYhpEaunjnLR6vEa7RB9lLSUlDAyloqaKjpohpHTwMbGxo9TWgAIPoQY83N29oNyMZlsdTN9DrIZBU2m48vMYZ2ggajgS1wJa4a+vtAQQAu2xe6Vpq3UjsVqLg0PLIqygc2eGQdzgWnVoOn44afUgzzst0/wB4tF7ocuziCOjfbHie02IPbLJ444xzTOYS1vIfaa0Enm01000ITJQcTdb/AGKwxslvl6oLNFKdI5K6pip2uPoBlc0FB5tV9sl9ifPZLzQ3mCM8sk1DURVDGn0F0TnAIOVQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQcfdrpRWS13C8XGXwaC108lVVy9pEcTS52g7zoOA70Fbuc78Z3llzqZLdeKvGbKHEUNst8xge1nYDLNHyve4jt48voCD0wjfXPcSuMElZearJLOXNFZa7lK6cuj4A+FLIS+NwHZoeX0tKCyOzXahv1pt16tsvjUF0p46qkkI0JZI0OGo7iNdCO4oOSQEBAQEBAQEBAQdXzXJI8QxS/ZLJEJ/0RSPmigJ0D5fixMJHYHPIBQVSZBkV5ym7VV6vtdLcK+rcXSTSEkNHcxjexrW9gaOAQe2OZJesTu1Le7DXSUFwpHAskYfZe3XiyRvY5ruwg8Cgtbw3I4cuxaxZJDH4LbvSMnkgB1EcnxZGA94a8EaoOzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgxpvHQVly2xzKkoWOkqTQGURs15nMge2WQADidWMPDvQVW/AgILUNmqCstu2GG0lfG6GpFB4xjd2hk8j5YwQew8jxw7kGTUBAQEBAQEBAQEHRdzMbny7A8nx6k0NZX0ZNEw6AOnhc2aJpJ4DmewDXuQVRVFPUUdRNS1UMlNU0z3RVFPK0sex7Do5rmkAggjQgoFPT1FZPBS0sElTVVL2xU9PE0vfI95Aa1rRqSSToAEFsO2+O1OJ4LjOP1hH023UTRWtBBDZpCZZGgjtDXPIBQd2QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAI14HiD2hBFTN+l6z3q4T3PE7uMdNS4vmtEsJlpQ9x1cYi1zXRt/N0cPRoOCD1wjpdtFluUF0yy7tyH6K8SQ2iGHwqZzm8QZnOc50jdfxdGj06jgglaAAAANAOwICAgICAgICAgICAgxll+z+AZvVOuF7sjRdH6eJc6R7qeZ4AAHiFhDX8ABq4EgdhQecP2gwDCKoV9ksgNzbqI7nVyOqJmA8Pky8lrOB01aAdO0oMmICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDi7xerTj1vnut7uEFst1MNZquoeGNGvYB3knuA4nuQYab1JbUuqhT/pasbEX8n000U3haflacvPp/5dfUgzRabvbL7QU90s9fDcrdVN5qesp3h7HAcDxHeDwIPEHtQcigICAgICAgICAgICAgICAgICAg4d+Q2CJ745L5b45I3FskbqmIOa4HQggu4EIOQpaukrYhPRVUVXASWiaF7ZGajtHM0kcEH0ICAgICAgICAgICAg+OsuNvt4Ya+up6ESkiI1ErIg4jt05yNdNUHzwXyyVUzKelvFDUzyHSOCKoje9xA14Na4k8EHKICAgICAgICAgIOKmvtjppXwVF5oaeeI8skMlREx7T6C0uBCDkopY5o45oZGywytD4pWEOa5rhqHNI4EEdhQe6AgICAgICAgICAgICAgICD1c5rGue9wYxgLnOcdAAO0koOH/aTHf/r9u/8Amof/AEkHLRTRVEUc8ErJoZWh0U0bg5rmnsII1BCD9EBAQEBAQV79TuV11zzn9l/Gc22YzBCRSgnldU1MTZnSuHYSGPa0ejj6SgjUglD0u5XX0GYVOJumc+1X2llnZTHUtZVU7Q8SN9HNGHB3p9n0BBPxAQEBAQEBAQEBAQEBAQEBBhbe3qA2w6f8cGRbjX5tC6qD22WwUwE1yuMjBqWU1OCCQNQHPcWsbqOZw1CClneHzPt58xqKug2uoaLa3HjzMp6sRx3G8SsPDmknqGGCPUDgI4uZup+UdwKCBGW7p7l55LLNmu4GRZW6UkvbdblVVTBr3NZLI5rR6AAAg6H6uxByNrvF2slUK6y3SrtFawaNq6KeSnlA9AfG5p/nQS/2c64upXAb3ZLc3cSrzGxz1lPBUWXKtbqx8bpGtIbUyn6UzRp0AZMB6uxBs5IKwfMt3h3N2jse0lRttmdww+a+V14ju0lA5rTOyCKkMQfzNd8Uvdp+FBUv/rO6pf42ZH/1Yv7tBNToE6jd8dzOoa24tnu5V4yjH5bHdKmS1VsjHRGWGNpjeQ1gOrSeHFBNjrH63bH060/7G4hTUuUbtXGAStt07iaOzwSt1jqK4MIc97wQY4Q5pI9txa3lDwoe3E6iN7d1bhUV+cblX27NnfzttUdW+lt8Wh1AioqcxwM04cQzU95KDqON7n7kYfcYbvi2e5Bj9yhe17KuguNTA4lmugdySAOHEgtdqCCQRoUG4Sg+asrKO3UlTX3CrhoaGiifPWVtRI2KGKKMFz3yPeQ1rWgakk6BBVP1A+aBieI1dfjOxtlgzy70rjFLmlyMjLKx7eDvo0Mbo5qoA6jm5o2d7S9vFBVduB1d9R+5c07sk3ZvtPR1BINms05tFEGHXSN0FD4LZABw+U5j6SSgjtU1VTXTyVVZUy1dTKdZaiZ7pJHEDQFznEk8Bog/BBlbC99d5dupIH4TufkuOxU5BZQ01xnNIe/R9K9zoXj1OYQgsm2J803JqCsobFv7YoL9aZC2KTObHA2mr4ST/wA2pomkQTDjx8ERkDsa88EF0GHZniu4OOWvLsKv1JkmN3mLxbdd6KTnieNdHNPYWPY4Fr2OAc1wLXAEEIOzICCoLzJ99N3Npc320t22+e3TEKK72OrqblTUD2NbNKypDGvdzNdxDeCCtb/Wd1SfxsyP/qxf3aCxTy3d+t4t2N086s2424F0y61W7FXVtDRV72OZFUfTqaPxG8rW8eV5HwoJFdWnXriewVRV4NhVHTZvuoxg+mUcj3fo2zlwBb9OfGQ6SUg6iFjgdOL3M9kOCj3c7qb313erKmozbci8VVFO4lmP0VQ6htkbTwDWUdMY4joDpzODnHvcUGB0HdMO3H3A28rWXDBc1veIVbXBxltNdPSB/qkbE9rXg9hDgQe8ILdulPzKa663a2bf9RElMH3GRlLZ9zqaJlM0TPcGsZdIIw2JrXE6eNEGtbw52ac0jQuXBDgCCCCNQR2EIPKCC3mF7j5xtdsLR5Lt9k1Zil9kyu3UT7pQua2U08sFW58erg4aEsaT+BBSF/rO6pf42ZH/ANWL+7QSA6V+qfqFzPqF2nxbKN2L5e8fvd8jprraqmSMxTxGN5LHgMB01HpQbEyAgIMf7sXOvsm1m5d5tVU+huloxW81ttrYuD4ainoZpIpG668WuaCEGsz/AKzuqX+NmR/9WL+7QP8AWd1SfxsyPT0+LH/doNnzBK2quWD4bca6d1TW19jt1TWVL/jSSy00b3vd6y4klB2pBg7fXqI2x6eMaZkO4V4dFUVoe2w41RNE1yuUkYHM2mhLmjRuo5nvc1jdQC4EtBCkfeHzL99s9qKuiwB1NtPjMnMyGO3tZV3WRh/9rXTs9g8NR4EcZHZzFBBPJ8+zrNqh9XmWZXzK6mR3M+e73CorXa/hnkfog6l/Sg5my5HkON1Aq8dv1xsNWHBzaq3VU1LIHN4tPPC5p1HdxQWA9JPWD1EHeLbLb287j1+W4plmQUFputDkAbcZhBUSiNzoqycGpa4AnT5TT0goNihAQEBAQQh6m9uLqbwzP7VSSVluqaeOC/eE0vdBLCORkzwOxjmBrde4jj2hBEBBMrpk23ulNcKjPbxRyUVKKZ1Nj8UzSx8xm08ScNIB5A32WnsdqdOxBNNAQEBAQEBAQEBAQEBAQEEcup3qMxnpr25qMuu8bLpkNze6iwrFw/lkr63l5tXacWwwgh0r+4aNHtvYCGsNuVubm+7uXXPOM/vs1+yG6OHiTv0ZHDE3hHBTxN0ZFGwcA1oA7zqSSQ6H6kHcML2+znce6/oTAsRu2X3Xg6SjtNJLVOja46B8pjaRG3gfacQPWgl7ZvLe6rrtSNqqjDbXYXPAcyluN5ovFId3ltPJOG/gcQR6EHAZh5f3VVh9LLXybbOySigGssuP11LcJezXRtKyQVLz/wCCI/0IIs2613OyZja7TebdVWi6UN0pYq221sL6eoheJWEtkikDXNPHsIQbjSCnjzc/3d2P/wAxvvzNEgpD9SCWHR1ujbdl9zsi3MucbaiPFsLvc9DRPdyiprZWRw0dOTqCBLPIxhI7ASe5BHDLMpv2cZNfcvyi4yXbIckrZrhd7hKfaknncXOIHY1o7GtHBoAAAA0QflaMayO/iV1hx+5XpsB0nNBSTVIYfzvCa7T4UHyXO0Xay1Bo7zbKu1VYAJpayGSCTQ9h5JGtP8yDcwe9kTHySPbHHG0ukkcQGtaBqSSewBBrsdcvWhdd6cguO2+3d3lo9oLHOYaiemc6M5DUwu41ExafapmubrDGeDuEjxzcgYFcwQfbbbbcbxX0trtFvqbrc6+UQ0NupInzzzSO4NZHFGHOc4nsAGqCZGJeXv1VZZRRXD/+eMxulnYHwG/XClopna9zqbxHzxn1SRtQfbkfl1dVuPUUlfFgtHkUULS+eGz3Wjmna0AnhDLJE954cBGHH1IIa3/Hr9il3rbBk9lrsdvluf4dws9yp5KWphf6JIpWtc09/EIOHKCXXSJ1UZF02Z3DJUTVFz20yKaOHNcZDi4NYSGivpWE6NqIRx7hI3VjvxXMDZ3s93tmQWm2X2yV0N0s95pYa61XKncHw1FNUMEkUsbhwLXtcCCg5FBRT5tn2ibR+7lb9bCCpP4EElOnTqBuHT03dK/Y9EXZjleL/s/idWWh8dHUT1kEslY8O4HwYo3FgIOr+TUFvMgwXbbXlOd5GygtFvuWXZXkVU98dJSRS1tdWVMpMkjgxgfJI5xJc46E9pKCZNg8uTqrvlDHXzYXb8fEoDoqS63ajjnLSO10cL5iz8D9D6kGKN2ekfqB2WoZrznG31VHjkLiJcmtksNyoY2g6c80lK+R0DSeAMzWa9iCNqDwg2LfLd36q91dn6nBskrnVmW7TyQW9tTM/mlqbPO1xoJHE6EmLw3wH81jCTzOQWLIK4PNJ+7RQe+lq+rVqDXc9GiCTnRj96XZL3ji+akQbUyAgIMY72/Yzu57l3/9XToNQv8AmQeNO1BuH7bfZ3gPu5avqkSD03Kz6ybW4Dlu4eROcLPiNtnuNXFH/wAyYxt+Tgj14c8ry2NuvDmcNUGqJvFu7mO+GfXrcDNq91VcrpIRRUTXONPQUjXEw0dMwk8kcQOg7ydXO1c5xIYuQS12S6J9/N97bT5BjOO09gxGrJ+h5dkUzqGjqADoXU7GslqJm9vtxxFmoI5tRoglpD5Sm5RjjM+7GMxzFoMscdJWPaHd4DiGkj16BBirN/LF6k8Xp6issAxzcCCFvO2ms9e6CrLQNXfJXCKlYSOOgbI4nu48EGD+nnEcowfqw2WxzMceuOL36izW0fSrRdKaSlqGA1LdHckrWktdpq1w4EcQSg2n0BAQEBAI14HiD2hB1cYRhbaz9INxCyC4c3P9OFvpvG5vyvE8Pm19eqDtAAAAA0A7AgICAgICAgICAgICAgICDwSGgkkAAaknsAQatPWTvvV7973ZHe6esM+HY1NLY8DgYT4X0Cmkc01QB/Gqngyk6a8pa0/FCCKmvrQTC6QOk+99TWYzirnmse2+MPjfmGRRAeK8v4soaPmBaZpQCS4gtjb7TgTyMeGyLt1tngu0+M0eIbe41R4zYqMD/tqVntzSaaGaoldrJNI7ve9xcfSg72gIMJbw9PO1G+VHTR55jMFTeLa5j7NldIGwXSjdG8PaIqkNJLNRxjeHMPe3XQoM2oKePNz/AHd2P/zG+/M0SCkPtKD2BLQQCRzDQ+sdvH+RBa90I9DFs3OttLvJvJQST4VLK79jMOe58X6VMLtHVlUWlrvowcC1jAQZSCXfJgCQLz7NZLLjttprPj9oorFaKJvJR2q3U8dLTRN9EcMTWsaPUAg4DO9usG3NsVTjOf4rbsrslUxzH0VwhbJyc2mr4ZOD4njQEPjc1wIBBBQQg8yXfCp2u2Uhwqw1rqPKN255rUJoyWyRWeBjXXJ7XDsMgkjg/wDDI4jiEGufog5rG8dvOXZBZcWxy3yXS/ZDWwW+z26HTnnqah4jjYNdANXEcSdB2ngg2culbpLwjptxWlLKWmvm5dzp2nLM1fGHSc7wC+koi4c0VOw8ABoZNOZ/4rWhLZAQRu6lOmXA+pLDaiy5DSxW3K6CJxxHN4YmmsoJuJaxzuDpKd7j8pETofjDleGuAau+cYZkG3mX5Hg+U0Rochxavmt90p9SW+JC7TnY4gczHjRzHae00g96DqyC/bytt5KjLtsMj2mvNYai6baVTKmwGR2rjZ7iXuETdSXOFPUNk1PYGyRtHAILTEFFXm2faJtH7uV31sIKkvwIOUsdlumSXq0Y9Y6OS5Xq+1sFvtNBENXz1NTI2KGNo9LnuACDaE6VulrD+m3CaOkp6Smum4l2pmOzXMuTmlmmdo91NTvdxZTxO4NaNOfTneOY8AlUg/Gop6erp56WqgjqaWpjdFU00rQ+OSN4LXMe1wIcHA6EHtQaz/Xp0927YXeZ5xek+h4HuBTPveMUbG6RUUokLKyhj/NieWvYANGxyMbx01QQi7OxBYf5Y2YTY71NUePCQimz7HrpapIPxTJSxi5sf+FraN4B9Dj6UGxogrg80n7tNB76Wr6tWoNdxBJzox+9Lsn7xxfNSINqZAQEGMd7fsZ3c9y7/wDq6dBqF/0IPH/BQbh+232dYD7uWr6pEghT5nN3q7b0vV1FTPLYcgye0UFwb+VCx0tYAf8A3lMwoNcdBmfp1xCw59vrtRh2UaOx7IMloKW707jyiohMoc6mJBaR4+nh6g6+1w4oNtWmpqeip6ejo6eOkpKSNkNLSwsEccccYDWMYxoAa1oAAAGgCD9kBB1PJMEw7L6zHrjkuOUN4uWJ3CG64zcqiIGpoayneJGS08w0ezi0cwB0cODgRwQdsQEBAQEHQb9ujt9jNY633vK6GkroyRNRtc6aSMjukbC15YfU7RB2GwZPj2U0prcdvNJeKdh0kfTSB5YT2B7fjNPqcAg51AQEBAQEBAQEBAQEBAQEEcerrPZttum7dvKaSoNLcWWN9stVQ348dVdpGW+GRn5zHVAePwangg1S9EHsyN8r2RxxukkkIbHG0aucTwAAHaSg2zem7aC37G7M4Tt9SU8cVyoaFlXlNSwDWpu9U0SVsrnD4wEh5Ga9kbWN7GhBnNAQEBAQU8ebn+7ux/8AmV9+ZokFIf8ASgyTs9t9U7q7p4Dt1SvfGcuvdJb6moj0LoaV8gNTMAddfChD3/Ag25rHZbXjdltGO2Ojjt1lsVFBb7TQRDRkFNTRtiijaPQ1jQAg5RAQa6HmdZtNknUpNjImcaLbywW62sptTyNqKxhuUsgH5TmVMbSfzQO5BXZ+FBaT5Vu2NNk27mW7lXCm8aDbW0shtDnAcrLjefFhbICe0tp4p28PywfwhfygICAgoX81vbmlsW5+BblUNN4P7fWee33mRg4SVlldE1srz+U6nqY2DU8RHw7CgqlQT88tPL5ca6pLDaPF8Omzuy3WyVQc4NZrHB+kotdeGpfRBo79Xad6DZGQUU+bZ9om0fu5XfWwgqTQWDeWdglJl/UvR3iugbNT7e2CvyCBr2ksNUXRUEHq5mmrMjde9mvaEGx4gICCqnzZMcgq9n9t8r5C6rsOXm2McBrywXOhnlkJOnAc9FGO1BQkglP0SVb6Lqq2Wmja17n3x0BDtdOWopZ4XHh6A8kINpxBXB5pP3aaD30tf1atQa7n/GiCTfRjp/ql2T944vmpEG1OgICDGO9v2M7ue5d//V06DUK70HlBuHbb/Z3gXu5avqkSCNnXtt/Xbh9L+4VJaqY1d1xltNklFTtGrnMtkokquXv1FKZiAOJPDvQawf8Axog5C03W42K6W292eslt13s9XDXWu4QOLZYKmneJIpY3dzmPaCD6UF+PT15mG2mZ2y32Het427zOKNkM+QCKSSyV8nZ4gdGHvpXO7XNkHhjuk/FAWVWLIbBlFsp71jN8t+RWerGtLdrZUxVdNIB+RNC57HfAUHMICAgICAgwpv5m1dhWAzz2qV1Pdb3UsttHVsOj4BI175JWntBDGEAjsJB7kFZ7nue5z3uL3vJL3E6kk8SST6UHbMIzG64LkduyG1TOa6lkArKUEhlRATpJE8dhDh2eg6EcQEFtNPPFVU8FVA7nhqY2ywv9LXgOaf5Cg/ZAQEBAQEBAQEBAQEBAQVy+aLdnW7pmp6Nsvhi/5jaqB7NHHxAyGrq+Xhw7aYHjw4enRBrr69iDMPT1Y4sl342ZsVRH4tJc82sUNdHqBrTmvhMw4gjXwwdOCDbhQEBAQEBBTv5uf7u7H/5jffmaJBSIgnj5bdpprl1XYfVVADn2O1XqvpQRqPFNDJTa9vc2cnjrx/lQbKSAgINVjrMuH6U6pN7anxTN4eSTUnORykfRI2U3Lpw+L4emvfogjGgvu8pq1Nh2c3JvfhgOuGZ/QTLqPaFHb6WUN07eH0rX4UFqqAgICCqLzZ6OB+0u2Fe5mtVTZdJTwv8ARHPQTvePhMLUFDSCUPRZNLT9U+yb4ZDG91/EbnDvZJBKx4+FriEG1Cgoq82z7RNo/dyu+thBUigtT8pr7Ztx/ct36xpEF+CAgIK4PNJ+7TQe+lr+rVqDXc7EEnOjH70myfvHF81Ig2pkFcHmk/dpoPfS1fVq1BrtoJO9GP3pNk/eOL5qRBtTICAgxjvZ9jO7nuXf/wBXToNQtB4Qbh+232d4D7uWr6pEg7jLFHNHJDNG2WGVpZLE8BzXNcNC1wPAgjtCDXx60+hLIdq7xd9ydprNUX3au4SSVlys9Iwy1OOve7mfGYm6vfSDUlkgB8No5ZOwPeFZ3qQP6kHdsG3Jz/bO6svW3+Y3bEbk1wc+e2VUkDZQ08GzRtPJK30teC094QWk7FeafkFulobDv5jkd/t/sROzqwxNgrox2GSqodRDN26kwmPQDhG8oLksD3Awzc7GaDMMCyKjyfHLkP8At7lRv5gHgAuilYdHxSM1HMx4Dm94CDuKAgICDCe/mFV+a4FNBaYTU3Wy1LLlSUrBq+YRseySNgAOrix5IHeQAgrPIcxxa4FrmnRzTwII9KDteFYfdc5yO349aYXOkqpAauqDdWU0AI8SaQ9gDR/KdAOJCC2ungipaeClgbyQ00bYoWehrAGtH8gQfsgICAgICAgICAgICAgIK2vNOtr67pss9Uzm0s2cWusk5ezR1HX03terWcfDog14UGWthL/Di2+Oz2RVM30ejs2aWKqr5vRTx18Jn11B7Y+YINulAQEBAQEFO/m5/u7sf/mN9+ZokFIqCwTyyvvSWn3cvHzTEGx8gICDVc60rWbP1Tb2UjofB8XIX1wZqTqK6GKrDuP5Xi83w8EEYPwIL3vKWvsNRthurjLZi6e0ZTT3OSDmPssuNEyFjuXTQcxonDXXjp6kFsiAgICCpTza7xTwbb7S2Bxb9KueSVlwhaT7Xh0NH4UhA9GtW3VBRQglj0MWqa89V+zNLBrzQXWprnkafEoaCpqn9pHDSI/1angg2kUFFPm1/aLtH7uV31sIKk/6kFqflN/bNuP7lu/WNIgvvQEBBXB5pP3aaD30tf1atQa7aCTvRj96TZP3ji+akQbUyCuDzSfu00Hvpavq1ag12/60EnejH70uyfD/APY4vmpEG1MgICDFu+MscOym8E00jYoYsJyB8sryGta1ttnJLieAAHaUGocg8+pBuHbbfZ3gPu5avqkSDuiAghBvh0A7C7yyV15pLQ/bjMqxzpZMjx1rY4Z5XakuqqB3yEmpJc5zBHI49siCqjdfy1OoLADU12IQUO61ih1c2azPFPcRHroDJb6hwcXH8mGSUoIDXmyXnHLnV2TIbRW2G829/hV9puNPJS1UDxxLJYZmtew+ohBxnBBIvpp6kMy6b88pMjsVRNW4xcJoos1xFzyKe40gJBIaSA2eIOc6J/c7gdWFzSG01i+S2bMsbsOWY9WNuFiySgp7laK1nZJT1MbZY3adx5XDUdx4IOdQEBAQdAvu1m3uS1j7hesUoauulPNNVta6GSRx/GkdC5hefW7VBz+PYrjmKUz6PHLLS2eCQgzCnjDXSEcAZH8XPI9LiUHYEBAQEBAQEBAQEBAQEBAQRd60MBm3H6Zd2LBRwma5UNqF8tjWjV5ls8rK8sYOOrpI4XRgd/Mg1XkHkEggtJaQdQexBtX9J29tBvzsliOXCsbPklBTMtGb0pfzSxXWjY1kz3jtAnHLO38147wUEk0BAQEBBTx5uf7u7H/5jffmaJBSIgsE8sv70tp93Lx80xBsfICAg15vNGwCoxvqBt2bMp+W27j2Cln+lAaB9dagKKdh9JZC2nOvocPQgrV7tUFhfltbyUe2e/H7K3usbR4/uvRssZle7ljZdYpPEtrnkn8dzpIG/nShBscICAgINdnzNd2qTPt96TC7TUNqbTtRbja6mRjuZhutW8T13KewcjWwxOHc9jvgCuNBaR5VW3s193ky7cOeEOtuA2A0lPMR2XC8P8OLlJHdTwzg6ekelBf0goq82z7RNo/dyu+thBUkgtT8pv7Ztx/ct36xpEF96AgIK4PNJ+7TQe+lr+rVqDXb7kEnejH70uyfvHF81Ig2pkFfPmbWp1w6XLnWNDiLFklnrnlpAAD5H0ntAjiNagdnfp3INcNBk/ZTL6fAN4Nr81rHiOgxfKbVcbk891LBVxuqP/hcyDbxa5r2texwex4DmuadQQewgoPZAQQ369NyaPbjpk3CD6hsd1zmm/ZOyU3MA6Z90BjqgO/RtIJnH8Gneg1hUBBuHbb/AGd4F7uWv6pEg7ogICAgwXvr07bY9QeMz2HPLHFJcooHssGW07GsudskcDyvgnA1LQ46uidrG78ZvYQGrfunt7dtqNxMx24vkrKi54fc5rfNVxgtjqGRnWKdjXcQ2WMteAeOhQdAQbJnlr5NWZD0tY9R1kr5jid6utlppH6a+CJRWMaDqSQ0VXKNewDTsAQT3QRx6g91bjgltt9ix2UU1+vrHyyV+gc6lpWHlLmA6+3I7g06cAHd+hAV+1VyuNdVuuFbX1NZXucHOrZ5XyTEjsPO4l2vwoJbdPW8V7qL3S4Jk9dLdKW4MeLFcal5fNDLGwv8F73cXMc1pDdTqDoBwPAJtICAgICAgICAgICAgICAgICD1exkrHxyMbJHI0tkjcAWuaRoQQe0FBqw9X2wVd0+7zX/ABuGmeMOv0kl3wGuLdGSW6d5P0fUcOeleTC7vPK1+gD2oIuoJD9N3UjnHTXm37T4uRcrJdBHBl+IVEhZS3OmjJLQXAO8OWLmcYpQCWkkEOY5zXBsN7KdYGxW+dFRjHMwpbJk84a2owi+yR0NzZKRxZCyR3JUj86Bzx6eU8EEoEHBZFlGM4hbZrzlmQ23GbRTgme6XWrho6dgA1Oss7mNH8qCsjfTzL8MtNdBhew0LcxvtdWQ0dVnNZC+O1UjZJGse6likDJKqQakAuDYgdHAyt9khaogp483P93dj/8AMb78zRIKQ0Fg3ll/eltXf/8Ajl4+aYg2PUBAQQr67tgKjffZKvbYKM1ed4DI++4lBGCZaoMZy1lCwDUkzxDVgA4yMjHAaoNZEgtOjgQR2g8D60HsyR8T2yRvdHJG4OjkaSHNcOIII7CCgvW6SfMYxa+2a0bfb/3ZuOZXboo6S3biVTiaC6NYOVrq+Xj9Hn0A5pH/ACbzq4uYfZIWt2y6Wy9UNPc7NcaW7W2rbz0lwopmTwSt/KZJGXNcPWCg+ipqaejglqquojpaaBpfPUzPDI2NHa5znEAAekoKzuq7zDcF2+sd0w7ZW90mbbi10b6X9oaFwqLVZ+YcrpvHb8nUzAH5NkZcwO4yH2eR4a/tXV1Vwq6qurqiWsra2V89ZVzOL5JZZHFz3ve4klziSST2lB601NUVtTT0dHTyVdXVyMhpaWFhkkkkkIaxjGNBLnOJ0AA4lBtIdGuwh6fdkrJjNziY3MsgkN9zeQaEsrqqNgFKHAnUU0TGRcDylwe9vxkErEFFXm2faJtH7uV31sIKkvUgtT8pv7Ztx/ct36xpEF96AgIK4PNJ+7TQe+lq+rVqDXc7UEnOjL70uyXvHF83Ig2pkGB+p/AKjc/p+3YwmipxV3K62Cee0Uumvi11AW1tIwet00DAD3FBqaoCC/Loa638OyfDMf2l3YyKmxrOsYp4rZj99ucrYKS8UUIEdM01DyGNqY2hsZa8gyaBzS5xcAFpzXNe1r2OD2PAc1zTqCD2EFBjfc3eDbXZyxTZDuPl9vxmhjjc+ngqJA6rqi38SlpWc007tT2RtOnadBxQa3XV11R3rqbzyG5R001kwHGWvp8KxuZwMjGycvjVdTyktM85aNQ3g1oawE6F7giYg8fAg3D9tvs6wH3ctX1SJBgnq/35yDpz2ysm4uP2mivsjcpoLbdbPXF7GVFFUQVLpWMlZxifrG0tfo4Aji1w1BD8djOs/YvfaCkpLLk0eL5hM1onwi/vZR1vinQFtM9zvCqhrrp4Ti7Ti5jexBLBAQdVzXOMS25xu5Zfm9/o8axy0xmStudbII2DQEhjB8aSR+mjGMBc48Ggngg1RN/Nyo94N5NxNyIKd9JRZTeJai100gAkZRxNbBSiQDhz+DGzm9evagxF+FBsseXLiFZinSziVRXQup58vuNyv7YXfGEM830eBx4nhJFTteNO5w70E6kEF+rGx1keQ41kojc6gqrd+jDKB7LJqeaSYNce4ubNw9PKfQgiUgy/sTYq297nY0aRj/BtE/6Rr52dkcUALhzH0Pdys+FBZ8gICAgICAgICAgICAgICAgICCPvUl074j1I7fVGHZE79G3eic6rxHKYo2vnttby6BwB054pNA2WPUcze8Oa1zQ1kd39mtwNjswrcK3CsklruNO5zqCuaC+jr6cHRtTRz6ASRu+BzT7L2tcC0BixAQd2s+5W4uPRNp7Bn2R2OBjPDjht91rKZgZ28obFK0aepB1y6Xq8XyoFXertW3iqDeUVVbPJUSADu5pHOOnwoPoxv94rAP8A7jS/PNQblCCnjzc/3d2O/wAyvvzNEgpD/m9KCwXyy/vS2r3cvHzTEGx8gICAgpf67OhGvrK+8727JWeSvlrpJK7PsBo2c0viu1fLcLfE3i/nOrpYWgu5jzsB1LWhS6QWktI0cOBHo0QP+Ag5+x5XlGMSOlxrJLrj0r3B7pLZWT0ji4aaOJhew6j0oP3v2a5llP7z5becj4h2l0r6is9oAAH5aR/EAAIOs/1oP2p6aoraiCjo6eSrq6uRsNLSwsMkkskhDWMY1oJc5xIAA7SgvQ6FOhOrwKstm9G89s8HMIAKjCMIqA1xtZc3VtbWtOoFSAfk4/8A1PxnfK6CMLbEBBRV5tn2ibR+7ld9bCCpL4UFqflN/bNuP7lu/WNIgvvQEBBXB5pP3aKH30tX1atQa7aCTvRj96XZP3ji+bkQbUyAg1r+vTpmuWyG6Nxy2x2552w3DrJq+w1kLCYbfXTEy1NtkIGjC13M+EHtj4DUxv0CBqAg7hZ9ws/x6kdb8fzjILHQOYY3UVvudVSwlju1pjika3Q+jRB1uvuNwutVJXXSuqLlWzf86sqpXzSvP5z3kuPwlBOHpa6UrnuLh25G9eaWt9Pt3hOK36qxhlQzRt4u9PQz+EY2u+NBSvHO93YZGtjHNpIGhBLVAQbh22/2d4F7uWr6pEggp5pPDppoPfS1fVq1BruIMyYj1Eb7YHBFR4lu5ldmt8A0gtcdzqJKRg0I9mnle+Idvc3+gIMhVXW31VVkEdNLvTfGRxN5WugZSwSEacvtSRQMe46d5Pr7UGB8v3AzrcCuFyznMr3mFcwnwqm819RWuj1/FjM738g9AboAg6igl10ldKWVdSOa0XjUlVatr7LUtdmmWhvK0sj0eaGke4aPqJQQOGojaedwPsteGzxaLTbbDarZY7PRx260WakhobVb4RpHBTU0bYoYmDuaxjQB6kHIIOGv+P2fKLVVWW/UEdxttYAJqeTXtHFrmuBBa4HiCDqEEbKrpPxSWrdLSZLdKWjc4kUjmQyuaCfiiTlb2dnFpQZ0wbbzF9vbfJQY5RujdUEGtuE7hJU1Bbry+JJoBoNToAAB3BB3hAQEBAQEBAQEBAQEBAQEBAQEBBj7crarb3d/HJsU3HxWiymyyEvihqmkS08hHL4tNPGWywSaHTnjc06cNdEFTe63lOzmoqbjstuLC2nkc58OMZYx7TGO3lZcaSN/MO5odTju5nniUEN775enVlY5/Cj2zZfYCeVlda7tbZWE8fxJKmOUdnaWAfCg6hSdE3VVWyOih2VvjHNaXazupadugIHB007Gk8ewHVBl7EPLN6oMiqImX20WLA6Zx1lqbvdoKhzW68eWO2fTSXadgOnrIQWCbJ+WHtZgVbbsh3Lv9XuZfrfLHU09rYw2+0Ryxu5280THvmn5SB8aRrXae1GQdEFnSCC/W50sZh1PWvbyhxHIrPj8mH1Vxnrn3c1AbK2tZTtYI/Ail4gwnXXRBXv/ALTe8/8AEfC/7Vx/wiCTfSR0FbjdPe8NFuNk2Y43erXTWquoHUNsNZ9IL6pga1w8anjboNOPtILVUBAQEBBC7fvoS2P32qqzIJrdNgmc1fM+fK8fEcX0qV2p566kc0wzkk6ueAyR3fJogrBz3yst+Menlkwe+47uHbQSKcCd1przp3vgquaBvwVDkEfrl0L9WFpLhVbM3SUteGH6HVW+tGpHNqDS1Uuo4dvZ3dqD6LV0H9WV4dAKfZ6vpWz66SV1dbaMMAOhLxUVTHD06aanuBQSR2/8qjeK9ywz7h5lj+CW55+VpaLxbxcG6doMbBBTjXuInd+D0haTsL0Z7I9PzobpjdjkyHMmM0fm1+LKquYSPa+itDGRUw7RrGwP04Oe5BK5AQEFdHWx0b511N5ThF9xLKLDYKbGLVUUFXDdzVB8j5pxKHM8CGUaAcDqQghN/tN7z/xHwv8AtXH/AAiCZXRX0V570z57lWWZZlVgv1HfrAbTTU1pNUZWSmqgn53+PBEOXSIjgddUFkyAgIIq9YewuR9Rm01Nt/i94ttjuUN/o7s6tupmEBipoqiNzPkI5HcxMw04aIKuv9pveb+I+F/2rj/hEGXNhPLd3T2n3i2/3GvOdYrcrXiN1ZX1tDRGu+kSsaxzS2PxKZjdfa7yEFyaAg6vmeFYpuHjV0w/NrFS5JjV6i8K5WmsbzRvAIc1wIIcx7HAOa9pDmuAc0ggFBTlvJ5U14iray7bGZpS1dtlLpI8RydzoaiHjr4cFfDG9ko46NErGaAe09x4oIX3roM6srG+RtRtBW1rGaFs1urrdWteC4tBAp6p7u7sIBA4kIP3sHQN1Y5DLCyLaiotMEpPPWXWvt9GyMAkauZJUiXtHY1hPfppxQT22J8rC3Wqtosg38yaDIDTPbKzBMffKyjeRx5ayve2KV446OZExnEcJSOCC0nKsHpbhtfk+3OL0tFj9JcsYr8esNJFGIaOjbUUclLA0RxN9mNnMODW9nYEFJ/+03vN/EfC/wC1cf8ACIPH+01vN/EfCv7Vx/wiC9HFLTNYMWxuxVMjJqiy2qjoJ5oteR76aBkTnN1AOhLdRqEGNd+9i8S6h9v59vcxrLjbrca2G5UdwtckcdRDV07ZGRP+VjkY5ukjgWlvEd4PFBULn/lQbnWuaon243CsOW0DdXQ0d4jntNby6ahg8MVUL3Ds1L2A9ug7EEart5fvVtaJSx21Elxi1+TqaC62qoY7QAk8ravnHbp7TRr3IOtUvRP1U1kvhQ7LX1jg0u5pzTQN0H5807G6+rVBlPFvLW6qMhkjF0xuzYVBIW/9zervTPAaeOpZbjWvGnoLdfUgnPtB5VeB49U0l33izCpz2ohIe7F7Sx9ttpcO1k1Rzmpmb62GE/1haTjuOWDEbLb8cxay0WPWG1R+DbrPb4GU9NCzUnRkcYDRqSSeHE8TxQc0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIP/2Q0KZW5kc3RyZWFtDQplbmRvYmoNCjIyIDAgb2JqDQoxNTE2OA0KZW5kb2JqDQoxNSAwIG9iag0KPDwvTGVuZ3RoMSAyMyAwIFIvTGVuZ3RoIDI0IDAgUi9GaWx0ZXIvRmxhdGVEZWNvZGU+PnN0cmVhbQ0KeJzsfAl4VFWW8LlvqX1PVVJJBfIqlbAVppJUAokgKcjCEoghCZgCgilIQgKBBBJAVBaHIBpXRFRwaVptRntorWCPHVFbnHZp/XXcp8Vuu22l3RqQ7kb0Q/Jqzr3vVVJhcfz7m+lv5vt4lXffufeee+/Z7jnnPqoAAgBm2AI8VF9eG8hvvDX0Abb8Du/GpSsjnbpb9Q4AMhnvuqXruqWNk9paALjbAQw5LZ3LVs6seX8ZgOkQ1hcta9/Q8tD8f3oMICUdwHWktTnSdB9kcACX4HQwoRUbnBbdp1gvwnpW68ruqx5/0erF+iKs39fesTQC5KHrsf4t1veujFzVyT9t/hAg5x6sS6siK5s/tq57A+v9AGOyOju6umNzYT3AfEqv1LmmuXPFX9J1WD8DIFwCvNDPPQMi6MQ9YhA58ChP/i1o4Rw6kTPqOAE/HH8EcmKH4MhmnEVPSZ1TK0kggTk2IL4jzyVm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\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t1234567890128\n+\t\t\t\n+\t\t\t\tCRONUS International\n+\t\t\t\n+\t\t\t\n+\t\t\t\tMain Street, 14\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tGB123456789\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tCRONUS International\n+\t\t\t\t123456789\n+\t\t\t\n+\t\t\t\n+\t\t\t\tJim Olive\n+\t\t\t\tJO@contoso.com\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t789456278\n+\t\t\t\n+\t\t\t\t8712345000004\n+\t\t\t\n+\t\t\t\n+\t\t\t\tThe Cannon Group PLC\n+\t\t\t\n+\t\t\t\n+\t\t\t\t192 Market Square\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tGB789456278\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tThe Cannon Group PLC\n+\t\t\t\t789456278\n+\t\t\t\n+\t\t\t\n+\t\t\t\tMr. Andy Teal\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t2026-01-22\n+\t\t\n+\t\t\t8712345000004\n+\t\t\t\n+\t\t\t\t192 Market Square\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t31\n+\t\t\n+\t\t\tGB12CPBK08929965044991\n+\t\t\t\n+\t\t\t\tBG99999\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t1 Month/2% 8 days\n+\t\n+\t\n+\t\t1000\n+\t\t\n+\t\t\t4000\n+\t\t\t1000\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t14000\n+\t\t14000\n+\t\t14140\n+\t\t0\n+\t\t0.00\n+\t\t0\n+\t\t14140\n+\t\n+\t\n+\t\t10000\n+\t\tItem\n+\t\t1\n+\t\t4000\n+\t\t\n+\t\t\tBicycle\n+\t\t\t\n+\t\t\t\t1000\n+\t\t\t\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\t\n+\t\t\t4000.00\n+\t\t\t1\n+\t\t\n+\t\n+\t\n+\t\t20000\n+\t\tItem\n+\t\t2\n+\t\t10000\n+\t\t\n+\t\t\tBicycle v2\n+\t\t\t\n+\t\t\t\t2000\n+\t\t\t\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\t\n+\t\t\t5000.00\n+\t\t\t2\n+\t\t\n+\t\n+\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\nindex 8a391d8117..7d3502ca5c 100644\n--- a/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\n+++ b/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\n@@ -21,6 +21,7 @@ using Microsoft.Inventory.Location;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.History;\n using Microsoft.Purchases.Payables;\n+using Microsoft.Purchases.Setup;\n using Microsoft.Purchases.Vendor;\n using Microsoft.Sales.Customer;\n using System.IO;\n@@ -884,6 +885,138 @@ codeunit 139883 \"E-Doc Process Test\"\n Assert.RecordCount(PurchaseLine, 2);\n end;\n \n+ [Test]\n+ procedure InvoicePostingDateDefaultsToWorkDateWhenSettingIsWorkDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Work Date\" (default), the created purchase invoice Posting Date equals WorkDate\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Work Date\" (default)\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL invoice (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-0.xml', TempEDocImportParams), 'The e-document should be processed');\n+\n+ // [THEN] Posting Date is WorkDate, not the document date\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(1, 1, 2027), PurchaseHeader.\"Posting Date\", 'Posting Date should be WorkDate when setting is Work Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure InvoicePostingDateUsesDocumentDateWhenSettingIsDocumentDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Document Date\", the created purchase invoice Posting Date equals the e-document's Document Date\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Document Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Document Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL invoice (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-no-currency.xml', TempEDocImportParams), 'The e-document should be processed');\n+\n+ // [THEN] Posting Date equals the Document Date from the PEPPOL file\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(22, 1, 2026), PurchaseHeader.\"Posting Date\", 'Posting Date should be Document Date when setting is Document Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure CreditMemoPostingDateDefaultsToWorkDateWhenSettingIsWorkDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Work Date\", the created purchase credit memo Posting Date equals WorkDate\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Work Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL credit note (IssueDate = 2026-02-15) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-creditnote-0.xml', TempEDocImportParams), 'The credit note e-document should be processed');\n+\n+ // [THEN] Posting Date is WorkDate\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(1, 1, 2027), PurchaseHeader.\"Posting Date\", 'Posting Date should be WorkDate when setting is Work Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure CreditMemoPostingDateUsesDocumentDateWhenSettingIsDocumentDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Document Date\", the created purchase credit memo Posting Date equals the e-document's Document Date\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Document Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Document Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL credit note (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-no-currency.xml', TempEDocImportParams), 'The credit note e-document should be processed');\n+\n+ // [THEN] Posting Date equals the Document Date from the PEPPOL file\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(22, 1, 2026), PurchaseHeader.\"Posting Date\", 'Posting Date should be Document Date when setting is Document Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n local procedure Initialize(Integration: Enum \"Service Integration\")\n var\n TransformationRule: Record \"Transformation Rule\";\n@@ -893,6 +1026,7 @@ codeunit 139883 \"E-Doc Process Test\"\n EDocPurchLineFieldSetup: Record \"ED Purchase Line Field Setup\";\n PurchInvHeader: Record \"Purch. Inv. Header\";\n VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n GLSetup: Record \"General Ledger Setup\";\n Currency: Record Currency;\n LibraryERM: Codeunit \"Library - ERM\";\n@@ -902,6 +1036,10 @@ codeunit 139883 \"E-Doc Process Test\"\n Clear(EDocImplState);\n EDocPurchLineFieldSetup.DeleteAll();\n \n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n PurchInvHeader.DeleteAll();\n VendorLedgerEntry.DeleteAll();\n \n"} +{"metadata": {"area": "peppol", "image_count": 1}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8059", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-08T09:31:42Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\PEPPOL\\App", "src\\Apps\\W1\\PEPPOL\\Test"], "patch": "diff --git a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\nindex 30f5f792bd..c7981a46fa 100644\n--- a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n@@ -798,6 +798,8 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n InvoiceLineNote := DelChr(Format(SalesLine.Type), '<>');\n InvoicedQuantity := Format(SalesLine.Quantity, 0, 9);\n SalesLineLineAmount := SalesLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesLineLineAmount := Round(SalesLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n InvoiceLineExtensionAmount := Format(SalesLineLineAmount, 0, 9);\n LineExtensionAmountCurrencyID := GetSalesDocCurrencyCode(SalesHeader);\n InvoiceLineAccountingCost := '';\n@@ -869,7 +871,10 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n \n InvLnAllowanceChargeIndicator := 'false';\n InvLnAllowanceChargeReason := LineDisAmtTxt;\n- InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ InvLnAllowanceChargeAmount := Format(Round(SalesLine.\"Line Discount Amount\" / (1 + SalesLine.\"VAT %\" / 100), 0.01), 0, 9)\n+ else\n+ InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n InvLnAllowanceChargeAmtCurrID := GetSalesDocCurrencyCode(SalesHeader);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139235, "functionName": ["LineAmountsConsistentWhenPricesInclVATNoDiscount"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\nindex 36931d56ed..cd237011d5 100644\n--- a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n@@ -3349,6 +3349,68 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual('', CustTaxSchemeID, 'Tax Scheme ID should be empty for Tax Category O.');\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ procedure LineAmountsConsistentWhenPricesInclVATNoDiscount()\n+ var\n+ SalesHeader: Record \"Sales Header\";\n+ SalesLine: Record \"Sales Line\";\n+ Customer: Record Customer;\n+ Item: Record Item;\n+ SalesInvoiceHeader: Record \"Sales Invoice Header\";\n+ SalesInvoiceLine: Record \"Sales Invoice Line\";\n+ PEPPOLLineInfoProvider: Interface \"PEPPOL Line Info Provider\";\n+ InvoiceLineID: Text;\n+ InvoiceLineNote: Text;\n+ InvoicedQuantity: Text;\n+ InvoiceLineExtensionAmount: Text;\n+ LineExtensionAmountCurrencyID: Text;\n+ InvoiceLineAccountingCost: Text;\n+ InvoiceLinePriceAmount: Text;\n+ InvLinePriceAmountCurrencyID: Text;\n+ BaseQuantity: Text;\n+ UnitCode: Text;\n+ PriceAmount: Decimal;\n+ LineExtensionAmt: Decimal;\n+ SalesInvoiceNo: Code[20];\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 630795] PEPPOL LineExtensionAmount equals PriceAmount times Quantity when Prices Including VAT is used\n+ Initialize();\n+\n+ // [GIVEN] Customer \"C\" with PEPPOL identifier\n+ LibrarySales.CreateCustomer(Customer);\n+ AddCustPEPPOLIdentifier(Customer.\"No.\");\n+\n+ // [GIVEN] Sales Invoice for \"C\" with \"Prices Including VAT\" = TRUE and Quantity = 7\n+ CreateItemWithPrice(Item, 139);\n+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader.\"Document Type\"::Invoice, Customer.\"No.\");\n+ SalesHeader.Validate(\"Prices Including VAT\", true);\n+ SalesHeader.Modify(true);\n+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item.\"No.\", 7);\n+\n+ // [WHEN] Post the Sales Invoice and retrieve PEPPOL line amounts\n+ SalesInvoiceNo := LibrarySales.PostSalesDocument(SalesHeader, true, true);\n+ SalesInvoiceHeader.Get(SalesInvoiceNo);\n+ SalesHeader.TransferFields(SalesInvoiceHeader);\n+ FindSalesInvoiceLine(SalesInvoiceLine, SalesInvoiceNo);\n+ SalesLine.TransferFields(SalesInvoiceLine);\n+\n+ PEPPOLLineInfoProvider := GetFormat();\n+ PEPPOLLineInfoProvider.GetLineGeneralInfo(\n+ SalesLine, SalesHeader, InvoiceLineID, InvoiceLineNote, InvoicedQuantity,\n+ InvoiceLineExtensionAmount, LineExtensionAmountCurrencyID, InvoiceLineAccountingCost);\n+ PEPPOLLineInfoProvider.GetLinePriceInfo(\n+ SalesLine, SalesHeader, InvoiceLinePriceAmount, InvLinePriceAmountCurrencyID,\n+ BaseQuantity, UnitCode);\n+\n+ // [THEN] LineExtensionAmount equals PriceAmount times Quantity per PEPPOL BIS 3.0\n+ Evaluate(PriceAmount, InvoiceLinePriceAmount, 9);\n+ Evaluate(LineExtensionAmt, InvoiceLineExtensionAmount, 9);\n+ Assert.AreEqual(PriceAmount * SalesInvoiceLine.Quantity, LineExtensionAmt,\n+ 'LineExtensionAmount must equal PriceAmount * Quantity per PEPPOL BIS 3.0');\n+ end;\n+\n var\n local procedure Initialize()\n var\n@@ -3993,6 +4055,8 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual(UnitOfMeasure.\"International Standard Code\", unitCode, '');\n Assert.AreEqual('UNECERec20', unitCodeListID, '');\n SalesInvoiceLineLineAmount := SalesInvoiceLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesInvoiceLineLineAmount := Round(SalesInvoiceLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n Assert.AreEqual(Format(SalesInvoiceLineLineAmount, 0, 9), InvoiceLineExtensionAmount, '');\n Assert.AreEqual(SalesHeader.\"Currency Code\", LineExtensionAmountCurrencyID, '');\n Assert.AreEqual('', InvoiceLineAccountingCost, '');\n"} +{"metadata": {"area": "manufacturing", "image_count": 0}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "bb325c49266ab81baa1c3c2a1154c182019929d4", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} +{"metadata": {"area": "null", "image_count": 0}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7953", "base_commit": "907fd4ab20c5a3156d2d3dac5787bce3a272bb57", "created_at": "2026-05-04T20:30:22Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\EDocument\\App", "src\\Apps\\W1\\EDocument\\Test"], "patch": "diff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al\nnew file mode 100644\nindex 0000000000..45c2b7121f\n--- /dev/null\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al\n@@ -0,0 +1,20 @@\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+namespace Microsoft.eServices.EDocument;\n+\n+enum 6162 \"E-Doc. Purch.Def. Posting Date\"\n+{\n+ Extensible = false;\n+ Caption = 'Purchase Invoice Posting Date (E-Docs)';\n+\n+ value(0; \"Work Date\")\n+ {\n+ Caption = 'Work Date';\n+ }\n+ value(1; \"Document Date\")\n+ {\n+ Caption = 'Document Date';\n+ }\n+}\ndiff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\nindex 08b2a7a822..556fbad792 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n@@ -21,6 +21,11 @@ pageextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n ApplicationArea = All;\n ToolTip = 'Specifies whether Copilot E-Document line matchings are learned by default (Item References and Text To Account Mappings). This can be overwritten on the matching page.';\n }\n+ field(\"E-Doc. Def. Posting Date\"; Rec.\"E-Doc. Def. Posting Date\")\n+ {\n+ ApplicationArea = All;\n+ ToolTip = 'Specifies how the posting date is set on purchase invoices created from e-documents. Work Date uses the current work date. Document Date uses the document date from the e-document.';\n+ }\n }\n }\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\nindex 24013c63c5..2dc0c9ccec 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n@@ -21,5 +21,10 @@ tableextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n Caption = 'E-Document Learn Copilot Matchings';\n DataClassification = SystemMetadata;\n }\n+ field(6102; \"E-Doc. Def. Posting Date\"; Enum \"E-Doc. Purch.Def. Posting Date\")\n+ {\n+ Caption = 'E-Document Default Posting Date';\n+ DataClassification = CustomerContent;\n+ }\n }\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\nindex b97c6db072..14907342c4 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\n@@ -100,6 +100,7 @@ codeunit 6404 \"E-Doc. Create Purch. Cr. Memo\" implements IEDocumentFinishDraft,\n if EDocumentPurchaseHeader.\"Purchase Order No.\" <> '' then\n PurchaseHeader.\"Vendor Order No.\" := CopyStr(EDocumentPurchaseHeader.\"Purchase Order No.\", 1, MaxStrLen(PurchaseHeader.\"Vendor Order No.\"));\n PurchaseHeader.Insert(true);\n+ EDocPurchaseDocumentHelper.ApplyDefaultPostingDateFromSetup(PurchaseHeader, EDocumentPurchaseHeader);\n PurchaseHeader.Modify();\n \n GLSetup.GetRecordOnce();\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\nindex 0f2b7905d4..f79acb69fe 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n@@ -129,6 +129,7 @@ codeunit 6117 \"E-Doc. Create Purchase Invoice\" implements IEDocumentFinishDraft,\n PurchaseHeader.\"Vendor Order No.\" := CopyStr(EDocumentPurchaseHeader.\"Purchase Order No.\", 1, MaxStrLen(PurchaseHeader.\"Vendor Order No.\"));\n PurchaseHeader.Insert(true);\n \n+ EDocPurchaseDocumentHelper.ApplyDefaultPostingDateFromSetup(PurchaseHeader, EDocumentPurchaseHeader);\n PurchaseHeader.\"Invoice Received Date\" := PurchaseHeader.\"Document Date\";\n PurchaseHeader.Modify();\n \ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\nindex dd97e61275..d21ea96b71 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n@@ -11,6 +11,7 @@ using Microsoft.Finance.Dimension;\n using Microsoft.Foundation.Attachment;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.Posting;\n+using Microsoft.Purchases.Setup;\n \n /// \n /// Shared logic for creating BC purchase documents (invoices and credit memos) from e-document draft data.\n@@ -137,4 +138,16 @@ codeunit 6402 \"E-Doc. Purch. Doc. Helper\"\n Clear(PurchaseHeader.\"E-Document Link\");\n PurchaseHeader.Modify();\n end;\n+\n+ procedure ApplyDefaultPostingDateFromSetup(var PurchaseHeader: Record \"Purchase Header\"; EDocumentPurchaseHeader: Record \"E-Document Purchase Header\")\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ begin\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ if (PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" <> PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\"::\"Document Date\") then\n+ exit;\n+ if EDocumentPurchaseHeader.\"Document Date\" = 0D then\n+ exit;\n+ PurchaseHeader.Validate(\"Posting Date\", EDocumentPurchaseHeader.\"Document Date\");\n+ end;\n }\n", "FAIL_TO_PASS": [{"codeunitID": 139883, "functionName": ["InvoicePostingDateUsesDocumentDateWhenSettingIsDocumentDate", "InvoicePostingDateDefaultsToWorkDateWhenSettingIsWorkDate", "CreditMemoPostingDateDefaultsToWorkDateWhenSettingIsWorkDate", "CreditMemoPostingDateUsesDocumentDateWhenSettingIsDocumentDate"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml\nnew file mode 100644\nindex 0000000000..52cd211620\n--- /dev/null\n+++ b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml\n@@ -0,0 +1,200 @@\n+\n+\n+\turn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0\n+\turn:fdc:peppol.eu:2017:poacc:billing:01:1.0\n+\t103033\n+\t2026-01-22\n+\t2026-02-22\n+\t380\n+\t1\n+\t\n+\t\t2\n+\t\n+\t\n+\t\t103033\n+\t\n+\t\n+\t\t103033\n+\t\t\n+\t\t\n+\t\t\t\n+\t\t\t\t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MzAxMjE5MDBaKS9Nb2REYXRlKEQ6MjAyMjA2MTUxMzEzMDBaKT4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAzIDAgUi9MYW5nKGVuLVVTKS9NZXRhZGF0YSA0IDAgUj4+DQplbmRvYmoNCjMgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWzUgMCBSXT4+DQplbmRvYmoNCjQgMCBvYmoNCjw8L1R5cGUvTWV0YWRhdGEvU3VidHlwZS9YTUwvTGVuZ3RoIDIxIDAgUj4+c3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJQREZOZXQiPgo8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgo8eG1wOkNyZWF0ZURhdGU+MjAxNy0wMS0zMFQxMjoxOTowMFo8L3htcDpDcmVhdGVEYXRlPgo8eG1wOk1vZGlmeURhdGU+MjAyMi0wNi0xNVQxMzoxMzowMFo8L3htcDpNb2RpZnlEYXRlPgo8eG1wOkNyZWF0b3JUb29sPk1pY3Jvc29mdCBPZmZpY2UgV29yZDwveG1wOkNyZWF0b3JUb29sPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KPGRjOmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KPGRjOnRpdGxlPgo8cmRmOkFsdD4KPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5TYWxlcyAtIEludm9pY2U8L3JkZjpsaT4KPC9yZGY6QWx0Pgo8L2RjOnRpdGxlPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6cGRmPSJodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8xLjMvIj4KPHBkZjpQcm9kdWNlcj5Bc3Bvc2UuV29yZHMgZm9yIC5ORVQgMjMuOS4wPC9wZGY6UHJvZHVjZXI+CjwvcmRmOkRlc2NyaXB0aW9uPgo8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJ3Ij8+Cg0KZW5kc3RyZWFtDQplbmRvYmoNCjIxIDAgb2JqDQo4NTQNCmVuZG9iag0KMTYgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCRytTZWdvZVVJLUJvbGQvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nL0ZpcnN0Q2hhciAzMi9MYXN0Q2hhciAxNjMvV2lkdGhzIDE3IDAgUi9Gb250RGVzY3JpcHRvciAxOCAwIFI+Pg0KZW5kb2JqDQoxNyAwIG9iag0KWzI3NiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMjcxIDAgMjcxIDAgNTc1IDU3NSA1NzUgMCA1NzUgNTc1IDAgNTc1IDAgNTc1IDAgMCAwIDAgMCAwIDAgNzAzIDY0MSA2MjQgMCAwIDAgNzExIDAgMCAwIDY0OSA1MTEgOTU3IDAgMCA2MTQgMCAwIDU2MSA1ODYgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNTM4IDAgMCA2MTkgNTQxIDAgNjE5IDYwMiAyODQgMCA1NTkgMjg0IDkxNiA2MDUgNjExIDYyMCA2MTkgMzk4IDAgMzg5IDYwNSAwIDAgMCA1MzggMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDU3NV0NCmVuZG9iag0KMTggMCBvYmoNCjw8L1R5cGUvRm9udERlc2NyaXB0b3IvRm9udE5hbWUvRkFBQUJHK1NlZ29lVUktQm9sZC9TdGVtViA4MC9EZXNjZW50IC0yNTEvQXNjZW50IDEwNzkvQ2FwSGVpZ2h0IDcwMC9GbGFncyAyNjIxNzYvSXRhbGljQW5nbGUgMC9Gb250QkJveFstNTczIC00MzEgMTk5OSAxMjk4XS9Gb250RmlsZTIgMTUgMCBSPj4NCmVuZG9iag0KMTIgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCQytTZWdvZVVJLUxpZ2h0L0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTE4L1dpZHRocyAxMyAwIFIvRm9udERlc2NyaXB0b3IgMTQgMCBSPj4NCmVuZG9iag0KMTMgMCBvYmoNClsyNzQgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDIyMiAwIDIyMiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCA2MjkgNTQ0IDYyMSAwIDAgMCAwIDAgMjI4IDAgMCAwIDAgNzA5IDc2MSAwIDAgNTU1IDQ5NyAwIDY0OCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNDk0IDAgNDQ0IDAgNTA1IDAgNTYwIDUzNSAyMDUgMCAwIDAgODIyIDUzNSA1NjEgMCAwIDMzMCAwIDAgMCA0NTNdDQplbmRvYmoNCjE0IDAgb2JqDQo8PC9UeXBlL0ZvbnREZXNjcmlwdG9yL0ZvbnROYW1lL0ZBQUFCQytTZWdvZVVJLUxpZ2h0L1N0ZW1WIDgwL0Rlc2NlbnQgLTI1MS9Bc2NlbnQgMTA3OS9DYXBIZWlnaHQgNzAwL0ZsYWdzIDMyL0l0YWxpY0FuZ2xlIDAvRm9udEJCb3hbLTU4NyAtMzk2IDE5OTkgMTI5OV0vRm9udEZpbGUyIDExIDAgUj4+DQplbmRvYmoNCjggMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFBSStTZWdvZVVJL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTIxL1dpZHRocyA5IDAgUi9Gb250RGVzY3JpcHRvciAxMCAwIFI+Pg0KZW5kb2JqDQo5IDAgb2JqDQpbMjc0IDAgMCAwIDAgODE4IDAgMCAwIDAgMCA2ODQgMjE3IDQwMCAyMTcgMzkwIDUzOSA1MzkgNTM5IDUzOSA1MzkgNTM5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MODW9nYEFJ/+03vN/EfC/wC1cf8ACIPH+01vN/EfCv7Vx/wiC9HFLTNYMWxuxVMjJqiy2qjoJ5oteR76aBkTnN1AOhLdRqEGNd+9i8S6h9v59vcxrLjbrca2G5UdwtckcdRDV07ZGRP+VjkY5ukjgWlvEd4PFBULn/lQbnWuaon243CsOW0DdXQ0d4jntNby6ahg8MVUL3Ds1L2A9ug7EEart5fvVtaJSx21Elxi1+TqaC62qoY7QAk8ravnHbp7TRr3IOtUvRP1U1kvhQ7LX1jg0u5pzTQN0H5807G6+rVBlPFvLW6qMhkjF0xuzYVBIW/9zervTPAaeOpZbjWvGnoLdfUgnPtB5VeB49U0l33izCpz2ohIe7F7Sx9ttpcO1k1Rzmpmb62GE/1haTjuOWDEbLb8cxay0WPWG1R+DbrPb4GU9NCzUnRkcYDRqSSeHE8TxQc0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIP/2Q0KZW5kc3RyZWFtDQplbmRvYmoNCjIyIDAgb2JqDQoxNTE2OA0KZW5kb2JqDQoxNSAwIG9iag0KPDwvTGVuZ3RoMSAyMyAwIFIvTGVuZ3RoIDI0IDAgUi9GaWx0ZXIvRmxhdGVEZWNvZGU+PnN0cmVhbQ0KeJzsfAl4VFWW8LlvqX1PVVJJBfIqlbAVppJUAokgKcjCEoghCZgCgilIQgKBBBJAVBaHIBpXRFRwaVptRntorWCPHVFbnHZp/XXcp8Vuu22l3RqQ7kb0Q/Jqzr3vVVJhcfz7m+lv5vt4lXffufeee+/Z7jnnPqoAAgBm2AI8VF9eG8hvvDX0Abb8Du/GpSsjnbpb9Q4AMhnvuqXruqWNk9paALjbAQw5LZ3LVs6seX8ZgOkQ1hcta9/Q8tD8f3oMICUdwHWktTnSdB9kcACX4HQwoRUbnBbdp1gvwnpW68ruqx5/0erF+iKs39fesTQC5KHrsf4t1veujFzVyT9t/hAg5x6sS6siK5s/tq57A+v9AGOyOju6umNzYT3AfEqv1LmmuXPFX9J1WD8DIFwCvNDPPQMi6MQ9YhA58ChP/i1o4Rw6kTPqOAE/HH8EcmKH4MhmnEVPSZ1TK0kggTk2IL4jzyVm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\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t103033\n+\t\t\n+\t\t\n+\t\t\t\n+\t\t\t\t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MzAxMjE5MDBaKS9Nb2REYXRlKEQ6MjAyMjA2MTUxMzEzMDBaKT4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAzIDAgUi9MYW5nKGVuLVVTKS9NZXRhZGF0YSA0IDAgUj4+DQplbmRvYmoNCjMgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWzUgMCBSXT4+DQplbmRvYmoNCjQgMCBvYmoNCjw8L1R5cGUvTWV0YWRhdGEvU3VidHlwZS9YTUwvTGVuZ3RoIDIxIDAgUj4+c3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJQREZOZXQiPgo8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgo8eG1wOkNyZWF0ZURhdGU+MjAxNy0wMS0zMFQxMjoxOTowMFo8L3htcDpDcmVhdGVEYXRlPgo8eG1wOk1vZGlmeURhdGU+MjAyMi0wNi0xNVQxMzoxMzowMFo8L3htcDpNb2RpZnlEYXRlPgo8eG1wOkNyZWF0b3JUb29sPk1pY3Jvc29mdCBPZmZpY2UgV29yZDwveG1wOkNyZWF0b3JUb29sPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KPGRjOmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KPGRjOnRpdGxlPgo8cmRmOkFsdD4KPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5TYWxlcyAtIEludm9pY2U8L3JkZjpsaT4KPC9yZGY6QWx0Pgo8L2RjOnRpdGxlPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6cGRmPSJodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8xLjMvIj4KPHBkZjpQcm9kdWNlcj5Bc3Bvc2UuV29yZHMgZm9yIC5ORVQgMjMuOS4wPC9wZGY6UHJvZHVjZXI+CjwvcmRmOkRlc2NyaXB0aW9uPgo8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJ3Ij8+Cg0KZW5kc3RyZWFtDQplbmRvYmoNCjIxIDAgb2JqDQo4NTQNCmVuZG9iag0KMTYgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCRytTZWdvZVVJLUJvbGQvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nL0ZpcnN0Q2hhciAzMi9MYXN0Q2hhciAxNjMvV2lkdGhzIDE3IDAgUi9Gb250RGVzY3JpcHRvciAxOCAwIFI+Pg0KZW5kb2JqDQoxNyAwIG9iag0KWzI3NiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMjcxIDAgMjcxIDAgNTc1IDU3NSA1NzUgMCA1NzUgNTc1IDAgNTc1IDAgNTc1IDAgMCAwIDAgMCAwIDAgNzAzIDY0MSA2MjQgMCAwIDAgNzExIDAgMCAwIDY0OSA1MTEgOTU3IDAgMCA2MTQgMCAwIDU2MSA1ODYgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNTM4IDAgMCA2MTkgNTQxIDAgNjE5IDYwMiAyODQgMCA1NTkgMjg0IDkxNiA2MDUgNjExIDYyMCA2MTkgMzk4IDAgMzg5IDYwNSAwIDAgMCA1MzggMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDU3NV0NCmVuZG9iag0KMTggMCBvYmoNCjw8L1R5cGUvRm9udERlc2NyaXB0b3IvRm9udE5hbWUvRkFBQUJHK1NlZ29lVUktQm9sZC9TdGVtViA4MC9EZXNjZW50IC0yNTEvQXNjZW50IDEwNzkvQ2FwSGVpZ2h0IDcwMC9GbGFncyAyNjIxNzYvSXRhbGljQW5nbGUgMC9Gb250QkJveFstNTczIC00MzEgMTk5OSAxMjk4XS9Gb250RmlsZTIgMTUgMCBSPj4NCmVuZG9iag0KMTIgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCQytTZWdvZVVJLUxpZ2h0L0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTE4L1dpZHRocyAxMyAwIFIvRm9udERlc2NyaXB0b3IgMTQgMCBSPj4NCmVuZG9iag0KMTMgMCBvYmoNClsyNzQgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDIyMiAwIDIyMiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCA2MjkgNTQ0IDYyMSAwIDAgMCAwIDAgMjI4IDAgMCAwIDAgNzA5IDc2MSAwIDAgNTU1IDQ5NyAwIDY0OCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNDk0IDAgNDQ0IDAgNTA1IDAgNTYwIDUzNSAyMDUgMCAwIDAgODIyIDUzNSA1NjEgMCAwIDMzMCAwIDAgMCA0NTNdDQplbmRvYmoNCjE0IDAgb2JqDQo8PC9UeXBlL0ZvbnREZXNjcmlwdG9yL0ZvbnROYW1lL0ZBQUFCQytTZWdvZVVJLUxpZ2h0L1N0ZW1WIDgwL0Rlc2NlbnQgLTI1MS9Bc2NlbnQgMTA3OS9DYXBIZWlnaHQgNzAwL0ZsYWdzIDMyL0l0YWxpY0FuZ2xlIDAvRm9udEJCb3hbLTU4NyAtMzk2IDE5OTkgMTI5OV0vRm9udEZpbGUyIDExIDAgUj4+DQplbmRvYmoNCjggMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFBSStTZWdvZVVJL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTIxL1dpZHRocyA5IDAgUi9Gb250RGVzY3JpcHRvciAxMCAwIFI+Pg0KZW5kb2JqDQo5IDAgb2JqDQpbMjc0IDAgMCAwIDAgODE4IDAgMCAwIDAgMCA2ODQgMjE3IDQwMCAyMTcgMzkwIDUzOSA1MzkgNTM5IDUzOSA1MzkgNTM5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MODW9nYEFJ/+03vN/EfC/wC1cf8ACIPH+01vN/EfCv7Vx/wiC9HFLTNYMWxuxVMjJqiy2qjoJ5oteR76aBkTnN1AOhLdRqEGNd+9i8S6h9v59vcxrLjbrca2G5UdwtckcdRDV07ZGRP+VjkY5ukjgWlvEd4PFBULn/lQbnWuaon243CsOW0DdXQ0d4jntNby6ahg8MVUL3Ds1L2A9ug7EEart5fvVtaJSx21Elxi1+TqaC62qoY7QAk8ravnHbp7TRr3IOtUvRP1U1kvhQ7LX1jg0u5pzTQN0H5807G6+rVBlPFvLW6qMhkjF0xuzYVBIW/9zervTPAaeOpZbjWvGnoLdfUgnPtB5VeB49U0l33izCpz2ohIe7F7Sx9ttpcO1k1Rzmpmb62GE/1haTjuOWDEbLb8cxay0WPWG1R+DbrPb4GU9NCzUnRkcYDRqSSeHE8TxQc0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIP/2Q0KZW5kc3RyZWFtDQplbmRvYmoNCjIyIDAgb2JqDQoxNTE2OA0KZW5kb2JqDQoxNSAwIG9iag0KPDwvTGVuZ3RoMSAyMyAwIFIvTGVuZ3RoIDI0IDAgUi9GaWx0ZXIvRmxhdGVEZWNvZGU+PnN0cmVhbQ0KeJzsfAl4VFWW8LlvqX1PVVJJBfIqlbAVppJUAokgKcjCEoghCZgCgilIQgKBBBJAVBaHIBpXRFRwaVptRntorWCPHVFbnHZp/XXcp8Vuu22l3RqQ7kb0Q/Jqzr3vVVJhcfz7m+lv5vt4lXffufeee+/Z7jnnPqoAAgBm2AI8VF9eG8hvvDX0Abb8Du/GpSsjnbpb9Q4AMhnvuqXruqWNk9paALjbAQw5LZ3LVs6seX8ZgOkQ1hcta9/Q8tD8f3oMICUdwHWktTnSdB9kcACX4HQwoRUbnBbdp1gvwnpW68ruqx5/0erF+iKs39fesTQC5KHrsf4t1veujFzVyT9t/hAg5x6sS6siK5s/tq57A+v9AGOyOju6umNzYT3AfEqv1LmmuXPFX9J1WD8DIFwCvNDPPQMi6MQ9YhA58ChP/i1o4Rw6kTPqOAE/HH8EcmKH4MhmnEVPSZ1TK0kggTk2IL4jzyVm3YMcJwGJ0T4BxD10NUjBkqDcqARNIJAZ+KyCEK5nwd7xkAO5kAf5UACFMBGKYSpMg1KYDpUwG+ZANdRCHUSgCZphGbRCG6yAdlgJq6ADOmE1rIFuWAsb4KFYjK323zhf7OPYydgnsVOxI7E/xY7HTsS+jH0YOxT7IPYr/LzPyl/GXo49HtsXeyy2N9Yfuy/289jPYo/E+mJ78HN/7Kex3bGfxO5G+DrG/X/jJR4FN1AJp7LSPbxXANoOEPtMKWN3YPk5gDw29jXDB/lgwlx7IImbETvG10AS4h37YRTo1FuglX+FP8FbrPmA2n0v3AUPwntwzQUnOEHaSfkPWyvxInWklOQRH4OnksnEPwgXEwnuGMRLIRaiARn+Cl/AR/AbfJ7G+h/hW/g3+PI8E0cT1ugis4iPnIYzcOocvFfxAySf2OAduAFuho2wDe3mHZz/08Q52DzJrExjlfXwC9gPV8N1aucjaIPKdTvsg18inoWMQ13YuSyw8xD7CuxwFA7CffAx9t8B//irCT+VF+rUtsl5ZBJKdPASXge7Zi+1oIEYmYIyvxN5EvC5BT5BSSZccotcJQTBEa/HjpEpZA5JR7zD8O/wApa3yH+VbxhYObA3tjW2Wjwu/k54TbTw9wqpsB1eQm1uRVl/DCcg9j/A98Xr4nXxunhdvC5e/5hrKzyD0fLO2LbYY1ADYzVOeAwqoEKuFxvhNswvtsEizForiI3gGYRkYFStxMz152fN8h40kWmYyXbBXCXzw+sp+IVYBRCat61p4YJwXc3lVXNmV86aOWN6Rem0qaGSKZdNnnRpcdHECYUFwfy83EDOJeP948aOGT0qO8uX6ZUyRo5I96SlulOSXc4kh91mtZhNRoNep9WIAs8RGE/cUXdpffnyaGppY9TkK/PZpKip6sScQBQcHq/PLgUD4UtUrKjoj0JSZdRZXd8HoaJwVOM/G6Uqymfb/urFwXM8UnlUyMY/36xIU3RMTb3XZ/sPz2B/GMdE00rrvV5PlMvGv5nYhX+zIlJT1FaN7V6P0jIzCtX19O6PfVyEjVDkDWNZUx8dGa+Gw+cj8ilMTA6dRWYV6bX1mVJLy6Lg7APTx1FwUbQTRZiOTI6O8SMhNoTYbBCIEudfoyQpSlxzkOThS9BhHxWdRwblTct95U1tKNGmxiGZnlAk6pV6pd6aensQQUZ0ZfTXc+v7jIZSX2mzARuANUCfwYgtRtqAU3T2EdMUwgDOVH5pHwc6M4rPQcktp/fyaOimRgR8ZSg37Eka6umPHbo5sQtwWBxKUiCFiKimNKpViJDaoqFIFG6S+sYf6r253wZLGv2mJl9TZFF9lI8gQh/w2eWtddH0yuoF2IRL4d3YKlF1l7GCKk8qb5V6sU5xG7H0lVGlD2tvam1upGZCGn1l2Kcvrd/uPeSJOvBZHrX7o2ZEM199xMP3lrvbJFrt7d0uRfciuQm9XlqiEbiR9N5yH66Gk5Uvn0ZVEhhUG7PGmU1MOaGbIlJ0y5Lliu1Fbo7bv7fXFjWd8qJ2UD84kg1URdnUuJySvDxC2SxfLvXe1MxYvZmxhvYqlS8vozcdiNYP83D0gvryVl/50ILIOAJ89tljvd5oqp8O7O0tpyRGmpB6hWTsGKKf7gmPnyA9pdFQHXtAHdMBrhiKlIXVJhVhAR1GexrLwmGvondEjWqzt4s5PqmXzqjNjjr9Nu8L2HfokvGVNfXlZR7GfZQrrb/smNtzDOHK6sFm4kac3sAxjyKjylpf5VzFClrjRWOdsoG5Qc0jqorPZn3d7Xkd4QpfRWNvb4VPquht7I30x7Ys8Uk2X2+fydTbWd4osZ1PsP3gTZ5oxc3hqK2xlVyKSqb2VlFTGU2au5Cqp0JqjSjOosTnLfJ47eE4TvWFutV9hhaPdk/3Wa/tKNJmQo/kkSqoe+lHr+CJ2oroNkVK5tXjPljKbJYVuD9qcXIP3Sl8OLu8rVYVEFqjajDU781VW3ESr5fuoZv6Q7AEK9Etc+uVugRLPAcgFPCj7hppz6F4j2se7dkS7xkc3uhDXbkra/8Lm0605167zyEVB5j8mbttih6qQx6/LYrqilR1J5XW8x5OhTgPTyGDH93X5GiKnw2kMkEv2WvzSW/6ojZ/VCytP+SZHJZsdnRvBHFm+OmuQS/6pu8VQn0nOG1RMjlKkmk7oC9lLp1PKcLOQeORynsbVetKZEsNAE2t5+cNcWw+ZM+j4NsdPsrha8ylqZ46u4LuJY9XwZgVjlqoP45ajrIC6fWU1kvofXC3zmWAVC61UmVHpcYy5gbCnsTm/thHjWXU7SHJFMWjmjWWimiH29oPt/AtaOHX3RxuReuOhsYhB1IhLst2S129KqUij7qL6FozKSvD+welGMc5V7qVdcNqCfPSgODF7qLBvV9XH63wx6dS6tP9nsTqjLO6Z8a7ASUh2WdSoWL8KfIMa0P9hpQm9CMbPVfTeMKRaX0+csPcvhC5oXZBPUa4aU/ZAKQb6uoPcIQrbZwW7svC/vqnJEyGWCtHW2kjrUi0ApUEZzzA6Ri+56kQwBbWK7AGVl/aT4C16eJtBJb2c0qbTVloFFsoBBz2CEpPKI4tYJtOadvC2tjVB5T/kEEM6UL6kIkzc54+QpsOYMtBAqAn8ISJmImnD0fVsOZ+sqVPH/IoGFsQI6RQeMO8oaXnLah/wgQ4jJW40DR6obi3oMCrcS/hGgujI6kSMb2KSmmveHpt1F1Hw37q0v5E/WAbmklfNrmhOpGnRVFnZc1CT5SEL8G2fQBCj7gOeNBCWsioJbwAvCjqBQi87igOvI6PktfzcoN2rz3ba/fu439/5knuyYFZ4rrTvXcKVTiDAUDcIe7B8Va4MTTCqiWgISYNp9MbjMRotlh5wSRg6mkRTCb0OqE8I8wxiRqO11mt/I6w1WrSaniB4Koarc5osmpEkgn5ODHYhVHiBJETAw1BezDQkO9IKYZASn5JsLg44LcDNtodxX57SjDXtl08hJdtOy3JlYsbGrxeHj/Ey/OjRvs0Wl7cIe9tkblm+UHOQDY79ti1OtF5HymRnxf3nLmffDyhsmSKnEbfd2egRHYyfi4JpfAOImrEnWENDyKI3KZcnvC8XofrBhqOBfMDASihlLhL8nIJiod+hJ3yMvkZuU3oFnZ+t1LYSbR01m046yLxKNghL+QhepdJsAq7wlYbSq+HkCSTrkfS5+o5PU6bj5MfgxJ14mBertdrL/Blalxs/uCEoGQXFskvPlzXKr9AJgvdL5NFXMUfN0UG+sWjA9f2yYsAhTcj9pkwQkjF9VKgITQRRAIcMYmiyJMU8kA4xaJLeWBGro6/O6xLtjjvCVtsJRqi0RD79ZIj18E5HKkppMcYYMQ0HLNjgZyCu8SPBQrfAcXuQF4ulTTxJnvzJ7o0vkwoLIBgvsOVTanVCiMGmmxE/+iWWz/5Vj5Oxrz/0dfybw/M7jCRfX+oPjKbJJ2KkXHyqSOX/W7TYiqhWUjxI+IBcEFrKMQbkgycCdKB4wWn08kJJqeJA71NzxlFlyuJS9oR5pIA7Ys3Gs06846wTkCfYcw1ckZjim2jGDhG6Q7G1RNAQlUIFUWpboArGxqyNT4J7Dbw5qfYR1EJO5OD+ROFR+4fkJ+UryePktq3b7+9/9Vvv3zp2fuDs0kPKSX1ZH+h/Mp8+fCb3zA5F8c+4w+jnF1oNztCFTqtW8vpNakazpiWQvgUYuWNKdPDYLQZObNoHJFEXPwIccTdYTF5m9VqTjLfE06yWY3JsE0iuYQjxGtNu14XOFasGNgQA/76UFKGNWAtsV5uvdLaYd1svc36I6u+wROmSmGWgkaJnPmBspebRxY3AO6CQh8qZlShLZsqRVs4gVqPWKhVWJ3AH5bfE5a9uutfSIQkP/mLn0z702LypPybg3sqQ+HOnfsfvYWMy8l+ZOXxzAK58oVyt3P9hPJr4ta8hFmXYs0Ga9yeL2TNColnW7NLseYl8os/rVnOrHn1+6SOKz5OrVmAB5+WF6i2fB+uZgQn+EO46q4wJGtMu8Iam36rlJSL5pCUbN3KK0o/phpqXq4oUYv05oPLCTyuaAvm223cyhjIv0Vh8zGSKb93pvPa45+kkoxTMsmQ/3g0Jr/Ph/bcIh8mAZKhWqV4GVplKiwKBcFgM3AaPTFyWmIS3Ck7w253ko5LugONkdnhHWiHKSkum9EIm1wuT9wQjxUHqMeI67JE3T9+xRaporI13kRL5BRLpCISL3tb/rW8T15Nfk6WH3ls34lXBj55vrtM/iO3pHED2UyqSQ35aYn8VqP83Qcf/tVL3IRTNcR7BQf65EAoXevSWQ0lGE3NNglymWs1aHokba6W01IVKdv79Yb8EurHRiVqJz+F9xbPXtbNlFP5q/x07pOMu/9JThHgl2+acJ21qJsa3HuKJbh4k4h6EZNt6NyZKRiGlqGCCEJJcNBjKtYp2XEtJxpjIfrOGvlFce0L8n1k0v55LWTSff9KHueWDxw4vL6Fm4V0b5PHCo+hJdjQM5SHxvC4otWFZpcsWDVp+rRdYb3NtFVy57o5t3ukxsH1SHwuz/GUx/y4bSiGGKch2zfIqcNl43yZvLIzCm0oBfKiwPhe++7Lhwfefmp558L29W9Hrlk/cED8zZ4n5K/+jKb0KldQs/z6f95NLDupP3gYd8YzGD30SGNxKNMI94eNRp5z8Ib7wzyv2ShZci2cxeIwkk0Sl4upjLpF4maLIDULSpRkd4KXtwelwgIv+Ux+lpzmRsqvyGf2bCacLJPjskPcI098X/6a+7k89eMPqdZxdf40ri5CV0hPhJ1h4uB4wNz9CbtmDnva2PPzJyzq06w+Tez50RNG9WlQn3r2PBSy6LNmAGiFTYqfUtTpj180WrGdjR/+9JmfklIuSdzzXbtKk1aDNHlgQkga5Zzg5EYbyBgtsTscvJAGmwgZkWS2bZHsuXbOjvMWM48RLAZmjOipxxJ7wUSM4cRLMJYnM9MkySnBCROJV6uRnzfpUp1yVP5W/qklQ2+WPySHSbbPpvGMJNnkdX7BTY/0XHomj39x9I/f3XvmM4z2j7UsW1/PV1PaFsU+I2+QPPQs7pAFNNGFkKR/fNBmgDkR9J4FaB3JLqeGOKpaV1TPXdaW2lgxY1HD9JkNqnfqwMhugxFQFBrJe0QP3QHEZXEZ0TaNNivYCWy1WDLcW3WKOwgGB8M7e8S3QibHImgKZluksGAwIk0QOuQXhPa3Dn1JuLdeqhLIZPnV7oa2dWuaGzfcso9Y/yaT/Fu5yBnNnKaen9y+/Y49QGJn5AyhDvelExaHCqy2DBtnFNAt6ZxiSKPRmXjdrjCf7jRZRWLMN5JsjKQ2m8mpeodk0WwKBNWkq9gebGiw00iUH3dcaa/baTP6LtQQ4byZowupu0J9JDG9JAl1cuNd8ttds0pmXZ07QW4ki59zGAS9+3kBvntMXp12JrtrMy8P7Lj08kvncKtVf0WeRynykBwyERcS0TNoacwS0Aq85Hm6HRGLwLto6SHxIJjAF7KT3hCmm/eGeZNOx5m0nBtHoJwxOSRI7DFlP1l4rX3ChIl8SH4xbXr1/HHXfFAvHjxdIcxPGetNEYkhq7MUea9CbZagvx+JKWhNaHwG9GL6beTN5oKxva6QVuvKsf0obIYcYuJzcsS0tKzd4TStaNgdFlPVuKOICGXDVg8G0mxU51g/hnomTk6Deh5tp2qdOBrBHNT5FC6YP5LLLshB/2NB3z8S61M4oaTux5/vjG5e/aOH+onmyn+r37XyslnbDq5ee3Brufx8ev4M/9jy/PT04Izx48ryPLzjOfmdNzuKiDDr929zt0xb+2Bk9cHrZy7cf1o/MVIxNqukPlh0xeQMb9FslF4teikrcpmFPI4jxHOjxcKPSkrC/B14YuZ5Sa+38MkYVZPte8LJWjwSAErXHfeeShhDG0AjIJS1tGNBFuGO5QeURJjyNHEKz4wYxU7ZczktnNbCk59xjWcqZnVum1xy5VSpdcVTjz7955U/u6rksuae6bnhsjFEI59uX/X4TSv8l9TMrQ0sWryTJG8oXn53w9I9m9ryMkunTlHzj+1oByb0sV4iYv6hAb8JYzIBQyYaNGaBFpNO6JHEXHZ+QPdPjTn4EoY6jHQsDxlLiE/JqNGxCNvlbfJTircneWS9vIOckQXx6JlJ5LCcgSuOjX3GnRAnQhIsCRVZ+QyeM2qS4K5wUpJdy2FCwiUbDFqLxqjVau4Ka60A5gDm02aNUWftkQTSKHQKnBBooIcGPDY0BOKZHZ5hzs0IsllU9BUGC7PtQZePRseJ3ImKW+QD+/aRSZ9+ujm/0JRNFpL3vvhwgfzKF/KSvSNUbyYUoFYL4eZQ2FCYVsjxfqIdS8RUVyonuJ1uzmglegsxQBrm1ZBOjBp9jj1LSA6mZSRn3BlOFoDYCKfniRAU7gwHk9LScrI22knORklP9PqJ8Q3JwpXtXXoqYDZve4ml1xSw4xlN4YHm18o10Z6cTO25EO179KhRirknp9hz+Li1p4zkqXVgorrkitdaL1t42cjc2jXTHvnJgntfW9P5s5lZ8xaEx0xcMCVzVEVTyfwblxQsvO+NrnXvTSShmTOTRxdmjJtWVOCpePW2zh+35nnS5fdSR6WaXKMKvVnFwby0rLktW6+46qHm8WOor8b8oYPlDyNgUkgyu4gn7q+tVsVbmy12nmYuQ946Jajs7HiaHWQmrrhrG3PXhedx1yvefP7PhHvjmQWKu17YdtXaxU0b5LFc0z5i/hsBkn/7+oEvappu+MkdW++8CzcYzRwOY5y04olNwn15ic5tt7sjYbs9lUBqJAwOYouECa8HcaPLBaaNI0Zk6u2pmxSfHU9xGMX24mG+iD3YGT5fwCimdSVjMBN8mFpgnlMQf47yPcwZThDu/qt3/0L+9OSRW5u6jm54vHPzxk5xT3Rv92OZQtIz21/8TNgv74/Me2DgGfn61gXzl9CcpwON77fiZxhFrTAmlGx2WXA7Ll2oAT2v5009kjnXzJmHzstUlCjChLiaRCN6dnVLS/Xc5uZKtgkfvLJ8+oIF02cs+m6xoMYHzR9QcyOhOVQMI2wjcP8Rvd3lsKbjuSPdluY0uTHzdNtITwgsOrt+mtPWg4HXwNvTdD0hfYak7xmTq8QDxRvnY8V2Mk1NCalXo4QFg4r5JpxSEk8rNCGmRxbNH/AAXrVEfuHHcyOM3ry+tsPVaz8hVdyMP1zfNPArrurwllUDLwuwt2bZc8/JTexMjjF5NfKQBqPxTD5uGwZiXncXxmFztjWbZrGp1pQMV8ausMsmprg9aIZG41gxc6sDMwbFEANn5a+DZ0N9riakqdY0agQ8EebmZeNJQg0yhYXfZ6mr8aD78hsbHvjx3qjQ/s4LnxJ46+kGarG/7lrUdtWapUs2rJU/kV+eRAyLHt0xdz9xfk4EZrlH50ZufHjXll13o25GxzgShTNow66QHlOnPlTYKxwNBscg8Drm2LwviUR3nmo5I2vIaarNRrT1CrR1C4wPucQbQ0bQaNCZg8lsNt0bNms0bpYgodmiwgJ2GspZGNcYOK13Qho3kb5nqWi8p7smTX4yfdGGnTUDLfynwpGfyW/Jh+U3ov9MJhAfcfbQsxCH0gahia3mwgzNY9XoiHhTyG7Bk5xNi+FcsFvQbVuUVVneEGQmQcN3MA3ZcFCfxjwxDW1TeEx0MJ3g+/fvlz8auK32wL7b8uXHyXxfzYJFmF9edVT+gIz6puHDL4+1n7mKfD1123UblDxYnI1U2GBqaMxYGym2kGJCDBYbEUWd1qHjrdb46cxh0GxKOJ1h5Cqmqi9RnCtLiWkqrL4PQmqIOFtulReb0kQ8JpSKpnRyM7lONnEdjssGpol7BhakF3DzB+qQittQFgswRnjgqtBUSMUQkKJxIvf3hLXaNJPVsjNstRI7l0bS0Nc4TPZIGE/2yRprslvC0Zq0NELAqXNvkYRcFtBwU+cHA9Q8MSwEA/ENzkKbo3jwVZES6uJbq5BaJUY3uv/Zedfl8uLHqfUKC84UPr9//8k3N69Y0tFPTPLJe7iNnxQc7j789Esn82R52qcPHJ7f30Rt6FaMdknsG5SLQgVms/NGjSbN+qUhBECP6ZIBfY/BrtuN/jPFmMLvDrPYZuAJSUk1Wu4NGzUKpUHqDOJUEpa4xXM2ls1MVHZRgTdTS90Ur7gs8GXeunPfxlvkdzp2TOC+GTjtnFP04Wn5P2JvZBPLgvUt79l5SZblP2o+f+GwfAx1Wo7UzkO56/GkHMQT+Y1gs2FOzttsSaYbQxzLILVgQTLjeSRzVWrmSN9l0LcDtOAz7cqLjHIZiItoyUn5q7+8/soLqdwbZC3ZPpAt3ylfK3wwMCB7yElykn1/VdzX8tDs8LNXWid/DR4d+3rB419Pfpw+f++9K/TdijO3WmXDUsTV46184xVL3YMDMoD15HcrTr9mlc/5JuxocRzsE/eCgStEq4pChvAWbBPqYIYgwyyhCoqF32D9CMwQozCLDyD8G1grnMLnl/CwkAIPax+Bhzk/LBJO4piq2BmuAvv2wLt4V+FdK2yAbfwIGCtcq+CIXsSvgA5tHeJhHceORrxGvEeLeTjnHrgN71vxjn8/dRoy4lDvVrzfR4fQS88OSPEEvOmulPDGdg22aR7D0yoeDbX/jtxjcNMh/3qcQ4/9hhvw7gcw2vA+hc7qSczyxuD9GoDlOMoJ57WV4f0IgB2Pvg6EHevwPgKQtBzvE3gcOwjgaqXfHWfSHM39C8b6h0GLFmKDAFyP1L1tWAQC653Fb8KSp2xwTsYNz/RiYzUKc6DjslSYhzRuvAoLCbAIbpSZAmsQXqzCWljDrVNhHYxD76jARpjPfa7CZouGn6LCFtbOAxF4XNdiL1NhASR7DYNF+q8B9jUqLEC6/VoGa7BdY79HhQVw2x9gMOVaZ39ShZFm+y8ZrMN2k/19FRZgpP0Ig/XIsNvBqbAiBwVW5KDAihwUWEiAFTkosCIHBVbkoMCKHBTYOMivHuXgdqapsAVmqe0GKofMfBVGOWSGGGzEdkdmowoLkJWpyMRE6cy8S4WRtkxFDhaq/cx+FRYgM/PXDLaxeb5UYTrPGQYnUXn6JBVGefpGMdhJ6fFNUWGkxzebwS5sd/raVViAUb4tDE5m+PtUmOL/nMGpDP9dFab4Cr+eBP16EvQ7gun3SRWm+lX0mEHxsywqjPhZbgZnUf1mFagw6jdLkds4Kp+sxSqM8slqYfAlbJ4tKkzn6aWwLkH+ugT56xL40iXwZUrANyXgmxL0Yorr5VHcl/kYjfPxI8EcaIOlsAYz3S68W6Ab20oRWgOdrIxgSxtCqyAHe6ZCO34wh8c2+kuFbhxFa834bEbsdVg2MUwzfmZgbQm2NsN6bLkcZ2zGeepgA4MkmI2zb8C517JV2xFaxqiR8Ka/fNiAY+PrSIN050IQoVGDtYkwntEQwRk6EVfCdSO4Dp1jKaxQcWdhrRVbae9apLFrkKc69ouLLkbBhehpYbKQ0Oe2IUftrDXCJDGcR2WeDpVTia2yFnuXMn7jEl6PY9ewlrWI1cQkJ2F7K2ubAzORJiqdNjZuFZPtJDa+mWE0w0pcs5l9F56WkkpRHFdi7V1Mr21IS1yDQ3zQ/m6kog1HdqEUatkvTzrY2Hm4/jSE2xHr7HZpsGc+o7prcOZCnGUClkMjKP4l551JkVKE8bxG/d3LSiaTFUx6LcOkca59LmP1tchZHJvqeiXWqd7bGO85zGq6sa0LLsX4E8BVqD3QnpXnzJmjzhBAeAOz/GWMMmpPG7A1gvJW7OJ89HQxWjqZFhR9tDCpdDP7CrOREuNwA9O5oqPuQbuLY9O2DsYNtQ6685qZbTcxvE7VPscz2a1i63QyDStjl6qzNKv1CJu7k+mJctzN+uioJYyOuITPtp1udYRiyWvOaWkZ5GH8D9JWJ6s34ZilWB+v2jH1Fcq64wfXOZuDNmZZ65mclrKdfT6ZrVc5bWN7vp3t7rgXOlv2dEw7g8Yg/thhe+n8sys0/L2yTdypdKZl2LaG2Wc309zSwb15Pg7iq59L16QEG6CcKLx0s/XifnsN290bmP10oJRWMY8WuSCniu1FhlmV4pk61FLhSoHXsr2leEpKbVyb8XkoZjvboRe2USWirFI1MzR7fIe0qVJew3w39bxtqpxzWHypU6XcwnxMO+MyLuXhVj2eaSbC4CbVDs71uGfvhDGDPkTxIM0sYqxnv89rY9qnWo1gG5XQMsSI9wXUOa88y4uPVXfvkLfoGpRYnJr/nzj5A+OSlH7WHLPjc0gjBq15ObYpeopbTTOL5+1qPBuy7u+LtXGrvHC8pZqrHtw5XQkxRNG3YgXN6lqKH16l6n0843mNGgfjvr+VWfsyVc9xO1bsqlONU8oKHTirEvdWDVpKBIbyjbP92f+ALgYlFGG8U7m1qb6+Sd2rS3H2leoeGcq/6Ap0Rys2MyZO44V1i3Dt8IwDtT02QUZNLMq0D/Mz5/L4PfMx79vGxsWxz+/dxp/l3eKyP3s0lZriTxP5jtM1lA0O7ZqhSBTX4Xjm7zvYKi2D9eYEC6F+S9FQF842FGEVqpcwWprVSLV2UJeJvkTRYUDVeBfbJe2DNMT39XBb+uFSTYzwCpeJkWa4TQ9JYj2T48q/U4/xaECz1VWqZJoTKGhiJV1zSC7LEWNpQuzo/h5/rHj+JsZBPOJdOsyLKznWOgafL/9fxWJEPMoMySceyYZklOhTho/qYr5C0dUSle/zx9zIBTS6ZpD7Lmalq9jsyi5SIm9iRP97LSAe32ZAOeu9HCqwdgVGyxrWMhPbJPSiNdgzH2tl2FqGLaMRo1btH800dQWLQzMQbx6LccocNVhWYT3MfFwFSKxOa5WIX4Vz0bHlUM/WKMfZahlmDZub/mJ9Nj7LVTw6ohRb5mGdwtOZF1TWq8JRymlmphoTFUrrsF0a5HA4VTPZinHK5mCtBuefofbS387PZPNR+un6FQyuGqSzQqV0KpMRnZnOWYoUzWY12joPn9WIV8vWn8p4VqitYjxUYL/CSzmjgK6co/Kq4FH5zFd7qI4ofbPxM8TVVCaDGYyaIfmV4rMaKafzT8feOhYhLseRZYzTWia9clVmlNvZrDbElaKpUsYNlSqVQRnCc/CePii7GlYqtNQkzDZcdlew/iEshb+palnKJHc5qynaKGW1OqYr2jte1WUN4+PsVa9glljOsKYyjmsHLaSCWa9Cfdw6lTUuT6BEWY/qNpGWuFVL37NHlFni/fNUTZ8rFyr1qUwmlK7awZUvNDPdm1XsNLtGPUWfe0oe3l8Ha4kZPcIX58Ec6qtg/udcDKW9gs3VfYF+7OFv4J/lX+Cfw7LvXKxhvf+oN0AGdl98C/R/5S3QxXcbF99tXHy38b/h3YbiOS++3/i/+X5D0d7FdxwX33FcfMdx8R3H2d784nuO4e854tK5+K7j4ruOi+86/ve96zAMvs1o+y/edij9NCOk3mcdy7fo/1x57ohzcaazHKjrPLjxngr4Ar3PCjiFo77AtvO9CRmOER/ZBcq7k47vmX0IZz6DzsVU2mcwH7gOvdj5sYb3V4PyTYK1LL/vYPnauWPOh5Uo0/PRPaxfyBCmCJOEUmGCUCSEhMuESqH43DHnxaqk9JI8XPPcNYb6Kpm37kTZno+WhF5ig495H0anc7AGe2arecv5LGmoj1e+5Birov9H7LnXcxAQjgGBywX6k6mQ8OfQPL25+A8fJaekv/seFtdcm+y55trUt95GeN16LFZ2YtHegcWKVcmeFas2r0nrXut0pS9bjkVLGxbNrU5Pc+u21WmpXclXl6Z6N+AdmGoSPoWASL+v9pHwDS6llJJw4gmzvTjUL3x5wOgsfip2SPjqCU9mcclUs0C/l3qb8Dcsc9XyK0bi508YbcUlz5JpWLOSqbCXTA2ZuW+/4fxfnxT9J78R/P2xQ0984/MV018ljvgmKbn48894/2efcv7Qp0mu4oLnSe3/4/w1eJc9SzqgDm+OdJD2A7GMFc+RVUDISrICCfWTdrLiAO+vPIhVQjaHyu4T/D/aLfrv2y34793N+ffs1vh37zL4I/cL/vt3cv47dwr+O3aI/h07ef/OXa4M21JpKTf9Ac5/zy5rxt27eP9duzgk7qOQZVf2mOL5u8gru8jfTmkZvadSPMXsabEWP0XaSGtoHO//c6/g/7KX99+Ezxt7Nf7eHr3/us3Ev2WT4N+M98ZNWv+mHp7NOWmJO7V4SQ/x34D3dryv7xH923o0/q09Wr9noss9weUqdDkKXNagy5Tv0ue5NLkuPuCCHFfGVBO5HAJ4c2QWqQQXVBP6G7BOMisUICf+Yj3+leXoMcuK48R4fNLxyuNPH//uuGg8sfDETSe+OyEc5WMZo0Zbxoy2jtK4/U+RFrIslGQd57eM91szfZYsn3VkhkXKsB4kEbKEdIauNFltdpPeYDRptDoTL4gm+M8xMvGwMUvI8zPbM/sz32dmmc9wn4FJmlGWV4JdildUQJxXiEWEV1+aUcdGy0bDRs1GxUbJRsFGzkbaRsJG1EbIht+G04bNhtmGwSbAOIRxg5A3g3eI0wZhoFe8g502GGt772BWCNpgpO29gTMgOmIjI2NfJFB0A1PHDkaGkA0sHTuYgJSQc1R0xA5GSZB0q/ROYIwzbPBOaO2N1NaW3ZACOnmmQTZygxGIMUE2ksF7g1HgBmllJ210UAwmitFEN2qouW7Qck3coOOa4AJWULLhjeuGD66ZiRs+KLtseOeaCeQkbHinDJHVRjKAEcMO8I7a4hKEfUiWF0MImACQWwx2TXEJkNwgscEeGCaYji7eyAkKn4AgJ+8NHEFAHBC9QUoZyDkB5JgBOTzKTsDyAgAJSmLADQplbmRzdHJlYW0NCmVuZG9iag0KMjQgMCBvYmoNCjEwMDE3DQplbmRvYmoNCjIzIDAgb2JqDQoyMzM0MA0KZW5kb2JqDQoxMSAwIG9iag0KPDwvTGVuZ3RoMSAyNSAwIFIvTGVuZ3RoIDI2IDAgUi9GaWx0ZXIvRmxhdGVEZWNvZGU+PnN0cmVhbQ0KeJztWwt0VNW5/vd5TCaZJPNIJg+GmDM5JkDzmMAAEkAzJJlkYiCEJKMzE6ozeZEoCSEJ0NTLNWpdQtD6LLaglnKRq1TtCVobfFWrt+q6YqVWW4sVl9VqvVrbitYKmbn/3uecySSAS7vWvatdixPOOf/+997/4/v//e8zZwYgAJAGo8BD0+oW14JLoucvRc7reIY7+iIDwm3idQBkOeV1bB6WXIeLtwJwOXiu7B5Y11eQ2bYTQOgEMFrWrR/p/vsv+1cBpA4DmHJ6uiKd2w/c2gaQfT3OX9yDjIy/JH8d289g+9yevuFvhIlpO7bfo/rWb+iIAFyBunN82O7si3xjgHva9Dy278O21B/p6/ro6MbLsf0CQMHPBjYMDcfWwBaAZTfR/oHBroH2VZej7mUK2tcLvLCElIAIRnGX6EYvHOqdPwLdnM0ociaRE/CP49+GstiT8PaVKCUZT1jVIkkUl9ik+HJ0DUkz7uU4CUiM9gkg7qLaIBuvBHGjCKYi+yW8lyNfAAteS6AMVkAVVEM9NMJqaIYW8EMEOqAL1kEP9EIf9MMGGITNsRiT95VmxN6KvR37Y+zJ2C9iz8Yeif009njsUOwxPH8cuzu2L3Y//t0V2x/bGbs9tid2I7PxKx3iB+gF9TQHutl12iEA5MI+gNi7se1TV4DovNinX1XTFx1GnVgLYbx+L6GrlV2/N214B+Kk94a+QGx4hhQ8ok3RxlPGtcLNp+HdcApv72mo0x2tsDLhqh64OmANo6YsHsY4q0cTeq4eKzEfZh5hTWrCgbHKhUzOBUGNgbOEnbGPOcxRLjE2FNFWwQ02uBEpHBX7kM02nTwZ+xgaoBb/PLElKD2M1vjw2guroNKwRzgMVjo6SvHei1b/IGrGmf8BDpYDPbAeeVgP4C64BO6AS8RGT11bKBjwt7Y0r2la3bhqZcOF9b66Wm9NddUKT+UF5y9ftrRiyXmLF80vd5WVlsydU1R4rlzgzM/JtFrM6WmmlGRjkkEUeI5AiaSQsFfhCyVrbUT2yhFfaYnkzempKS3xyrVhRYpICt6EItnnYyw5okhhSSnCWySBHVY8OLJ7xkiPOtITH0ks0nJYTlXIknK4RpYmSGhNAOkbauSgpHzI6FWMFopYIw0bTifOYFZRayWvUru5Z8wbRhvJuCmlWq7uSiktgfEUE5ImpJS58sA4mXsBYQQ317t0nANjGlWLnnojnUrTmoC3xuF0BktL6pV0uYZ1QTUTqRiqlSQmUuqlpsMOabzkybHrJyzQHi5O7ZQ7I2sDCh/BuWO8d2zsOsVarMyTa5R533w7Bz3vUkrkGq9STKU2NMf1NEypJIpYaJGlsU8A3ZE//GA6J6JxDIWWT4CSCletkOaAkx6OWsR6bKxWlmrHwmORidhouyxZ5LHx1NSxAS/CDU0BFDERe2SHQ6m9PqhYwj1kaVBzvba5QclY0xZQuMJaqSeCHPxXKTuXOJzW+JimM3UDwoLgIMJOJ4Vhx4QH2rGhjK4JqG0J2h0HweMqDipcmPY8qffY/bRnVO+JTw/LGNuGlsCYIhTWd8peRHxHRBltx+y6jAZGtijpnzqc8pjNKlW4gmyshFbVd/ZKiliEIOGsxAmYN3TKmIU10j9Vbx86UEGR1SZVyCiGyvHK3rD2b3NPDgqQEGhfsZoIrQHFU4OEJ6JFzDte7sIZkTAGrLeGBVNxyQNKplylDshBu9AF5oWKW31nD/VFQtGXIaD4L3K9kirXOHGMRVZSP3Wo4602alLwBZrkXiWzWsGnBE2L4vKydSh5x2hmftnQj2Lor7o+2LMU7ZTXBA6BO/bm+ELJ8aAbFkKwhgrOqsYMLvKOBTq7lfywoxPXdLcUcDgVTxBFBOVAV5CmNKI/700HS7wgy8PWQEOL3LAmFFhC3XboHVScUOidIUYOOFQxmNyKsdAoBTgHH6TuI0OqRUKuWk5BSCo04mnBYDIuXRRVy6UAcYA+Gs1Q5knerhptHG1PEypSyKt9ujQDbaKcap/DGXSqR2kJh92SphhnGGkx8OldWAKxw4hxqvYxFsU9h6IqBeQuOSj3SIqnKUB9o/CwiGhgsPhoq7x1WisBLIQJnNitNyiYSm2xIxFcpY61403fjO56vVsaM8oNLWNUuKwJBLS8XgG6PDxLrA5WZ2jGyFjXJQvmDMuYsXGPh2YLTQ5pTK7vHJNbAsvZaKxVWx3fpLps0EAaWqtKS7BsVo3LZNuacQ/Z1hIKHMIHGGlba+AgR7jqcFVw/FzsCxySADyMy1EuZdKGRBtUUjM2jGy845AHYJT1CozB2h0TBBjPqPMIdExwKs+iKipiijzAYY+g9nj00QLyjCpvlPHYMQ4UMk+K6DF6kj2pXBrnGCeUdRA5j+DTWzKBB1NJGnGM46xmxp4go+PJHoc6YhRHeFQLt/mnVPtDgQdTAaexKyqqogemS04PBhu3LK/USRPl34I9Y+EgXWyQpa5/ohD5AgyTfAEaYkhVUuSuKsUkV1F+JeVXqnwD5SdhipIsgtNHMfZNCqEZ0BZw4pKUZj3vGLN8SCMVxII1ZnmnFI3bj08l3xI349NzEuR4knlRAC6J4GOla4HL7SL0Or/cbXVaC51W537+jZMPcw9PXihu/nzsNqER5y/D+YfxaSUJn0XKPTnWVAsvQFJSBi9YuHAwVbRYRGTYoHJBZYXLVlFMclxuq9vltmVXzC938k5eJm5CiuYUzZENSbxTuGTf5C37+ri8S7jsyddMSUlGwWr5CzePPBGtEnd93i0o5+Tl5lbNm1yH0Z5QP0mg7RmeZLARHvhQCFzFkFNZSY12Wyc66CT66QCfkfkJIRctcXtmmZKMSXUhI9jqQmCC9HS+KZhuSTYbwU7trCy22qACDaXGFlsJAuC0WpwFBrtVtrrt7sXuBVl2K782+ultT6xdKwz8ab/CtZKNr+2ZfEiAR17+3eHJm6nGTNS4A4E0wSyPycCZOANJ4cwEVVS6bRXEhWigYOp+VrZ78Xl4P94aHV5H5mclC2kWsqxTgJNHlpVXzuXdiHMo9q4go/0m/LQzz5PFm30h3p7sC9nB1hSELENqU9BggUrqe7Fu+vxysQAWLQT3Aps9E3h0IDPLvWDxooVFXOWb0RPEeuxoNDr52x//+pcPH3ru2Vwy54MYkaJvTX4U/Q3/xvHXnj/+51eOvo+6r0V38ukTKZjha6g7+cIQz6elpdeF0sz2NLMBWoIGXtVdSRhiTHlGQdGihQysTAOPwThyTpkrL99VtmqtyJUUOOfNLZDKPo+ilxQt9I+vRP/sUOTJgBTR4guJxrSmoNHCZTQFuazprmFICg2y5ly2vUgu4Jhv5/HLBu86EgMivbWpv/+ah948fM+uwdJakv/ecXJeeU9NdPLFZ/+Kj9gMT15h+ZALjZ7iDCvqQ8W5plxfyJQLTUFzbn4uZ+Jzc9ON6Vk0P0SjEfPESC2xgjtHzZIc16WXfF3PkxzXrBeo38wSO9rHWRfaKPj2OUVooiHpkacP3Lfv+8/8/HjshZ++EDbcteOmx7PIyZf/dGX7RjKb8G8Sd/T4e/Nax5956iGKSR/GfKN4EDEp9WSLlraQaAJTmjEtHDQK9gwuIxzkMqasATcFhgKP0EhgtYCTQcNINEjY+MDj0d9GbyC3kMV33377f0b/Gn2AVH/28ztdPrKDXEC+Tu5e1FsTvSX6UvRo9P5ViBGuL8GAcc+A2dDiKTZn2DNSc1PbQpBrNyQZQqEks10U7eEgiMTEi/jp3piJpvFJ6nJPwEdfTwwjN71ZWfLzCIuMi8rJciTJnpWdQaxqhsr8zp8u2xw82EG+/cRrB/f417wyaf/bvqce2Ev2XR2cvErcdfie3S+dIxTcHz1PrJzcdd/O7bvRYkRMPICIaavEntwWsvPmthBvSA0HDViH0NiMU1eJiha7kgIGF6N5A2JxOxkiK0gBWRe9Kfrq59HHyYIYSSGLo0dyyW2kmlxM7owORZ+I3hHtETdGdyJ0v4n+gLSRxaSc+NUaJRxHDDOhxJNly8D6ZDMZk42hULKQbkyx8WBEsNy0IlSQOEAIDZbEOXIWqzi0PhQtwgUkPHDywKzMNIHrWMk3zXaKYodwnSxnzio8cYm468Q1RYtrFwgRLHcE9mPmbEetaVDoyTBBKGQSkkIhIVXkuWQtaxACN9ERIBanZEUN6k3YHuWijnayk2xv586fPMB5+KGTu6Np5B1+iOblDlw7VyLKBVDjkVOz20KEpNpseYa8tpAh22CWCC/x4aCUYcs0Y0KYhcQctVJH9VRQ0/W8RVpVwlXCCgZb0LRYZWfRvJALinbsuuueBzY9/dvhD/5rdPTfb7zlh5t+9vy17xy58Cn3xvYdW/uv2XjlDwe++6vinorbBvuvHhgcH7r7pTJqqStmJMXwe9whsjwp/CjxJKf6COaJ6zC6Puvw/PJsOcO9tXFn92fkKJZrGi3+XcTNjPmTD5d6FhjtVruISWTPy8PEz7PmQi6G0GjNseagZ1bMe6sVCLGEg7j75GJ22bTsOkPy61cbqWDbqp74zE819y1OHvn0PkFG7n3u2i3fue/9Z6JvPXfHY9FffERS7n0w2ifuenjn1p8UCemHbvzxO5j+r+zZTrjJKyb37P0Omaftdtx1QiZYsF7bU3Cx1oWSICXdkM7RSmY0G+guFN/ntE2OMNS1PY6Ggbuu7IKRfZg38nc7K0r5Pc7P/xDNF+D3m662qToMAlZQCZo9pRkWq6UuNAszuy6UnIzPAhJurXlCUzDPkjkrOzkbt6dsi81ssSfbgenWtFdMLURbBbND33AX6tbM2Hmz0TRMUvGekWtGlLXRk1v34x58+YsD359d/mAvaeJ6nrrjpTsn7+E2kIuO7J88KMCBp6/q3XBFNDx5Hav70Xz+12h1LhRBnadoVm5dKCdlllXyhQwGa645y5SZnpnXFMy0pMsIVRZvbArys7WY6nFFowlNXVpv6WIttHDOgjmYxZJ1kUzLvrotuRe5+YVaJtPA8r8+iY8Md+69mdwjjHz2+EeEe/mtbmHt2p/ceu+Lj++++5mV0WPR443hEHny2iPE9sknZPGje6Nbtv08euSXf3x1t/4MI36AFQyfYVJVrCEDgU41gxmxNltSIPkLnmHikOKjkf4Q863rv/UcAjjy7v4HuO6H733xycnnxQ8m1x559bnJaylel+Fa70S8snG113vmGB2+kNlsdAJk14VwNypoChKTSTRnZOBenWERz2kKilkswipagIUtx6U+9mnVjS55J+JE1/UiSyF+qi1IWrRYtYcYdLAW8UZh/qODtxwgHWTZZ/fuqXj6orvuj4794OqR9bc9c7h3676tJHWJi1y4bUOp55lHJ7tJNHvdcNvmo/d30vy/NfYnsghuxH0gy2Pik3eGeDDsbgO6d6sFLzvh2eT3BWVlBQXl5TZXgVxaKhe4gL2lFfd333zu4Z9dal7+CZjU958/+mT5j+j9DefOxhONJ39ljqZ0AH1TTbT3ung17p2MAlhyTjSeKDNHT3nfmyN+DfaLRljGzcfhL8OE4IN9/B7IFLZCiOyDa/kbICSk4PkZ9AkbYcKQDX3ifTAhumA//znsIM+CSwjBBLcP9hluhX3CFTiWyjgOl2HfrZoe/PwBj2nne6gphOc9GNBz8dyG52eYS3fg3jQbzxfR2TCer+KKXojnGwBJ6Xhi27gUzz+ji/cBpOAHtpRX6fcJzKsc7le49h/EJ38O64yLvh/lbEYLiKx3NrkIaEXFg8tkFvEMn9msRWkO0rlyjeYT+EICLaKWCzTaALM4XWYSDHIDGm2Er0G6RpvgIu4tjU5LF/glGp2ewLeAJS7fCilcEf3mQEim36VYl2u0aqdKq3aqNJ/AFxJo1U6VVu1UadVOlVbtVGnVTpVOS8/JaNXodLgwzlftVGnVznsR7wVQDvNhCVKroBc6YBA2wBCe3TCMvGr2rcQAu0aQ04tUP5RhzwpYj39Yq5FHv8MYxlm01YX3LvpNBl472cg0/PNhqx25XbAFOatRYhfKaYURRkmwEqWPoOxNTOt6pNYxayQ8N+CYEZyr65HidpeDG6mieOs8KGE2RFDCAI6VUG8E9VAZHXC5NvZCbPUgl/ZuQhuH4j61su9ihpgFZ7Knm2EhQRW227GHciMMiek+qnI2aJ5KTMsm7O1g/uoIb8G5g4yzCUd1MuQk5Pcw3iqoR5soOr1sXj/Ddhmb38VGdEEf6qRId7KrpFmkj5UYf4jFtRdt0SM45QftH0YrenHmEKLQwr6T2sDm+lG/ql1Fvpn1bWLoDMJFzNqhuMRFOHsxXqck0PmlCfMTZav4RJi3NLc6mS9U7uUMt+5pOJyametYexP6pI+mUe7DNo14L/O6jGkdRt4QLMWK4kItNBNoT98pMss0CS6kR1jOr2OW0UwaQW4EkVYz4nT2DDFbBhj+aiS6GS7DLLOCbKbEPBxh0VajMxzPOH005W1g3tC8oGuui2V1Jxs3oGVmCcOun+kZYLFV53ZoUrq0doTJHmCRoh4Psz46q53ZoSM8M2uGtRlqDg+ewumO+1DypaI1wNqdOKcD2yVaBtMqoeotieuZ6UEvy60tDKcOtqZPh9kWzdNettrXs3Wt15+Z2NM56xk1F8fPm7aKTi9dteEfxTZxjVJJ65A3yPJzmEWuI74qT+eBrv1Uu5Yl5AD1RPVlmOnTK/YgW9cjLH82IEr9rJZFzuipmnuRaVml1qQN2lX1SqU3sbWl1khqrR5NXQ4duZ6t0DPnqLqX9GuRmZKur5BeDeVBVrVpze3VcC5jO0urhjL1YT3zbksc5elZXcIiE2F0p5YHp9bamSthbryGqBWki+0VVMflrKJ2sahGkEcRWocj9D6XJvPSGfV7nrZ6p6rFUBwx3ZqvskN+yR1Jmj1DxkpdhpQXz+bLkKfGSc+aLraTr9d2sqns/qJdVs/KM++0NHJN8ZUzlLCLqPFWs6BL06XW4X4t7iXM50FtB9Rrfw/L9nVanPU8VvNqQNupVA0bUKq64/XHMyUCU08aM+vZ/0Es4ghFmO8Ut16t1ndqa7UDpfdpa2TqyYtqoCtazZm5uo1nji3SLdOfNTDa8xIw6mS7zPppdeZUH79AHqu+vWyePvr01a1kRnXTsZ85ez37PUzvDL91u6aeA6dWzdROpMewhNX7DUxLd7zdlZAhtG6pERpCaVM7rGp1O7OlS9upNsVjmVhL1Bi6tIgPsVWyPm6Dvq6n59KXRzVxh1e9TNxppuf0FBJbGI59/2Ac9d2APqf2a8h0JVjQya5U5xQul+GIjoS9Y/gL6rFa+TuZB/qOt3RaFVefsTYz+nRP/v1sj9B3mSl89J1sCqPEmjJ91hCrFWqs2jW/T7/nRs4Q0cG490MsS/uZdHUVqTtv4o7+j2aAvr/5wMt6V0Mtti7G3bKZceqRJ2EVbcaei7BVg9wa5MzBES1a/xwWqYvZPuTDcX62x6kymvHaiO0gq3G1ILE2bTWw36nVsLleCDAdXpTWwkY2M9mrkLsS715tHJ1RjRw/tildx6qgqo/+5k39HFOv7Ymqpa3Il+IeTreqnmnULVuFrWaU79N66a/p6pk8aj/VX8voxridtZqlKxhGVDKVWY0WrWQtyvXjvQnHtTD9K5jPqrWNzIda7Fd98TILqOYyzVd1HMXnIq2HxojatxL/prxawTDwab/60/GrxnsTWk7l12FvK9shVuPMGuZpC0PPq2FGvV3JWlNeqZGqZt5QVCkGNUivwrMujl0zu6q2NCdIm47dxax/apTq3wrtWs2QW81aajSqWauVxYr2lmixbGZ+zNR6MctELxu1gnncEs+QWpa9qvV6dqo6VidYouqjsU20Rc9q6QvWiCpF7/drkT4VF4r6CoYJtaslrvlMksv+396dpLDz7PuTf5X3J2ffDZx9N3D23cA/w7sBtXKefT/wr/l+QI3e2XcEZ98RnH1HcPYdwcxqfvY9wfT3BDo6Z98VnH1XcPZdwT/buwK6NrXfrgDEGun/az31WJFCHOAms8BPculPb8Efe5Kce1A6t/YQEvJBp05k5tROkMyDTb582nbqHc6DmefUrrCSLGLFj/X5xAIeYkZh6SgsDd0ZJkYgRCTCwcJ8aYIInitx4t9Qyqd1vvy/V3zm/4R87D/u/tj/V+T9xRfL/3NdLP9tpM3vk/fJH/x/9L3nN79H3kPyXd8f/L+rO+avPEYsx8gb7tf95tcrXz/2Ov8KDn8ez+eocXg+jOdDKF7B+/14HsAzWj/pP1l/wn/lY4SHG/HkCO95kJzwfzRJYJJMImU+UXni2Al+CEf34+yRb3Tm51bk+JMWGPxmQ6XhmIEPY9eleLaFfPmhupz8TGLzZ1TY/CLh/cIC3u/gi/k2fge/mxcb+CuQeJT/H1408cv4ozzvQ5l5xOGf7XP4XQ6STez+rAq730rMfssCs5+cD34TOLCytcEO2A0GnfhvOAqG3Xjh+NFRkRwiN0FrccNEUqy5QUlualPINqWwhV49a0KKYZsC/lBbYJyQbwevveEGyKtqUBa0BA7y4XBeVbBB6aS0x8PoUUpbLEgPDW8qpsdQcTEpBq1FiouBsSgP70NDWr92YeOHhtRpQ9pwtY/Sw3ER9KD/4fd/AZrCVvgNCmVuZHN0cmVhbQ0KZW5kb2JqDQoyNiAwIG9iag0KNjQ2Nw0KZW5kb2JqDQoyNSAwIG9iag0KMTU5MDANCmVuZG9iag0KNyAwIG9iag0KPDwvTGVuZ3RoMSAyNyAwIFIvTGVuZ3RoIDI4IDAgUi9GaWx0ZXIvRmxhdGVEZWNvZGU+PnN0cmVhbQ0KeJztfQl4VNXZ8Dl3mX25M5NJJpksMxkSCBMySYYEBgO5EBKWsISAmAEDSRiWQIDIvshiAYWIVSyoROtKKVWrw1IMCkqttdJKtVVbba0L5bNqwVJrLR+Smf99z72TDbTL8/zf833Pww3n3LPdc9/9fc8515FQQoiZbCY8qZk8NVA8u2n4Lmh5F1LDnMWNraZKy2hCaBmks3NWrfB8i6//PSG8hxBD9rzW+YvHjX57PkwAYww3zm9ZO+9C7vc5QlIeJmTQhQVzGyNJ8xtgfOVdMF/pAmhIsug6of4K1PstWLxizT+a00ZC/RzUz7YsndNIxOIHCKl6HeofL25c06rRmz8lZEwH1D1LGhfPnfRMMpTHvA2Pb29dunxFfApZTUhLA/a3Lpvb+p3PMo9BfTMhOpnwwmR6FxGJTmwXg4CBW7nzvyLzOLtO5IwiJ8Afx58lBfGT5OwmmEUPiUyc6vEQmZjjneIbsSnUrHuU4zyExrFPIGI7vo2kQE6BbkhBExEowESWwVMiKYbeHOIn+WQQKSABUkiKoC1IBpMSUkqGkKEkREaSUWQ0qSRVZAwZT6rJBDKRTCI1ZAqpJVPJNHI9mU5uII2kicwhETKXzCcLSDNZRFrIYrKELCWt8K7lZAVZSdaQtfE4g+h/+J3xM8QU74xfjH8Wfw+I85f4eZb+Svj43+Ifxc/GP4yfjP8YShfiH8d/Hf9j/N34n+NvxY/Hfx8/E38h/jqU3o8fg9Jj8dPx78WPxH8YfzL+SPyJ+P2QjsXvjT8QfzG+J/5ovD1+X/z5+GFG6f/hSzxHkgly3JXIe14CUVoAvx3deWxSLC/+dzaexJ5VRnKn4+fFR4iZGxv/Mx8GjSPxP/ecKX5eCBI72UeeILeTW8jq2FOJHp2aBKXapjYvV++LIN0E+tv0DUj8Bv7+/StKDpBdavkAQEZ6lO8HyUhc95KdKmRb2H03lLpHf/P1Afw9TM7S5yl3Rd+t8EfIT8lPgB7jyQwyRfy9+HtoqyN3QWoDnLuv11iOWK4Be7AOZHgdPKVctzAaEda3mN3vhra7gc4Pk3vpG6AFK0DaD3RPpvGRU2QhjJ0A8zSTV8ij8K6NZBHw08b1IzaexP8CM8wHuv/n152gY/eQk7Hjsc/h7RGyitzMfQnyAcZUuCf+N9DGKoBhEZmgbY4VkbPkePejwmli0zyMMhMj5HFyFPQT7x1wf+7fByROYnM6F3euin8rvkX8RPyj8Lxwjo8IqaDxm4Cz95Pvs9IuoNaBfz7btevade26dl27rl3/C68t4Ed3k93xbfGnIObN0ySRp8DPVsXqxAbwyNvg70bmeb9P7oMY40PyIETJzeRI/ONeszwA/vpDiEiqIcabRIh8/bbIzBnhabWTJ02cUD1+3NgxVRWjRsrlI4aXXTcsNHRIacngYHFRYaBgUL5/YN6A/rk5/XzZXk9WZka6Oy3VlZLsTHLYbZLVYjYZDXqdViMKPEdJPnVFXRV1lQujqRUNUZNvtE/yRE2TLkwMRInd7fXZPMFAeJA6Kir6o8RRHU2qqTtI5KHhqMbfd8ikKJ8jfe6Fhye6PZVRIQf++cY3RqIDauu8Puk37q7+MDwTTauo83rdUS4H/o2DLvg3vtETiUo10O51Ky3joqSmDlNH/MxQaCRDvWHIa+uimYlqOHw1IGGRFj/ZB8xJtE06aEqtGB0lSQeJ6UyUOHHYhaEQipZFB/gBEAlKbDYSiNKkz6PUEaXOiQBy71fgYx8MvQoNKiMLfZWRZqBopKGbphcUino9bZ622jpbEIoM6OroK1PqDhoNFb6KuQZoIKyBHDQYocWIDTBF60FqGkFZgTNVDjvIEZ0ZyGdHcCsxLYzKtzdAwTca6AY9ju6ejvjJnT27CDyWKDmUkgJEVFMR1SpAeJqjcmOU3O45mH+ybWeHRJoa/KaIL9J4Y12Ub4QBBwmfU7lgWjS9umYGNMGrIDUs8CC7R7MMmeepXOBpgzqObYDcNxqZ3qs9smBuA4oJbfCNhj59Rd1t3pPuqB3ulVGbP2qGYeZ1Z918W6Wr2YPVtrbbPNGHAdwevV7MQQhcAHpbpQ/eBpNVLhyFLAl0sY1J47gIY458e6MnurlpoSJ7jTsT8u9tk6KmL73AHeAPPMkeVEkZaViIIC9sRDQrF3rabp/LUN3JUAN59VQuHI0JHwTpJ9fD0zPqKhf4KrtfCIhDgc/p+6zXG03144NtbZUIYmMEoFdAho5u+FEn3H4K8FRE5WnsRqYxHsAb5cbRYbVJHTADH8OehtHhsFfhOwyNanNuEwt8njacUZsTTfJL3peg7+Sg/OrausrRboZ9lKuoG37e5T4P5eqarmbqgjFtgfNuhUbVU33VUxQpWJDIGqYpCsx1cR6GquPZrKdd7tNQrvJVNbS1Vfk8VW0NbY0d8c1NPo/kaztoMrW1VjZ4mOZTaH/2dne0amc4KjUsoMOAyShvVbXVUceUmcieKs+CRsVYlPu8Q91eWzgxpubrulU9A4kHuUc9a5POAWwmsEhuTxWalw6wCu6oNBTVFCC5vg70YA6TWZaBfkyFyd2oKXw4p7J5qkogkEZVYNDuTVFbYRKvF3Xo9g6ZNEElunlKnVL3kCb3ISIH/MC7Buw5mehxXo89mxM9XY83+IBXruqp/0Sme8pzm81n94QCjP7M3EaiJ6cBjheHRnVDVXY7Kup4N6eWODePJYMfzFdZNMXPHkSagJVsk3ye131RyR8VK+pOusvCHskG5o3CmLF+1Bqwoq/7TlG0nSRJitKyKE3GdgK2lJl0PmUodHYJj6eyrUGVrp5oqQ4gsuDquMEYyQfouZXxNrsPMXyVmTTVUudUoS65vcqI8eGoBe1x1HKOZQCvu6LOA9YHtHUKK3gqPQuQ2VFPw2hmBsLuns0d8Q8aRqPZA5BxiFsVa8gV0vaWtX9dwjeDhN+yM7wApDsqDwQMPCXwWqYt0+pUKg11q1qE7xqHqPTu76JiYsyV1K2e1qvWY150CF7oHtql+9PqolX+xFRKfYzf3bM6tk/3uEQ3AUp4bOOQqOB/hrp7tQF/ZaUJ7MgG9zr0JxwdddBHt085KNPtU2fUgYcbdUwixLN9Wt0hjnIVDaPCB/tBf90xDwRDrJXDVmzEigcrpJrCjIc4HRvvPiYTspn1CqyB1ed0UMLadIk2SuZ0cEqbpLwol71IJhz0CEqPnBgtQJtOadvM2th1kCD+skGUdbJeNnFmzn2QYtMhaHmWEqKn5LCJmqn7IDxVy5o76OaDetmtjNgMI2QFwu3Xd7/6+hl1h00EHmM5vGgUXkDuzUDwGtAleMfMqIRMhPAq6kk75W6T0FxHw340af+FdrAZxORgDt1e0xOnG6NJ1bUz3VEaHgRt+wkRtoqrCE+0JE02aikvEF4U9QIJnLaHAqfhVn66qDBo89pyvDbvfv69y0e5o53jxVWX2nYLk2AG3MG0i+3wvJW8LudrtVSnoXrJRCZyOr3BSI1mi5UXTLxATZRKPMUewWU00wm0I/7xESyYQFRYwQgFOYQli1lvEESjSWfWTDTJ9uSxJo2ss3K8ld8Vtlo1PBV1VpOR5yx6s8EgrhbpGkJFmE+2GE1kAnGxnNjEgC0Y8Pvr6+0pIRIIlIcCfiK5XpJeSpP+4Pe/BK1FhX4/9fv9s2fV19928qTl5EnpNsjEkycpPOb18V7eR4MOPre/T6PlRfuz93U+fOdzXO5TD31oNAoG8/v07tgSsf3yndyczFHDfZ3fJUDL40DVANDESlJIFnlXNunNVGME2gIBBISywEgm6lw2m2tX2GZLpSR1VxisqLQrTHl9qkmDSGtMmBkh25AB1vcwtLG7SbnLAejKyBBxmLhhk5M6dVBy6qDV6fTaUpFwqdiUik2pGwlYfJwD7l/iHFiX9dBFvDIA4wcq+T+BVAxcB4J94g8lWmwhUu4nrnK/zU5CrgC7FRVSP0GS1YNkFMMaQ6N1JsNN8PG2YDGsSbyJ+3F637O/27pi11Oxi6cuPdn2YOz8j8/ufiy2X2w/eve6I7mC7djujrMiFyvatvZXne2dl3euixGQqhnxj/ktgoskAf0el2s1EgU9kQQNY6zReU/YKAEyRmO6nTr5dDF9T1hMtsp601ir1Ww37wnbJY+10MpZjVkEqUmQTASpSbZSDhpA9r5AMsD9MzkF2in1WlO36EzQphOgHtBRXaAeKBC0d1EiGAzUAy1sJAhkUO7lNtZdVEiYBHl9JT6NLzu3RMoBD5WtLSkNemxarUbjTEpGevBb9gmLXt/7Q1pLg28c23PvT2nzvn8sW7EovO6hhzsevZVmBfxU3HigIfat3dnSlPnVs5/YgudAoKX8RaCGndwjD+BslJOAFtSpdxqsJsEq7AlbpSvRREYrmF5UMb0oZzJMk0w6HK3D0TocrduqR6LoO+IxHIr3o9CsDyTR+t6CwYoqDcrLy0EOAG0CeNsAXY3T5rMFncHSIIgEf3HfZ+sf2bdPWPHugUPcWFp17I5OMECPv/jO6QRG4jliIvfL0joTXW2kazm6wUA3UmpC8daDmaASSCbBWjbU9JxBpE4RcNYQg9FIW2GaJERVNtKJxIRqlY6KoxMQOQGRExA5sG8CNIB1iCNSYsDCkGI4FaPc1wNfgwSwQWYy0UaLQeqRndSHKNmCNEj5ix/FygRAiD7121gOPRdLEs9dLqdvxewKPtxxwU4kEj5GTABKfxRUrVNnJcTAWSQEltgNGgRNg6BpEDTNVm1H/G+yBRq1AjRqRWjUdlHcFkJ5O11cHEBK+2luDxIDjVO44/4pzXcARL67wnI2P8P78hOdXwrkjZa1FpSaBtChJpAaJ9kmz6zjqd6aauWMxElNvNPp4Bx7wlyy0WjWgbroJOIxARWJERXAyAEYrWC6sc0oIcwSwiwhzNIWMQnJiQNFHyOoCm/AD/oC5jahIuoNBKSocFY9rc8BzSAlgwlA7mSooE4M4RtWPfr72N9o9ue3zV/2re+eOvHQrasCY2jGHztpsPhAzYfPHHk9THpIjI3pgNStAwkNMJCr6cDFr9EBx7+sA46v0YGEElxNB2xBVHxUgTX7gD+rfkdncJOofGxX53HxXOfCF2OzASPwEqIMXsJBfiibV5voMiNdAzpAqRFF3gCyb9WhLxQR6gDzinYqCnoDr6fWvrhu3GSjNhe02Wxo9W34TCp02JxGsS+mGwG5zw8ryIITQGw1DFUVtxDgydjJKkESKAdHiUYOXSLTCvCGyQxRmpwSzC2xBUX5l52Z6XaN7sDvuF8OMguGA8Jqf6Dg3q++ENu/ur8qbcQe/nO06yCTQg3IpBE84w7ZlyobuYnEvidMkjWmPWGNpEdQ9ZoukLY4Vd/nVIyCZqLHWejkoPaePJD5ulQrujqrAbqs+Ih1C4+ugUf55JECfCC1m4PIwPouK4ZeDbESQS4lkEviTCJ8dsJYD87lav8Y+ytNu/BflMb+/IcHO5594KEnnnDRrPOUo9mxjy79PfYOv/+3J47++pfPn3wdONoa/5TWkF8AdumyjWiiM4lD/3QWH+A5PmAGIG76kOALU8BBDGZGMknzfsHIkQWBUaOSRxUUVFQUFIxCWb8LNPeMAPELeUQuHaeh8I83S2hRrDw1acDlmUQTujzJqrPSK8R+k5VaO+KXkGxwv4zijHdGMKvVYcDxBhxvwPGGrVoDGiBs0HLMADl6E8yvSAKzkYrQM53209lM7NHleWwg9BJSzRbkz+wT5v0mdvdjF9fcv+/RZ+kRLtJ5NHb84J3cJMDNH/+Uu0UMgGe/Wb6OZ/48KcnO2dEaGQxai8YI/nJPWAuG04yRiRmgNeqsCLNV08XkrYIqwoIaE8H9s8No7bucdXGwOBAAe6SYI9TJLpMEsOcwmH0lwZIhNi8ETMwWcbcMmx37WzS6j3KxWNWUEYMMHprPzdp5qST2q52dL8yvy0bu2CG6+wj01khekQ3rjXSFgHoLSvv6YbSXsFI8bFbucja4JqEQWgWPGTOohoy0VKArtFQ7AFVai3KdivRHtdVisGbUcjzPGVGsjSr78C7bsG8AAKAzwYN4lovqa0UioPMQMGwReGh7Bvv785SHACaIERwY5fpiFHnQ5BBoMjAUxL6+3s8uUGlKIchFXS4dQoWPOs8f67z4HL3DYRB0qXSP2H5pHmjxnUPGllUKS5ECeUABE4v5N8pGHoySRtwV1vAiCp2RxZaX5AFYEImF48VRr4lUFHUcYsQhmhyiyW3k0S8jwLIZ9ZTX62AJRdAqnTyEMalfCa5UMaz3U+mMK1DQHX8ADl4wQt4Sr2CKNR2IzeH/KHKXYiJ3H1gajMFPAozppD95Th5WaaW8bKFWjprElEydLnNXWKczZBgzdoWNPDWk6G0InWI7Ebp+G2wQkKyjlEusUnC5IueyUjpnE9Cj4yMkL7Ov0dpoUIXTgAQxqXdUNRTOD9GRSC/761OKkfaBDxl6JBDsE2HPRp85G5cgBbwPwxBvcSbnTLJwWmcmn0Ihvh7BgY3yCSdfueAdMbI60HaAPjnroZWjBk1dOa5fSWEgo/Pg2fJFk/L33EHvHjq5OKXzQbE90HBnQ/WGpkqHIOUNHRPgp3ZezB0zX15+i2Kb+T+wKDOVPP0jq5ZKGg0uyAYZLWM1GiqAKIRTUwWrHtytPtmajE53E8hxMgouhgpaLdniYGs5UGqHqg8O1YA7kHwoFA6HO5Ui5SgSmyKx6RYT2myThGueDFzz9PG4/k+KMVC7ciECN4VS3mRUYCeEGBwLMezO/rkYZGj5P3QOEqLtP9x123vvXKTWU6fePUBvW7PiUQf97RPPLmtvoimdf6GDYpf/VPLtB/ffynxULFOQgA4ukkN+LksGgfJWCxCjHzNWOtBrhqCItBlmtI4VRS2nBfOVbvCZfXvC5uQUqzPDkbEn7JAEZ2oyf4V91ouq71UDjQuyH8VG31/w4FAPDvXgUM8WCekiWTD4SsPgK9C/2zT3WJmkJMycK2Gh1VUKW95ieDK7PkfyZvcvSYa4hK1RuBLJDpFYsCTIoxQlvJ4gdZ59/ts//C5dJ6z88wuffPW71yIQ835v/X1Pfm972w9rO18du6+B3t36ErV9REU6eP+3O1+7d91Tf/jZE6dfQtrdBeZhnvgO2EYrmST7iGbOTGKxmvVNvNnEN8UL+65tt5rVeMusxltms01S1B71AlT+QwJm+2VAxNHDazog9LiUP2JE/qDyct++faJQVlAwfHhB/ohLl/FTJkoWgCxbgYcF4EFTtbmUT4aVtYnqMXKCuNHPnKkdSV+CJcNQxtEB1kwhaVBKalLqnnCSBAOph/JgHvhB/J7woOSUlAGZW6xWMmCLiMY9GTkkFoqcKBYS5BNJR/YGcMkM1upDwAITE1rpZWCCUrBhMIV8Yevn2fX1Q4ApxSWDC7j+BcCKEZwaH1tA2TO5lEwedd6XveDWR97OKb++aPT8St+oJXdUb2u+6TsF40syMobWBEe3TMiraL275sGc6Jy78kL5Pod7SGXddWOXVucW7B/vzC3xDCgdmJ2UNqRyxogJreP7IYXSCNE2gH1005GyZ72brk2jq5LoKjNdbqIr9XQ9R90eMMZpmCWh7urBJDtc6JHRw0GrCYlggIJBh9TTK9svZKIOl20cZjSxkiO46+NWLYJb9ZBufMABLtGEHtKEHtLkgioQ9xXwnGBoU4ZibmV5isziH5aLSO0U1bBY8SUZSH4qWh0pGoORNyQ5NJRL0RusKR4Mo/GFcE9BgJMAEisiZdWk8EZCMoyBDNAp8JEsyEVvGVT+JeJe5VLWhX2ueuVC98k2iHq40cRd2xBb9NPYOw5B0CTFfvuT2I3HaJFDFMU0OvwRWijpBCGF5qCLFVwVk8dXfQWRxVdHKqtLZgoTvnoyNHHwdKFGWf3Q8bD64ckwOZk6uauudWLqGocpEoWlQrciEVyneDFgHw/qck6NxCUoSSQD1uBDrRqwcOnMwnFu0Y3BJXVanEbnnrBRshKbWXF2aLKJTnmh2HtldYHFl5RmuRA0F4LmQtBcW3TILh0aMR0aMV0gq298qeyudK+p8MYCzFmJLRXFqqcAX/qYq33Css9+/CdK3nqjAQzVvo33PPm923c88dTL1HE+Rov3c+u++uO9Nz/57osHT78MdJwFWJ8TD4GHe0rWEwO1ClQSMeCQrwORcKXsCrtcOoKr411hzmE1Zhk5A88WyRAvCCkpTsloJBi2EKF76eXE2NPE1iifgeDiqsTdY9W8QUS/xmRWlHosmLuCm+KATbETifUyK4F5ZwZc2VnK0Xg9xCYRr2IcsAj+jsU+596OXYydjm2j36MVnz701Gd/jb1KM/9+YH3sZXqmaR3dSavoRPrEhGeXxI7AwAuxUxX0boyQZsX/xCMtPGQwqZL7eckOXYoklfp3yCn2wr1hq92eK6bntofTtRApiYb2sJjaY2nPnG/IT12BtPMAvT10HjhGkzgNMAvdDEYnyLgCTrFpmZwWTFzCrGE3f27SPW+3fbtl9W2NexcOFW48e2N764jK9T+ItHx/WdlB/4TmEdfNq/bnTVg0MjS32s/7fho7/dbS4u9W1Oz9YNexkav3zVkY3VR1w/e/MEzd3lgSuH5l5YQ1U/P94+awFRS9xB3i1oO+pMsSR6eGJ3MUv7ImHkppoD5QT8BCY/xY4uUOdb7HZdNLt+DO7Yz4J/xloImPDCHVZKYcGLpDN6rNLjrtOvgjaTsKCib22yETpxgcPjzYHh4+PM+clbc3nJVqHtMeNmuvjFBCCQqdt4VCAaBTSDovnQd3BlQZkpubIA5uoSZMfQE3RCVRiUoyR5/6jH4Vc8rrlwxv2T39ht0tZUtmjmiq6Dd6/RPz5z1+c+WhvOpFI8sXTgTSLRw1onlifjBn5PSiohvk3Bz5huKSG8qz6V2h5ZFa1+DH5ky+tWnI0KZbJ815bLCrNrI8NOuBpSNGLH2gpQI8ysAJLaPKmmsK/BMXceHgDSNzckfeUDy4ToZ7HdK4CQj2OXgQOxl0jGjprbJdtup0YFCIZLNJe8M2jc7FVBqoAEQA1AOhNMCcWniO0/pK7XagADCA/9xbv6Bl1hgpaq+evTAyNbWziL9LvC70+JtfxC7H/n7LZmqk9LNX9vp341vPQpjxpvgssZAM2QwEb6M6rZaatRTfBa8I0sD5l4PM2Fl4bckIfkiQe3OfY9zMuYWla1cuyB0h/NZRVDjQtN8aLK/0YswyHfQAeS5BxJcnO8kOmy3NuUM2WB3tYatWTFEFH/naxcsuUc/NBabYS0uDHl7yemyQ+Msj1x9e1vKDFWXl6360kv7kQOwPsdN0EM3j3jgS+/SFObOPUv0Tx6nnJ3M6bbAy3tX5HGC1HmA4BjDkkWXyyOQdaY5+vC47W0d2yFarX5eaRq1p1MinpbkyXO3hfnaHw94edjgMGdpSHSxDJJ1Hx+v5K9QUDQfShLGgu4kiK9JAHtHlMVRQ6hJKK4HFhSBxsJdtX6NoSiKsOPhj47Y923p67a7nqtfeEIi1rr6JNsU+v2/bjhMz7l4Qip0Zd/OMIL2n8aGbRkyKLssdO0+mqbdT3RfzHqotnrFxQuy/pgi6IXWrkYOLQW7OAK4DSZmcmenYYQAu5GfskL0kw+LJ2Bv2uAwG0SK2hy3a3vamh60pBqhVXQAoFTBxaWThnbCaR6UaMoLnhbwxDUMLb7xhiq/yifV19ywp7z95zZS5WyZmcT+/fPuAG/e0TGqW3UL2qKaRnrQCuX+0Ykyw6a7669vWtQ4bOy8cHvadMTfu3Lhx8tB585qV/TrNMoyYyLOyc10aXemguY5SB7csmSazAy1zYqnITqKGYCk5jYp6s8Zus9t5oa8L3ZiGDWmbwCThzh2lGsWTXvoROtIMB66MU3DpZO67B7vRpq4wbepxjk3186Fiv7p3F1S28lApWBCjrPhxl3LwECVS6bWJhxGLZtn3LYLLEUuujaU4kwXdo+/RjqBV40+jP/41/+Ky7zUO/OqQUFU4Z/pPLsti+2XX8tCqYfxZoMxaiLbfA46WkF/LzuoSOr6AVuXQ0Wm0ykkHu8CxDgSCYMg4gO3WkImpSKDpULBhrz7fkS24itJgJjc18W6X7IJluUsgFGSeFhVpdoWLHG53fjaSKxvpl430y97gcNB8bMvHtnxsy9/A1lNWDM31EO4PUdaXAWUDQVlqqytuNTB/SQnM01zSaSjBqtqmngomwrshJZk82w78JwF6Abc2e3bzwkH37w3OWD+m+lsNQ6bvPFz/ZuOmnw1ZMr00r2Z59cS2BcOn3tExLzuyoH7Yy5mFXvvylmHTx4zslztp1uqapl2zCoIn6lIG1143pGbUiJzcafNurln4nRvzjM4soEz/2EVaBtaPJ5VyRoinIUI5mT8kEA/KE9tt2czJttSxXEf8UxQJvGMgyAVEJdxKOw1xoPRl2mkmCTm8z0HLHl658mwsiZ5DO2ghRDCAfFuIk4yQM3kqtmlkyaLRWFN0gs6qaw/rqc1itWqgSTW29lAwiBoKmgmODWLmNKmz+GWY3xZ0si0LtL/UC5aYr+3oeLRz1qyTT+8JxvrRT6pvXYvHphPviT1Np3x74V8v/uOmyxO557f88sB2dbdfMw3Wb1nkD0fHmeg4gWaCyDyDwbyX8umwkpDz8Yg5mZoE0ZnsFswu855whktyWA3U/k3B8TkZV2nUYrAbRiXZcKANB9pwoG2rHbeuiqBut0Dd7u67tbPVYMDozyDDYgXeZOI9XsPWQiVS9fslpoIuVReLYfV6QQ2/XYFgsLwcaZUS7No89SvqmDjW6XOCloJHCJpp+5pvbv7Ovk9adu7bJyz+VfMDGcvO0FpuwuP3nby1s4NroAU/2oXnao8+u3L2m7HZRLFTwqPAR4k8IKdvsNA8S8jCbaR0IB1GOcmFm4OSBOssS6+dLWbBDBYJd+q0dh0PjKbs2Ao7cYMSz69EJIdy5ozkEDdq1UWYNnGSwHYwexxh4dZjSD1gY4pFE4qlHCOopyW4XhIe/bTzN1la4cABweLiXL/q3MvdlWPuHCG2d85KdnM3ddYgdh+TTcJuwU+MZJzs5S2CzqKVDVTQaoXnwVtTM68lFiqIo0SDlp4Q2FKV7Qp/GAqdVrcTkFcsNAOlZ7FYYhsRQPEKu2Mt22KL6Xe20d2cHQu30u/EFoN+LAUfHeuOl+0GssPrLfWnQqiAYXJaenohxMxJ1iQWNhT2CBuYD8MYX42Xi5VwMOF5C9QQosusBEuvGi/HRq/Z39jyxOoRU/e+vW33jKXrG9qXXCfMOTvr3kXDDuSOWTBq+IIJ/oETmuUR88YOoD9rjm4eM+MHX+x9jha9syrv/tD07763/bC88tE11WumDSqY3Hzd+FsahgSmrSTKbqk4Qv2K4145l/AU/kki0bMPE3T4YYKAllZASysgj4UNZvUM3azKgFn1RXD/FMSJ7eVcsTVK1GNpomoku6vbJj0WhH1OaNgBGzDHgysg3hbEpZD3ON3JfRmbGXvozd/QNDqs8ygISiWscRaL3Ff30AJYJfdX94HzADMDxKl3yXlVGspZwWiYyK6wycRzdt64K8zzWl2vLXjtBgk9FjpdFP9MdLy4dJOkJBNFlBRXjSjRjZx6ygj3L5gOcAIzu1c9OAeEsA7LOhaJsW3dZGcSUT+ckLw0coC2fdQZ+9NfTkSfeiYW5TI7z4jtH7z6auwyd7bzyEO7aDpogSWWyb8lEJIEa3eDOYkSM9VwNAk3OPJZKOLBnPOwnRgqCcRqskqF2CZRo0aj43V7wny6xoggo6WjJiPDhzclYROeqycRSfmKJtmMnWaT6rtNAX+QHSlAqIGRRdfCFUycvzxxNKQeKyTiyiHdGyL8W7G8jWdlf0n+zSNqY61HqVOUNKKV+gTy1Y2xF83fse9+kY9dPmctdw3mk/GQP/4x5wcOmshiOQU/qKLUqgfhZGgA8xxGPHm4wE7/RfGKIMvgUnbiv0zsxKNTNBgsZls3Y4oDXQe6gYS41UOEr0JvswU5/9s/mlZaOv2PBzguHvsv1/7+9Ba+XbG2/G6ATk/my/mcuCts5SBq4Tg0onRXWMcLwCYj1/fkHy3nV6rlZJDh/SizncbeB87BQJfYoOFi1gpPrEBy+N2dr3OazksHuLdFLibd27kN/7NQjuyPfyxMU/d2HpD9xEAlDe+kTqtzT9iarHXr3XvCehCKvruxW1yqKLswvDSx+x9l3LNxubI0nB2H23G4HYfbt7KzGxse4nB42krZaWuPzZ3iqx2Yd53dADY5Pqd6Wl5sd0pAbr7r7BWcIZ2En1us/eSn71965xct39u05wcP3nbnU7t3i+c6G16Nnf9TLB77BTfuzk0Hz/7iiRd/Rmj8bNzODwIS8CRVNq+mlLBNSKhyASBigB1g414dP6izZi/3lNj+32s024lIauKfamQxyk6l3aQ/CZKn5eJUF589oDacbUlPL6gNpzs0ZBSx14YJMLE2rBHKXZNdXJorzZXDZ53wm4AI/o74fyMH/UUncthOI7TluIAwOfidVU5OCa8/4cQAJNmc+FLLeoJHqeXTTewg7OxhRkE8JHoTkiqgiXIoEKhXY1Y/M4xQOosFRKzH5njPE+wcwNbxNX109+7osw/u/cGJ22cvaamftbCZv+Hygjv5e3N3R48/cN/jJ25vWMyauV/85LFDp59/8snXuNV3rF97286b195Wd+lGcd+lmpcePfTayR8+8Rq3aufNq2+7Y/26rSh9sTwBY7de0udOSJ9g1ajy9+9Jn53D4RwO53A4929KX6/TkYT0dUVb3yB9L7936Z2ftXZJX+ce8bdHriJ9uJ9WrsmB+CCJ9COlcppDEmwmkzdVcEhEp3Pi/iGBZY2dOEj5y127RLiohehIepl9eiR6+ufapCGlXk9Ksk3SwjLNmwM802psUgpa0VKb1D+Xi8VeP/bMc8fpSDrg6NFn84shPnkt9vnCZWfuuGNH2x/Obd++davr1Ck6is48/ctXXomdiD3yapEv9v7PvWLxY4/F/hG7+Ngj7e3USTPa78eI6nGwFm+B1pjJOrmIg7gYjJddxxkFTo+boCZevOIIa+MmIzWa2Bd4GDCn4BG1Vavp+owAB2k3QvQVk/Vd59NdR7mJT0vY9wQJT4i7J/gNAbsJb3W+3/nlAbqCzj/Aje7cx1Xyiy8/GBtDH+dvUm3uEXYC3yoP1gCU4Ps0u/yFGgNHDRCr2NEOcxCxCDpCzJq+HzxspGrEQtXzWaqez9JedjcYCPTYzsMYHoD1KsaXJf5Ip457WzHBXI3Yfl/Md2/MoJyt8HeD2XeQD2THegddbqFrTXSFga7n6UpKHYlvLy1oBEyJmgFrfKLGFq5m9esGk3pnXwY5UAVwS5liRiR1+x1POPCwVbaxT4UkFs+znFe+J4KSDc9XNBjSOKHAa2wOwWi2GglnNnKc0+jEk3cTfg0K/h3tcs9Pf65+9qHnfOq3sT5Kgw5w8ZS/O3aA1r5wypEmiANPn6D1sUMvvJzsFCgRSOelmIZOyAroIVCjX3KG2KP98+hT6qqF3wc8Fcmtsp4KjIvMrx+W2Md7jGGiSgd2N7L7x4cN7P7BYT27n5Rdhiw8k+37GeDGHl+Dfc7iNCr25LkaeKquinEaIk5+X6frACeL7ZdiCOU+WAOcAih9pFbOT29LS0lR9uhydFn29nBWlsHlcu8NuzR23JaDOODqW3KJ/WG2bFZ24q7chxvM1gJaB4gar+xw8afGbju+/JXGu/dO2lAXOH44Q5aHpxZx93b+I8MzNn3ZkQ0j6dHmx9eNKntqVkHtisqdD4EK8Nxru2MzOb5s6SOE/caFuH+e+8j962dby/5O3Dr2nxw+/feyp/H+nvee4FeLLh+1xgxzCP5aCVV/FQNy3aOdQADrF18tuvQra+yKX8sIiQPJfjGPJHNFEG/fQ/BbyBnCbWQ/f4ns516B+yHSgHXxMvRFSQM9Tlqhfhd3lPiFi8QuFJE84RT0BWDcUei/QO7i55IF2rUkDcr7sU3cQGYJNWQWHyR3wX0GpCZIZyHhKdl6SIu1AZhDJmth/v5Qt2jOwrP7yHFxLfkY6kvFB6B/PTnOv08s3O9JEv8x1I8AfJnxs5qdpAbLGh2ZJW4ij8Mi4Tj/JEnjX4IxNV2/O4GfaE1XEncfSC1+Q78GCDsW0ruEaB4nRHszUKwVSDgJ0j2EGJZBDDiYEFMppN8RYjEBLZMIkWBJK71NiO0SGIsDkOCedIEQ52UIu6E9RSLEVQbpECGpYFBStxOStoIQdz4h6VWEZMC7MmGuTIAj601CPDDOC33ZwNjsM4T4OgjpB3DnAMw5vyEk95eE9NcQMmAaIXkQ2g+EOQceJcQPuOS3ETKoEH9bh3E3xB2Dle5jsCLkwJMH8PcyRIvhRtBh7C3k4O0QWMHFJTGq8ExOJFbDMgf07aeWeeLhitWy0GOMSFxcrVrWwPiFallLlnFr1LKODMSdKVY2kuncp2rZbBF4WS1bWDtPqAChHjHZRrOyiJDbalhZw9obWJlhZGthZR0r38zKegDaZduplhVclLKCi1JWcFHKQo8xCi5KWcFFKSu4KGUFF6Vs7IJZD7i4HPvUsoWMV9sNPXAxIpze46xs6tFuwbL3VVaWEE7v26zsgLLd+xErJ/UY72TzXGTl5B7tqfgsSA2W3TgmO5mVM3qMyepR7sfG57LyIFYejGVdD5h1PeY39Wg3JeD/AchXMSmEhL9pNJE0kzlkGVlKlkOaR1ZAWwWUlpFWljdCSzOUlpAC6BlJWuDPQ2qhDX9JaAU8hbW5cJ8Lo1dBHmEjzfA3FmpN0DqXrIaWyTDjXJhnGlnLSh72WyxrYe6V7K0tUJrPoPFAwl8mWgvPJt7j6YK7ENYJHpLbVRtC8hkMjTBDK4z1wHsb4T04xxyySB07HmoLoBV7VwKMy7twmsZ+EWk5g+Dr4JnHaOEBG9QMGLWw1kZGid44KvMsVTH1sLeshN45DN8EhVfDs8tYy0oYFWGU80D7AtY2kYwDmJA6zey5JYy217Hn57IRc8lieOdc9hszmHtUiBJjPax9OeNrM8CS4GA3Hti/gv0STguMKyBT2S9DLWXPXg/vr2X1lYwiy67o9fTpn84wWN71lhKYsRTy7ufwqZ6zKHRqZFijjEUYTjjXIka/eb3ocaWEzmf1lYBbYjRyezHUkfPNDPsCJjcroG05GQaWNABvQYnAnsVXzFmgzhCA8lom+/MZZChRa6EVf0FLkYyrwbOcwdLK+KBwZB6jxQomYWH2pIdhuJZxXeHSii7JS4zGtqUMG5QP1L25TLojbFyrKqH5jHZL2HtaGY+VZ+eos8xV641s7lbGHcR4BevDp5oYHAkK95WeFeoTiiwvu6JlXhcO+f8St1pZPQLPzIF6virJaC2U9+Z3vacvBs1MnlYzOs1hun01mq1WMW1mWt/C9Dthh/rSHp9pYaUBMD6vlzZdfXYFhv+Utj11FWeaD23LmHyuYJyb06WdV8Mg8fYr4bquhwwgJgouK9j7EpZ7GdPvtUx+lgKVljCb1vi1mCqy19hLqhTbtFTNFayU8kqmW4qtRGgT3EzMgyNbmIZ+vYwqPmWJypnu2RMa0qxSeRmz3mh7m1U6FzAPM02lMuLQwrBb3UXl3lKdzzjTyMoRVQ6utLl9NWFAlw1RLMhc5jNWs1/Qa2bcR642QhtSaD6MSPQF1Dln97Hjear2dluL5V0US0Dz73jKf9EzedL7zDEhMYcno0uaF0KbwqeE1MxlHr1F9Wjd0v1N3jYhlV/vcZFzNV2as7yH51D4rUjBXPVdih1eovI9n+G8TPWECdu/gEn7fJXPCTlW5KpV9U7KG5bCrIrnW9IlKY2kO+Loa8/+P/Cii0KNDHekW7Nq6yOqrs6B2RerOtIdgeEbUKMVmRmQgPHreQvlqb1jDuB2Xg8aRZiXaellZ67E8RvmY9a3mT2XGH1165bfx7olaN/3aaSaYk974p2Aqzse7Naabk+U4GE+s/dL2VvmddXn9pAQtFsKh5bDbN0eVoG6icEyV/VUK7t42dOWKDwMqBxfzrSkpQuGhF73lqV/nao9PbyCZU9P01umuymxmtFx8X/Ix4Q3wHh1iUqZuT0giLAc39lNl4UwYk4P37HiG+yxYvkjDIOExxvWy4orMdYqVr7aCmAJ8xEJL9NNn4Qn66ZRT5vS+6nlzFYovGpS8b66z238Go4u68J+OZPSJWx2RYsUz9vTo/+nEpDwb2NJJeudTKqgdgN4y1rWgvG0B6xoLfRMhxr+BuxoaOkPI6aq/f0Zp25gfmgsjLue+ThljlrIJ0E9zGxcFfGwOtaqYfwkmAufrSR17B2VMNtUNrKWzT0RWifAvVIdh09UQMv1UMfyGGYFlfdNgqeU9cw41ScqkE6Ddk8Xhr2hGsfemIBsItRqYf6xai/+5u04Nh/Cj++vYuVJXXBWqZCOZDTCmXHOCoBoAqth6/Vwr4FxU9n7RzKcFWgnMRyqoF/BpZJBgG8uUHFVxiF9pqs9yCOEbwL8dWM1ktFgLIOmm34VcK8ByHH+MdA7jXmIyfDkaIbpVEa9SpVmiO0EVuvGSuFUBcMGqYo0GA3liZDGdNGuluUKLLU9ZutNuxtYf/coBb+Ral7BKDeZ1RRuVLDaNMYr7M1XeVnL8Oj71huYJFayUSMZxlO7JKSKSa8CfUI6lXdM7gGJ8j7kbU9YElLt+QYdUWZJ9F+vcvpKuiDVRzKaIFxTu978dTMXQO9SZmkamY2DOIWaQWcXgs5/wuxNom+qaiEiTKsjfDt/kD/BvwDpGP8s/+T/2F6MgaVr+zH/V/Zjru0xXNtjuLbH8L9hj0GxnNf2Gf5v7jMo3Lu213Btr+HaXsO1vYa+1vzafkPv/YYEda7tOVzbc7i25/C/bc8BdbN736GR+YlE/UOo9dyTmNtr54HtPfTqh2hFyBSKhGphjDAc8lCvmZbA85Ng3CoWx6M9Gwl9y9jqGGfllQ+y4pPw/9N15XWMeOiII3oXHe/poGWJwuBEoThRCCQKBYlCfqJgShSERIFPFKj8FSvFWR5j+WWW/43lf2X5BZb/heXnWf4py99l+e9Y/jbL32D5aZa/yvKfs/wUy19h+cssf4nlL7L8JMtPsFyB7CDLn2b5TpbfzvI2lu9g+VCWD2H5VpZvYfkmlm9k+QaWN7G8huVjWW7BPPC8cJ5QMlk4B7ks/Flu1JtD73+QnJL+5luQrb852b3+5tRf/RrKq1ZDtrgVspalkC1akuxetGTTsrQVK5Oc6fMXQjavGbK5C5LccxdsuyktdXnyuopU71pI14WIfxik0J6xWYHjwkckIPKEE/nDjnjWB88L/4B3f8Byj3DhsNkWkjuETw8Zk0LH4ieFvxx2Z4fKR5qFL6D/TuFvkBeq+V8YzB8fNkqhwhP0eqhtxpxOO7ynX1b5C3QUtFjpSPIwJC7+wZG/5vlhaiofHl6h3PsNwHv54fyAck9Jx/twOTnXH/roT7xf/lN+QUj+kxuap2VlhfCj1ORf+Hwh+Z28gaGptZy/9gzn90SN5tAxyoEguTl/52WD/6unRf/n0POTn3J++XcpqaHfQwUePnymsIhNYjuTkRmSf5OSEvrz85z/+XbopVsP7TXA7Rbltlm5bZKtcL8f0l4Y1L5HhGk+eOazpOTQ3bt4LMumLxzJoXN7BP8uwBkbjHNcqaF5c+g9ezhlwJ6cAaGhQ4h/yNZ4Fkj70Q2c//LvDf5jdAQtOwQAgkodyuoXAvU5tAHmpAWHt/L+10F3fkTltwF4BFj/UnZOSH4RAEY0Tqa58f7MSckeOv0qwnHymVNAlp+/wspy8gWgyKcbOX9hk8mkqTj4NOd/eqNCgTesdjbFif4DQsfprWQHJcRPtx1qM7An03dmZoZ2tAn+tq0G/+0Axy2bqH/DRsG/cauC7sgmwK5pK/Vvh3QbpG2QtmwV/J9s/e+tXPNW2n8rdQ9xukqdzhKnfbDTGnSaip36Iqem0MkHnKTAOTKXjqfVxElq6AT8qT86HiRmGL0OJGUoDRELLaVDiIUY6VByHaRqSL+AJEBLKbSUkpmQeCLRYfCc5hAfzxrppQZqhOd1VA/Pa6gWnl9EdTC7EfLrIFVDeg7SnyF9BUkDPQaYyUBuh8RTjZwNE+X2twzoby0ptQRLrQP9lny/Ndtn6eezZmZZPFlW8gItgtcWgTEsQotJC+XNtHXgBwM5UkalfnK/1n4P9xOsks2kNxhNGq3OxAuiiVDOlKtJz9LwriwrX86/z/MPkfcJZ03JSgmk8NakrKRAEu+mGWaXNs3slFLMdiHJHHDT/LKBZQPKcsv6lWWXecoyy9xlrjJnmb3MWqYv05TxZaSsJjiNRu3VpHraqKgDSFo9dVQ06K/u4D210WJ/dVRfM7PuIKXfDkNrlNveQcm0qLC9g4ObvWLGzLoOmord29zHgJIkWt2w7Y6w358RjeAPyG/OCEeLsXBXRphUR4unRN2+UVd8u76cZXAl6j3K/oMDciujAysbo/mVDaNZ54oOqqls7qCGyuZGyH2jO6hOqTdAyTdanaKDDsPWoZXN0DwUR7F6KauX+pS5ekBBl69YeQVoV8LJPknvUf5nF7xj+YoEdlhirVFXtBwofZXRB/VI9ZraUdVRXS2kmpnRNB9UXoFKKVRMvlHsZ84Pcphp8JfHZ9aNdNIRJELLIA2GVAwpAKkAUj4kEyQBEg+JypMj8Ugscjnyt8hfIxcif4mcj3waeTfyu8jbkTcipyOvRn4eORV5JfJy5KXIi5GTkRORI5GDkacjOyO3R9oiOyJbI1simyIbIxsiTZGayNiIJfKvUqL7Cv/7j/j9/w/oTBrNDQplbmRzdHJlYW0NCmVuZG9iag0KMjggMCBvYmoNCjE0MTE4DQplbmRvYmoNCjI3IDAgb2JqDQoyOTg4OA0KZW5kb2JqDQoyOSAwIG9iag0KPDwvVHlwZS9YUmVmL1dbMSA0IDJdL1NpemUgMzAvSW5mbyAxIDAgUi9Sb290IDIgMCBSL0lEWzxCNzYzMUVCNTcyODkwNDQzQTgzNjc1QzJDQTBGRDFFQz48Qjc2MzFFQjU3Mjg5MDQ0M0E4MzY3NUMyQ0EwRkQxRUM+XS9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDExND4+c3RyZWFtDQp4nGNgAIL//xkZGDhPMDAAKa69YIqbA0LZgSkGQQj1F0xNMQJTIpoQ6iSYEmMEU1XJYErwApgSqgBTwplgKmgrmOKDmMK/BKKSF6J9F5ji3ABR8gyiYQ7ETC8IZQixXRJCQew7fRpCbYJQTxgYALRaF5oNCmVuZHN0cmVhbQ0KZW5kb2JqDQpzdGFydHhyZWYNCjUyMTk2DQolJUVPRg0K\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t1234567890128\n+\t\t\t\n+\t\t\t\tCRONUS International\n+\t\t\t\n+\t\t\t\n+\t\t\t\tMain Street, 14\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tGB123456789\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tCRONUS International\n+\t\t\t\t123456789\n+\t\t\t\n+\t\t\t\n+\t\t\t\tJim Olive\n+\t\t\t\tJO@contoso.com\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t789456278\n+\t\t\t\n+\t\t\t\t8712345000004\n+\t\t\t\n+\t\t\t\n+\t\t\t\tThe Cannon Group PLC\n+\t\t\t\n+\t\t\t\n+\t\t\t\t192 Market Square\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tGB789456278\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tThe Cannon Group PLC\n+\t\t\t\t789456278\n+\t\t\t\n+\t\t\t\n+\t\t\t\tMr. Andy Teal\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t2026-01-22\n+\t\t\n+\t\t\t8712345000004\n+\t\t\t\n+\t\t\t\t192 Market Square\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t31\n+\t\t\n+\t\t\tGB12CPBK08929965044991\n+\t\t\t\n+\t\t\t\tBG99999\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t1 Month/2% 8 days\n+\t\n+\t\n+\t\t1000\n+\t\t\n+\t\t\t4000\n+\t\t\t1000\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t14000\n+\t\t14000\n+\t\t14140\n+\t\t0\n+\t\t0.00\n+\t\t0\n+\t\t14140\n+\t\n+\t\n+\t\t10000\n+\t\tItem\n+\t\t1\n+\t\t4000\n+\t\t\n+\t\t\tBicycle\n+\t\t\t\n+\t\t\t\t1000\n+\t\t\t\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\t\n+\t\t\t4000.00\n+\t\t\t1\n+\t\t\n+\t\n+\t\n+\t\t20000\n+\t\tItem\n+\t\t2\n+\t\t10000\n+\t\t\n+\t\t\tBicycle v2\n+\t\t\t\n+\t\t\t\t2000\n+\t\t\t\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\t\n+\t\t\t5000.00\n+\t\t\t2\n+\t\t\n+\t\n+\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\nindex 8a391d8117..7d3502ca5c 100644\n--- a/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\n+++ b/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\n@@ -21,6 +21,7 @@ using Microsoft.Inventory.Location;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.History;\n using Microsoft.Purchases.Payables;\n+using Microsoft.Purchases.Setup;\n using Microsoft.Purchases.Vendor;\n using Microsoft.Sales.Customer;\n using System.IO;\n@@ -884,6 +885,138 @@ codeunit 139883 \"E-Doc Process Test\"\n Assert.RecordCount(PurchaseLine, 2);\n end;\n \n+ [Test]\n+ procedure InvoicePostingDateDefaultsToWorkDateWhenSettingIsWorkDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Work Date\" (default), the created purchase invoice Posting Date equals WorkDate\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Work Date\" (default)\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL invoice (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-0.xml', TempEDocImportParams), 'The e-document should be processed');\n+\n+ // [THEN] Posting Date is WorkDate, not the document date\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(1, 1, 2027), PurchaseHeader.\"Posting Date\", 'Posting Date should be WorkDate when setting is Work Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure InvoicePostingDateUsesDocumentDateWhenSettingIsDocumentDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Document Date\", the created purchase invoice Posting Date equals the e-document's Document Date\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Document Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Document Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL invoice (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-no-currency.xml', TempEDocImportParams), 'The e-document should be processed');\n+\n+ // [THEN] Posting Date equals the Document Date from the PEPPOL file\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(22, 1, 2026), PurchaseHeader.\"Posting Date\", 'Posting Date should be Document Date when setting is Document Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure CreditMemoPostingDateDefaultsToWorkDateWhenSettingIsWorkDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Work Date\", the created purchase credit memo Posting Date equals WorkDate\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Work Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL credit note (IssueDate = 2026-02-15) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-creditnote-0.xml', TempEDocImportParams), 'The credit note e-document should be processed');\n+\n+ // [THEN] Posting Date is WorkDate\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(1, 1, 2027), PurchaseHeader.\"Posting Date\", 'Posting Date should be WorkDate when setting is Work Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure CreditMemoPostingDateUsesDocumentDateWhenSettingIsDocumentDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Document Date\", the created purchase credit memo Posting Date equals the e-document's Document Date\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Document Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Document Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL credit note (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-no-currency.xml', TempEDocImportParams), 'The credit note e-document should be processed');\n+\n+ // [THEN] Posting Date equals the Document Date from the PEPPOL file\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(22, 1, 2026), PurchaseHeader.\"Posting Date\", 'Posting Date should be Document Date when setting is Document Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n local procedure Initialize(Integration: Enum \"Service Integration\")\n var\n TransformationRule: Record \"Transformation Rule\";\n@@ -893,6 +1026,7 @@ codeunit 139883 \"E-Doc Process Test\"\n EDocPurchLineFieldSetup: Record \"ED Purchase Line Field Setup\";\n PurchInvHeader: Record \"Purch. Inv. Header\";\n VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n GLSetup: Record \"General Ledger Setup\";\n Currency: Record Currency;\n LibraryERM: Codeunit \"Library - ERM\";\n@@ -902,6 +1036,10 @@ codeunit 139883 \"E-Doc Process Test\"\n Clear(EDocImplState);\n EDocPurchLineFieldSetup.DeleteAll();\n \n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n PurchInvHeader.DeleteAll();\n VendorLedgerEntry.DeleteAll();\n \n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8251", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-20T13:52:50Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\EDocument\\App", "src\\Apps\\W1\\EDocument\\Test"], "patch": "diff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\nindex 556fbad792..6e67ed6537 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n@@ -26,6 +26,16 @@ pageextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n ApplicationArea = All;\n ToolTip = 'Specifies how the posting date is set on purchase invoices created from e-documents. Work Date uses the current work date. Document Date uses the document date from the e-document.';\n }\n+ field(\"Apply VAT Diff. For Purch EDoc\"; Rec.\"Apply VAT Diff. For Purch EDoc\")\n+ {\n+ ApplicationArea = All;\n+ ToolTip = 'Specifies whether VAT difference should be applied when matching incoming E-Document line with Purchase Order line';\n+ }\n+ field(\"Resolve VAT Group Purch EDoc\"; Rec.\"Resolve VAT Group Purch EDoc\")\n+ {\n+ ApplicationArea = All;\n+ ToolTip = 'Specifies whether to resolve VAT Product Group for purchase lines created from e-documents based on the VAT rate and the vendor''s VAT posting setup. If disabled, the VAT Product Group will not be identified based on the purchase e-document.';\n+ }\n }\n }\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\nindex 2dc0c9ccec..7da8eadd20 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n@@ -26,5 +26,17 @@ tableextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n Caption = 'E-Document Default Posting Date';\n DataClassification = CustomerContent;\n }\n+ field(6103; \"Apply VAT Diff. For Purch EDoc\"; Boolean)\n+ {\n+ Caption = 'Apply VAT Diff. For Purch. E-Doc.';\n+ DataClassification = CustomerContent;\n+ InitValue = true;\n+ }\n+ field(6104; \"Resolve VAT Group Purch EDoc\"; Boolean)\n+ {\n+ Caption = 'Resolve VAT Product Group for Purch. E-Doc.';\n+ DataClassification = CustomerContent;\n+ InitValue = true;\n+ }\n }\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\nindex 2eceac35ed..37f6fea09e 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n@@ -178,6 +178,7 @@ codeunit 6117 \"E-Doc. Create Purchase Invoice\" implements IEDocumentFinishDraft,\n EDocLineByReceipt.Close();\n PurchaseHeader.Modify();\n PurchCalcDiscByType.ApplyInvDiscBasedOnAmt(EDocumentPurchaseHeader.\"Total Discount\", PurchaseHeader);\n+ EDocPurchaseDocumentHelper.ApplyVATDifferenceToLines(PurchaseHeader, EDocumentPurchaseHeader);\n exit(PurchaseHeader);\n end;\n \ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\nindex 857e73d309..cfc2d04acd 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n@@ -7,7 +7,9 @@ namespace Microsoft.eServices.EDocument.Processing.Import;\n using Microsoft.eServices.EDocument;\n using Microsoft.eServices.EDocument.Processing;\n using Microsoft.eServices.EDocument.Processing.Import.Purchase;\n+using Microsoft.Finance.Currency;\n using Microsoft.Finance.Dimension;\n+using Microsoft.Finance.VAT.Setup;\n using Microsoft.Foundation.Attachment;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.Posting;\n@@ -40,6 +42,9 @@ codeunit 6402 \"E-Doc. Purch. Doc. Helper\"\n PurchaseLine.\"Variant Code\" := EDocumentPurchaseLine.\"[BC] Variant Code\";\n PurchaseLine.Type := EDocumentPurchaseLine.\"[BC] Purchase Line Type\";\n ValidateFieldWithContext(PurchaseLine, PurchaseLine.FieldNo(\"No.\"), EDocumentPurchaseLine.\"[BC] Purchase Type No.\");\n+ if EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\" <> '' then\n+ ValidateFieldWithContext(\n+ PurchaseLine, PurchaseLine.FieldNo(\"VAT Prod. Posting Group\"), EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\");\n if (PurchaseLine.Type = PurchaseLine.Type::\"G/L Account\") and HasTotalDiscount then\n ValidateFieldWithContext(PurchaseLine, PurchaseLine.FieldNo(\"Allow Invoice Disc.\"), true);\n PurchaseLine.Description := EDocumentPurchaseLine.Description;\n@@ -154,6 +159,45 @@ codeunit 6402 \"E-Doc. Purch. Doc. Helper\"\n EDocImpSessionTelemetry.SetBool('Totals Validation', TryValidateDocumentTotals(PurchaseHeader));\n end;\n \n+ procedure ApplyVATDifferenceToLines(PurchaseHeader: Record \"Purchase Header\"; EDocumentPurchaseHeader: Record \"E-Document Purchase Header\")\n+ var\n+ PurchaseLine: Record \"Purchase Line\";\n+ Currency: Record Currency;\n+ LineAmount: Decimal;\n+ TotalLineAmount, VATDiffRemainder, VATDiffForLine : Decimal;\n+ AppliedVATAmountDiff: Decimal;\n+ begin\n+ AppliedVATAmountDiff := EDocumentPurchaseHeader.GetAppliedVATAmountDiff();\n+ if AppliedVATAmountDiff = 0 then\n+ exit;\n+\n+ if PurchaseHeader.\"Currency Code\" = '' then\n+ Currency.InitRoundingPrecision()\n+ else\n+ Currency.Get(PurchaseHeader.\"Currency Code\");\n+\n+ TotalLineAmount := ComputeTotalLineAmount(EDocumentPurchaseHeader.\"E-Document Entry No.\", Currency.\"Amount Rounding Precision\");\n+ if TotalLineAmount = 0 then\n+ exit;\n+\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseHeader.\"Document Type\");\n+ PurchaseLine.SetRange(\"Document No.\", PurchaseHeader.\"No.\");\n+ PurchaseLine.SetFilter(Type, '<>%1', PurchaseLine.Type::\" \");\n+ if not PurchaseLine.FindSet() then\n+ exit;\n+\n+ VATDiffRemainder := 0;\n+ repeat\n+ LineAmount := PurchaseLine.\"Line Amount\" - PurchaseLine.\"Inv. Discount Amount\";\n+ if LineAmount <> 0 then begin\n+ VATDiffForLine := VATDiffRemainder + AppliedVATAmountDiff * LineAmount / TotalLineAmount;\n+ PurchaseLine.Validate(\"VAT Difference\", Round(VATDiffForLine, Currency.\"Amount Rounding Precision\"));\n+ VATDiffRemainder := VATDiffForLine - PurchaseLine.\"VAT Difference\";\n+ PurchaseLine.Modify(true);\n+ end;\n+ until PurchaseLine.Next() = 0;\n+ end;\n+\n procedure RevertCreatedDocument(EDocument: Record \"E-Document\")\n var\n PurchaseHeader: Record \"Purchase Header\";\n@@ -181,4 +225,27 @@ codeunit 6402 \"E-Doc. Purch. Doc. Helper\"\n exit;\n PurchaseHeader.Validate(\"Posting Date\", EDocumentPurchaseHeader.\"Document Date\");\n end;\n+\n+ procedure SetNormalReverseChargeFilter(var VATPostingSetup: Record \"VAT Posting Setup\"; VATBusPostingGroup: Code[20])\n+ begin\n+ VATPostingSetup.SetRange(\"VAT Bus. Posting Group\", VATBusPostingGroup);\n+ VATPostingSetup.SetFilter(\"VAT Calculation Type\", '%1|%2',\n+ VATPostingSetup.\"VAT Calculation Type\"::\"Normal VAT\",\n+ VATPostingSetup.\"VAT Calculation Type\"::\"Reverse Charge VAT\");\n+ end;\n+\n+ local procedure ComputeTotalLineAmount(EDocEntryNo: Integer; AmountRoundingPrecision: Decimal): Decimal\n+ var\n+ EDocPurchLine: Record \"E-Document Purchase Line\";\n+ TotalLineAmount: Decimal;\n+ begin\n+ EDocPurchLine.SetRange(\"E-Document Entry No.\", EDocEntryNo);\n+ if EDocPurchLine.FindSet() then\n+ repeat\n+ TotalLineAmount += Round(\n+ EDocPurchLine.Quantity * EDocPurchLine.\"Unit Price\" - EDocPurchLine.\"Total Discount\",\n+ AmountRoundingPrecision);\n+ until EDocPurchLine.Next() = 0;\n+ exit(TotalLineAmount);\n+ end;\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/EDocPreparePurchDraft.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/EDocPreparePurchDraft.Codeunit.al\nindex 23612228b1..2b267d5875 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/EDocPreparePurchDraft.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/EDocPreparePurchDraft.Codeunit.al\n@@ -8,8 +8,11 @@ using Microsoft.eServices.EDocument;\n using Microsoft.eServices.EDocument.Processing.AI;\n using Microsoft.eServices.EDocument.Processing.Import.Purchase;\n using Microsoft.eServices.EDocument.Processing.Interfaces;\n+using Microsoft.Finance.GeneralLedger.Setup;\n+using Microsoft.Finance.VAT.Setup;\n using Microsoft.Foundation.UOM;\n using Microsoft.Purchases.Document;\n+using Microsoft.Purchases.Setup;\n using Microsoft.Purchases.Vendor;\n using System.Log;\n \n@@ -31,11 +34,15 @@ codeunit 6406 \"EDoc Prepare Purch. Draft\"\n Vendor: Record Vendor;\n PurchaseOrder: Record \"Purchase Header\";\n EDocVendorAssignmentHistory: Record \"E-Doc. Vendor Assign. History\";\n+\n EDocPurchaseHistMapping: Codeunit \"E-Doc. Purchase Hist. Mapping\";\n EDocActivityLogSession: Codeunit \"E-Doc. Activity Log Session\";\n IUnitOfMeasureProvider: Interface IUnitOfMeasureProvider;\n IPurchaseLineProvider: Interface IPurchaseLineProvider;\n IPurchaseOrderProvider: Interface IPurchaseOrderProvider;\n+ LineAmount: Decimal;\n+ LineVATAmount: Decimal;\n+ TotalLineVATAmount: Decimal;\n begin\n IUnitOfMeasureProvider := EDocImportParameters.\"Processing Customizations\";\n IPurchaseLineProvider := EDocImportParameters.\"Processing Customizations\";\n@@ -72,16 +79,26 @@ codeunit 6406 \"EDoc Prepare Purch. Draft\"\n EDocumentPurchaseLine.Modify();\n until EDocumentPurchaseLine.Next() = 0;\n \n+ // Resolve VAT Product Posting Groups from extracted VAT rates\n+ ResolveVATProductPostingGroups(EDocument.\"Entry No\", EDocumentPurchaseHeader);\n+\n CopilotLineMatching(EDocument.\"Entry No\");\n end;\n \n Clear(EDocumentPurchaseLine);\n EDocumentPurchaseLine.SetRange(\"E-Document Entry No.\", EDocument.\"Entry No\");\n+ TotalLineVATAmount := 0;\n if EDocumentPurchaseLine.FindSet() then\n repeat\n+ LineAmount := Round(EDocumentPurchaseLine.Quantity * EDocumentPurchaseLine.\"Unit Price\" - EDocumentPurchaseLine.\"Total Discount\");\n+ LineVATAmount := Round(LineAmount * EDocumentPurchaseLine.\"VAT Rate\" / 100);\n+ TotalLineVATAmount += LineVATAmount;\n EDocImpSessionTelemetry.SetLine(EDocumentPurchaseLine.SystemId);\n until EDocumentPurchaseLine.Next() = 0;\n \n+ ComputeAndApplyVATAmountDifference(EDocumentPurchaseHeader, TotalLineVATAmount);\n+ EDocumentPurchaseHeader.Modify();\n+\n LogAllActivitySessionChanges(EDocActivityLogSession);\n \n if EDocActivityLogSession.EndSession() then;\n@@ -138,6 +155,72 @@ codeunit 6406 \"EDoc Prepare Purch. Draft\"\n ActivityLog.Log();\n end;\n \n+ local procedure ResolveVATProductPostingGroups(EDocumentEntryNo: Integer; EDocumentPurchaseHeader: Record \"E-Document Purchase Header\")\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ Vendor: Record Vendor;\n+ VATRate: Decimal;\n+ LineBase: Decimal;\n+ LineCount: Integer;\n+ begin\n+ if not PurchasesPayablesSetup.Get() then\n+ exit;\n+ if not PurchasesPayablesSetup.\"Resolve VAT Group Purch EDoc\" then\n+ exit;\n+ Vendor := EDocumentPurchaseHeader.GetBCVendor();\n+ if Vendor.\"No.\" = '' then\n+ exit;\n+ if Vendor.\"VAT Bus. Posting Group\" = '' then\n+ exit;\n+\n+ EDocumentPurchaseLine.SetRange(\"E-Document Entry No.\", EDocumentEntryNo);\n+ LineCount := EDocumentPurchaseLine.Count();\n+ if LineCount = 0 then\n+ exit;\n+\n+ if EDocumentPurchaseLine.FindSet() then\n+ repeat\n+ VATRate := EDocumentPurchaseLine.\"VAT Rate\";\n+\n+ // Single-line fallback: compute from header Total VAT\n+ if (VATRate = 0) and (LineCount = 1) and (EDocumentPurchaseHeader.\"Total VAT\" > 0) then begin\n+ LineBase := EDocumentPurchaseLine.Quantity * EDocumentPurchaseLine.\"Unit Price\" - EDocumentPurchaseLine.\"Total Discount\";\n+ if LineBase = 0 then\n+ LineBase := EDocumentPurchaseHeader.\"Sub Total\";\n+ if LineBase > 0 then\n+ VATRate := Round((EDocumentPurchaseHeader.\"Total VAT\" / LineBase) * 100, 0.01);\n+ end;\n+\n+ if VATRate > 0 then begin\n+ EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\" :=\n+ FindVATProductPostingGroup(Vendor.\"VAT Bus. Posting Group\", VATRate);\n+ EDocumentPurchaseLine.Modify();\n+ if EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\" = '' then\n+ EDocumentPurchaseLine.LogVATRateMismatch(Vendor.\"VAT Bus. Posting Group\", VATRate)\n+ else\n+ EDocumentPurchaseLine.LogVATRateResolved(Vendor.\"VAT Bus. Posting Group\", VATRate);\n+ end;\n+ until EDocumentPurchaseLine.Next() = 0;\n+ end;\n+\n+ local procedure FindVATProductPostingGroup(VATBusPostingGroup: Code[20]; VATRate: Decimal): Code[20]\n+ var\n+ VATPostingSetup: Record \"VAT Posting Setup\";\n+ EDocPurchDocHelper: Codeunit \"E-Doc. Purch. Doc. Helper\";\n+ CustomDimensions: Dictionary of [Text, Text];\n+ VATPostingGroupNotFoundLbl: Label 'VAT Product Posting Group not found for VAT Rate %1.', Comment = '%1 = VAT rate', Locked = true;\n+ begin\n+ EDocPurchDocHelper.SetNormalReverseChargeFilter(VATPostingSetup, VATBusPostingGroup);\n+ VATPostingSetup.SetRange(\"VAT %\", VATRate);\n+ if VATPostingSetup.Count() = 1 then begin\n+ VATPostingSetup.FindFirst();\n+ exit(VATPostingSetup.\"VAT Prod. Posting Group\");\n+ end;\n+ Session.LogMessage('0000TXZ', StrSubstNo(VATPostingGroupNotFoundLbl, VATRate), Verbosity::Warning, DataClassification::SystemMetadata, TelemetryScope::All, CustomDimensions);\n+ exit('');\n+ end;\n+\n local procedure CopilotLineMatching(EDocumentEntryNo: Integer)\n var\n EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n@@ -172,4 +255,64 @@ codeunit 6406 \"EDoc Prepare Purch. Draft\"\n if Codeunit.Run(Codeunit::\"E-Doc. Deferral Matching\", EDocumentPurchaseLine) then;\n end;\n end;\n+\n+ local procedure ComputeAndApplyVATAmountDifference(EDocumentPurchaseHeader: Record \"E-Document Purchase Header\"; TotalLineVATAmount: Decimal)\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ GeneralLedgerSetup: Record \"General Ledger Setup\";\n+ ActivityLog: Codeunit \"Activity Log Builder\";\n+ VATAmountDiff: Decimal;\n+ Reasoning: Text[250];\n+ VATDiffAppliedLbl: Label 'Applied VAT amount difference of %1 to reconcile document Total VAT %2 with computed Total Line VAT Amount %3.', Comment = '%1 = VAT difference, %2 = Total VAT, %3 = Total Line VAT Amount';\n+ VATDiffSkippedSetupLbl: Label 'VAT amount difference of %1 was not applied because Apply VAT Diff. For Purch. E-Doc. is disabled in Purchases & Payables Setup.', Comment = '%1 = VAT difference';\n+ VATDiffSkippedAllowLbl: Label 'VAT amount difference of %1 was not applied because Allow VAT Difference is disabled in Purchases & Payables Setup.', Comment = '%1 = VAT difference';\n+ VATDiffSkippedMaxLbl: Label 'VAT amount difference of %1 was not applied because it exceeds the Max. VAT Difference Allowed of %2 in General Ledger Setup.', Comment = '%1 = VAT difference, %2 = Max. VAT Difference Allowed';\n+ begin\n+ if (EDocumentPurchaseHeader.\"Total VAT\" = 0) or (TotalLineVATAmount = EDocumentPurchaseHeader.\"Total VAT\") then\n+ exit;\n+\n+ VATAmountDiff := EDocumentPurchaseHeader.\"Total VAT\" - TotalLineVATAmount;\n+\n+ if not PurchasesPayablesSetup.Get() then\n+ exit;\n+\n+ if not PurchasesPayablesSetup.\"Apply VAT Diff. For Purch EDoc\" then begin\n+ Reasoning := CopyStr(StrSubstNo(VATDiffSkippedSetupLbl, VATAmountDiff), 1, MaxStrLen(Reasoning));\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Header\", EDocumentPurchaseHeader.FieldNo(\"Total VAT\"), EDocumentPurchaseHeader.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::\"AL\")\n+ .Log();\n+ exit;\n+ end;\n+\n+ if not PurchasesPayablesSetup.\"Allow VAT Difference\" then begin\n+ Reasoning := CopyStr(StrSubstNo(VATDiffSkippedAllowLbl, VATAmountDiff), 1, MaxStrLen(Reasoning));\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Header\", EDocumentPurchaseHeader.FieldNo(\"Total VAT\"), EDocumentPurchaseHeader.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::\"AL\")\n+ .Log();\n+ exit;\n+ end;\n+\n+ if not GeneralLedgerSetup.Get() then\n+ exit;\n+ if Abs(VATAmountDiff) > GeneralLedgerSetup.\"Max. VAT Difference Allowed\" then begin\n+ Reasoning := CopyStr(StrSubstNo(VATDiffSkippedMaxLbl, VATAmountDiff, GeneralLedgerSetup.\"Max. VAT Difference Allowed\"), 1, MaxStrLen(Reasoning));\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Header\", EDocumentPurchaseHeader.FieldNo(\"Total VAT\"), EDocumentPurchaseHeader.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::\"AL\")\n+ .Log();\n+ exit;\n+ end;\n+\n+ Reasoning := CopyStr(StrSubstNo(VATDiffAppliedLbl, VATAmountDiff, EDocumentPurchaseHeader.\"Total VAT\", TotalLineVATAmount), 1, MaxStrLen(Reasoning));\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Header\", EDocumentPurchaseHeader.FieldNo(\"Total VAT\"), EDocumentPurchaseHeader.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::\"AL\")\n+ .Log();\n+ end;\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al\nindex a49e0ab6aa..ee70da225f 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al\n@@ -10,6 +10,7 @@ using Microsoft.Finance.Dimension;\n using Microsoft.Inventory.Item.Catalog;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.History;\n+using Microsoft.Purchases.Setup;\n \n page 6183 \"E-Doc. Purchase Draft Subform\"\n {\n@@ -71,6 +72,12 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n Lookup = true;\n ShowMandatory = true;\n }\n+ field(\"VAT Prod. Posting Group\"; Rec.\"[BC] VAT Prod. Posting Group\")\n+ {\n+ ApplicationArea = All;\n+ Lookup = true;\n+ Visible = VATProdPostGroupIsVisible;\n+ }\n field(\"Item Reference No.\"; Rec.\"[BC] Item Reference No.\")\n {\n ApplicationArea = All;\n@@ -333,7 +340,7 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n EDocPOMatching: Codeunit \"E-Doc. PO Matching\";\n AdditionalColumns, OrderMatchedCaption, MatchWarningsCaption, MatchWarningsStyleExpr : Text;\n LineAmount: Decimal;\n- DimVisible1, DimVisible2, HasAdditionalColumns, IsEDocumentMatchedToAnyPOLine, IsLineMatchedToOrderLine, IsLineMatchedToReceiptLine, HasEDocumentOrderMatchWarnings : Boolean;\n+ DimVisible1, DimVisible2, HasAdditionalColumns, IsEDocumentMatchedToAnyPOLine, IsLineMatchedToOrderLine, IsLineMatchedToReceiptLine, HasEDocumentOrderMatchWarnings, VATProdPostGroupIsVisible : Boolean;\n HistoryCantBeRetrievedErr: Label 'The purchase invoice that matched historically with this line can''t be opened.';\n \n trigger OnOpenPage()\n@@ -350,6 +357,7 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n trigger OnAfterGetCurrRecord()\n begin\n UpdatePOMatching();\n+ SetVATProductPostingGroupVisibility();\n end;\n \n trigger OnAfterGetRecord()\n@@ -362,6 +370,7 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n IsLineMatchedToReceiptLine := EDocPOMatching.IsEDocumentLineMatchedToAnyReceiptLine(EDocumentPurchaseLine);\n OrderMatchedCaption := IsLineMatchedToOrderLine ? GetSummaryOfMatchedOrders() : '';\n UpdateMatchWarnings();\n+ SetVATProductPostingGroupVisibility();\n end;\n \n internal procedure SetEDocumentPurchaseHeader(EDocPurchHeader: Record \"E-Document Purchase Header\")\n@@ -381,6 +390,14 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n DimVisible1, DimVisible2, DimOther, DimOther, DimOther, DimOther, DimOther, DimOther);\n end;\n \n+ local procedure SetVATProductPostingGroupVisibility()\n+ var\n+ PurchSetup: Record \"Purchases & Payables Setup\";\n+ begin\n+ PurchSetup.Get();\n+ VATProdPostGroupIsVisible := PurchSetup.\"Resolve VAT Group Purch EDoc\";\n+ end;\n+\n local procedure UpdateCalculatedAmounts(UpdateParentRecord: Boolean)\n var\n TotalEDocPurchaseLine: Record \"E-Document Purchase Line\";\n@@ -564,5 +581,4 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n if WarningDetails.Length() > 0 then\n Message(WarningDetails.ToText());\n end;\n-\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al\nindex 60c3eb6528..0dd57bc335 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al\n@@ -8,6 +8,7 @@ using Microsoft.eServices.EDocument;\n using Microsoft.eServices.EDocument.Processing.Import;\n using Microsoft.Foundation.Attachment;\n using Microsoft.Purchases.Document;\n+using Microsoft.Purchases.Setup;\n using Microsoft.Purchases.Vendor;\n using System.Feedback;\n using System.Telemetry;\n@@ -193,6 +194,16 @@ page 6181 \"E-Document Purchase Draft\"\n group(\"E-Document Details\")\n {\n ShowCaption = false;\n+ field(\"Applied VAT Amount Diff.\"; AppliedVATAmountDiff)\n+ {\n+ Caption = 'Applied VAT Amount Diff.';\n+ ToolTip = 'Specifies the VAT amount difference that was automatically applied to reconcile the document total VAT with the computed line VAT amounts.';\n+ Importance = Additional;\n+ Editable = false;\n+ Visible = ApplyVATDiffEnabled;\n+ AutoFormatType = 1;\n+ AutoFormatExpression = EDocumentPurchaseHeader.\"Currency Code\";\n+ }\n field(\"Amount Excl. VAT\"; EDocumentPurchaseHeader.\"Sub Total\")\n {\n Caption = 'Amount Excl. VAT';\n@@ -497,6 +508,7 @@ page 6181 \"E-Document Purchase Draft\"\n trigger OnOpenPage()\n var\n EDocumentDataStorage: Record \"E-Doc. Data Storage\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n EDocumentNotification: Codeunit \"E-Document Notification\";\n EDocPOMatching: Codeunit \"E-Doc. PO Matching\";\n MatchesRemovedMsg: Label 'This e-document was matched to purchase order lines, but the matches are no longer consistent with the current data. The matches have been removed';\n@@ -517,6 +529,8 @@ page 6181 \"E-Document Purchase Draft\"\n PageEditable := IsEditable();\n IsCreditMemo := Rec.\"Document Type\" = Enum::\"E-Document Type\"::\"Purchase Credit Memo\";\n EDocumentNotification.SendPurchaseDocumentDraftNotifications(Rec.\"Entry No\");\n+ if PurchasesPayablesSetup.Get() then\n+ ApplyVATDiffEnabled := PurchasesPayablesSetup.\"Apply VAT Diff. For Purch EDoc\";\n \n if Rec.\"Entry No\" <> 0 then\n Rec.SetRecFilter(); // Filter the record to only this instance to avoid navigation \n@@ -540,6 +554,8 @@ page 6181 \"E-Document Purchase Draft\"\n SetStyle();\n SetPageCaption();\n \n+ AppliedVATAmountDiff := EDocumentPurchaseHeader.GetAppliedVATAmountDiff();\n+\n Rec.CalcFields(\"Import Processing Status\");\n ShowFinalizeDraftAction := Rec.\"Import Processing Status\" in [Enum::\"Import E-Doc. Proc. Status\"::\"Ready for draft\", Enum::\"Import E-Doc. Proc. Status\"::\"Draft Ready\"];\n ShowAnalyzeDocumentAction :=\n@@ -775,4 +791,6 @@ page 6181 \"E-Document Purchase Draft\"\n ProcessingDocumentMsg: Label 'Processing document...';\n ResetDraftQst: Label 'All the changes that you may have made on the document draft will be lost. Do you want to continue?';\n PageEditable, HasPDFSource, IsCreditMemo : Boolean;\n+ ApplyVATDiffEnabled: Boolean;\n+ AppliedVATAmountDiff: Decimal;\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al\nindex 06a2997843..2abe927c57 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al\n@@ -6,7 +6,9 @@ namespace Microsoft.EServices.EDocument.Processing.Import.Purchase;\n \n using Microsoft.eServices.EDocument;\n using Microsoft.eServices.EDocument.Processing.Import;\n+using Microsoft.Finance.GeneralLedger.Setup;\n using Microsoft.Purchases.Document;\n+using Microsoft.Purchases.Setup;\n using Microsoft.Purchases.Vendor;\n using System.Telemetry;\n \n@@ -290,6 +292,45 @@ table 6100 \"E-Document Purchase Header\"\n if Vendor.Get(Rec.\"[BC] Vendor No.\") then;\n end;\n \n+ procedure GetAppliedVATAmountDiff(): Decimal\n+ var\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ GeneralLedgerSetup: Record \"General Ledger Setup\";\n+ LineAmount: Decimal;\n+ TotalLineVATAmount: Decimal;\n+ VATAmountDiff: Decimal;\n+ begin\n+ if Rec.\"Total VAT\" = 0 then\n+ exit(0);\n+\n+ if not PurchasesPayablesSetup.Get() then\n+ exit(0);\n+ if not PurchasesPayablesSetup.\"Apply VAT Diff. For Purch EDoc\" then\n+ exit(0);\n+ if not PurchasesPayablesSetup.\"Allow VAT Difference\" then\n+ exit(0);\n+ if not GeneralLedgerSetup.Get() then\n+ exit(0);\n+\n+ EDocumentPurchaseLine.SetRange(\"E-Document Entry No.\", Rec.\"E-Document Entry No.\");\n+ if EDocumentPurchaseLine.FindSet() then\n+ repeat\n+ LineAmount := Round(EDocumentPurchaseLine.Quantity * EDocumentPurchaseLine.\"Unit Price\" - EDocumentPurchaseLine.\"Total Discount\");\n+ TotalLineVATAmount += Round(LineAmount * EDocumentPurchaseLine.\"VAT Rate\" / 100);\n+ until EDocumentPurchaseLine.Next() = 0;\n+\n+ if TotalLineVATAmount = Rec.\"Total VAT\" then\n+ exit(0);\n+\n+ VATAmountDiff := Rec.\"Total VAT\" - TotalLineVATAmount;\n+\n+ if Abs(VATAmountDiff) > GeneralLedgerSetup.\"Max. VAT Difference Allowed\" then\n+ exit(0);\n+\n+ exit(VATAmountDiff);\n+ end;\n+\n internal procedure FeatureName(): Text\n begin\n exit('E-Document Matching Assistance');\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseLine.Table.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseLine.Table.al\nindex df4c126db9..7a2523070d 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseLine.Table.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseLine.Table.al\n@@ -11,6 +11,7 @@ using Microsoft.Finance.AllocationAccount;\n using Microsoft.Finance.Deferral;\n using Microsoft.Finance.Dimension;\n using Microsoft.Finance.GeneralLedger.Account;\n+using Microsoft.Finance.VAT.Setup;\n using Microsoft.FixedAssets.FixedAsset;\n using Microsoft.Foundation.UOM;\n using Microsoft.Inventory.Item;\n@@ -20,6 +21,7 @@ using Microsoft.Purchases.Document;\n using Microsoft.Purchases.History;\n using Microsoft.Purchases.Vendor;\n using Microsoft.Utilities;\n+using System.Log;\n using System.Reflection;\n using System.Utilities;\n \n@@ -208,6 +210,26 @@ table 6101 \"E-Document Purchase Line\"\n DimMgt.UpdateGlobalDimFromDimSetID(\"[BC] Dimension Set ID\", \"[BC] Shortcut Dimension 1 Code\", \"[BC] Shortcut Dimension 2 Code\");\n end;\n }\n+ field(110; \"[BC] VAT Prod. Posting Group\"; Code[20])\n+ {\n+ Caption = 'VAT Prod. Posting Group';\n+ ToolTip = 'Specifies the VAT product posting group resolved from the extracted VAT rate.';\n+ TableRelation = \"VAT Product Posting Group\";\n+\n+ trigger OnLookup()\n+ var\n+ Vendor: Record Vendor;\n+ VATPostingSetup: Record \"VAT Posting Setup\";\n+ EDocPurchDocHelper: Codeunit \"E-Doc. Purch. Doc. Helper\";\n+ begin\n+ Vendor := Rec.GetBCVendor();\n+ if Vendor.\"No.\" = '' then\n+ exit;\n+ EDocPurchDocHelper.SetNormalReverseChargeFilter(VATPostingSetup, Vendor.\"VAT Bus. Posting Group\");\n+ if Page.RunModal(Page::\"VAT Posting Setup\", VATPostingSetup) = Action::LookupOK then\n+ Validate(\"[BC] VAT Prod. Posting Group\", VATPostingSetup.\"VAT Prod. Posting Group\");\n+ end;\n+ }\n #endregion Validated fields\n \n #region Metadata fields [201-300]\n@@ -374,4 +396,52 @@ table 6101 \"E-Document Purchase Line\"\n exit(GetEDocumentPurchaseHeader().GetBCVendor());\n end;\n \n+ internal procedure LogVATRateMismatch(VendVATBusPostingGroupCode: Code[20]; VATRate: Decimal)\n+ var\n+ VATPostingSetup: Record \"VAT Posting Setup\";\n+ EDocPurchDocHelper: Codeunit \"E-Doc. Purch. Doc. Helper\";\n+ ActivityLog: Codeunit \"Activity Log Builder\";\n+ VATPostingSetupRef: RecordRef;\n+ Reasoning: Text[250];\n+ VATRateMismatchReasonLbl: Label 'VAT rate %1% extracted from the document could not be matched to a VAT Posting Setup for vendor''s VAT Business Posting Group %2.', Comment = '%1 = extracted VAT rate %, %2 = VAT Bus. Posting Group code';\n+ VATRateMismatchTitleLbl: Label 'VAT Posting Setup for %1', Comment = '%1 = VAT Bus. Posting Group code';\n+ begin\n+ EDocPurchDocHelper.SetNormalReverseChargeFilter(VATPostingSetup, VendVATBusPostingGroupCode);\n+ VATPostingSetupRef.GetTable(VATPostingSetup);\n+\n+ Reasoning := CopyStr(StrSubstNo(VATRateMismatchReasonLbl, Rec.\"VAT Rate\", VendVATBusPostingGroupCode), 1, MaxStrLen(Reasoning));\n+\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Line\", Rec.FieldNo(\"[BC] VAT Prod. Posting Group\"), Rec.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::AL)\n+ .SetReferenceSource(Page::\"VAT Posting Setup\", VATPostingSetupRef)\n+ .SetReferenceTitle(StrSubstNo(VATRateMismatchTitleLbl, VendVATBusPostingGroupCode))\n+ .Log();\n+ end;\n+\n+ internal procedure LogVATRateResolved(VendVATBusPostingGroupCode: Code[20]; VATRate: Decimal)\n+ var\n+ VATPostingSetup: Record \"VAT Posting Setup\";\n+ EDocPurchDocHelper: Codeunit \"E-Doc. Purch. Doc. Helper\";\n+ ActivityLog: Codeunit \"Activity Log Builder\";\n+ VATPostingSetupRef: RecordRef;\n+ Reasoning: Text[250];\n+ VATRateResolvedReasonLbl: Label 'VAT rate %1% extracted from the document was matched to VAT Product Posting Group %2 for vendor''s VAT Business Posting Group %3.', Comment = '%1 = extracted VAT rate %, %2 = resolved VAT Prod. Posting Group code, %3 = VAT Bus. Posting Group code';\n+ VATRateResolvedTitleLbl: Label 'VAT Posting Setup for %1', Comment = '%1 = VAT Bus. Posting Group code';\n+ begin\n+ EDocPurchDocHelper.SetNormalReverseChargeFilter(VATPostingSetup, VendVATBusPostingGroupCode);\n+ VATPostingSetupRef.GetTable(VATPostingSetup);\n+\n+ Reasoning := CopyStr(StrSubstNo(VATRateResolvedReasonLbl, VATRate, Rec.\"[BC] VAT Prod. Posting Group\", VendVATBusPostingGroupCode), 1, MaxStrLen(Reasoning));\n+\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Line\", Rec.FieldNo(\"[BC] VAT Prod. Posting Group\"), Rec.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::AL)\n+ .SetReferenceSource(Page::\"VAT Posting Setup\", VATPostingSetupRef)\n+ .SetReferenceTitle(StrSubstNo(VATRateResolvedTitleLbl, VendVATBusPostingGroupCode))\n+ .Log();\n+ end;\n+\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al\nindex 52ca55a954..ddc548d7f5 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al\n@@ -182,9 +182,60 @@ codeunit 6174 \"E-Document ADI Handler\" implements IStructureReceivedEDocument, I\n EDocumentJsonHelper.SetStringValueInField('productCode', MaxStrLen(TempEDocPurchaseLine.\"Product Code\"), FieldsJsonObject, TempEDocPurchaseLine.\"Product Code\");\n EDocumentJsonHelper.SetStringValueInField('unit', MaxStrLen(TempEDocPurchaseLine.\"Unit of Measure\"), FieldsJsonObject, TempEDocPurchaseLine.\"Unit of Measure\");\n EDocumentJsonHelper.SetDateValueInField('date', FieldsJsonObject, TempEDocPurchaseLine.Date);\n- EDocumentJsonHelper.SetCurrencyValueInField('tax', FieldsJsonObject, TempEDocPurchaseLine.\"VAT Rate\", TempEDocPurchaseLine.\"Currency Code\");\n+ ResolveVATRateFromADI(FieldsJsonObject, TempEDocPurchaseLine);\n if TempEDocPurchaseLine.\"Unit Price\" <> 0 then\n TempEDocPurchaseLine.\"Total Discount\" := (TempEDocPurchaseLine.\"Unit Price\" * TempEDocPurchaseLine.Quantity) - TempEDocPurchaseLine.\"Sub Total\";\n end;\n+\n+ local procedure ResolveVATRateFromADI(FieldsJsonObject: JsonObject; var TempEDocPurchaseLine: Record \"E-Document Purchase Line\" temporary)\n+ var\n+ TaxRateText: Text;\n+ TaxAmount: Decimal;\n+ TaxValueText: Text;\n+ ParsedRate: Decimal;\n+ UnusedCurrencyCode: Code[10];\n+ begin\n+ // 1. Prefer TaxRate (string) — unambiguous percentage field from ADI\n+ EDocumentJsonHelper.SetStringValueInField('taxRate', MaxStrLen(TaxRateText), FieldsJsonObject, TaxRateText);\n+ if TaxRateText <> '' then begin\n+ ParsedRate := ParsePercentageFromText(TaxRateText);\n+ if ParsedRate >= 0 then begin\n+ TempEDocPurchaseLine.\"VAT Rate\" := ParsedRate;\n+ exit;\n+ end;\n+ end;\n+\n+ // 2. Fallback to Tax field — but it's ambiguous (can be amount, %, or Y/N)\n+ EDocumentJsonHelper.SetCurrencyValueInField('tax', FieldsJsonObject, TaxAmount, UnusedCurrencyCode);\n+ if TaxAmount = 0 then\n+ exit;\n+\n+ // Check value_text to disambiguate\n+ EDocumentJsonHelper.SetStringValueInField('tax', MaxStrLen(TaxValueText), FieldsJsonObject, TaxValueText);\n+ if TaxValueText.Contains('%') then\n+ // Tax field contains a percentage (e.g., \"20%\")\n+ TempEDocPurchaseLine.\"VAT Rate\" := TaxAmount\n+ else\n+ // Tax field contains a monetary amount (e.g., \"$6.00\") — compute percentage\n+ if TempEDocPurchaseLine.\"Sub Total\" > 0 then\n+ TempEDocPurchaseLine.\"VAT Rate\" := Round((TaxAmount / TempEDocPurchaseLine.\"Sub Total\") * 100, 0.01);\n+ end;\n+\n+ local procedure ParsePercentageFromText(TaxRateText: Text): Decimal\n+ var\n+ CleanedText: Text;\n+ ParsedValue: Decimal;\n+ begin\n+ // Strip common non-numeric prefixes/suffixes: \"VAT 20%\", \"20%\", \"20.0%\", \"20\"\n+ CleanedText := TaxRateText.Replace('%', '').Trim();\n+ // Remove common prefixes like \"VAT \", \"Tax \", etc.\n+ if CleanedText.StartsWith('VAT ') then\n+ CleanedText := CopyStr(CleanedText, 5).Trim();\n+ if CleanedText.StartsWith('Tax ') then\n+ CleanedText := CopyStr(CleanedText, 5).Trim();\n+ if Evaluate(ParsedValue, CleanedText) then\n+ exit(ParsedValue);\n+ exit(-1); // Signal parse failure\n+ end;\n #pragma warning restore AA0139\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Setup/EDocumentUpgrade.Codeunit.al b/src/Apps/W1/EDocument/App/src/Setup/EDocumentUpgrade.Codeunit.al\nindex a10d76086c..aad2d5d532 100644\n--- a/src/Apps/W1/EDocument/App/src/Setup/EDocumentUpgrade.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Setup/EDocumentUpgrade.Codeunit.al\n@@ -8,6 +8,7 @@ using Microsoft.eServices.EDocument.IO;\n #if not CLEAN29\n using Microsoft.eServices.EDocument.Processing.Import;\n #endif\n+using Microsoft.Purchases.Setup;\n using System.Upgrade;\n \n codeunit 6168 \"E-Document Upgrade\"\n@@ -24,6 +25,7 @@ codeunit 6168 \"E-Document Upgrade\"\n UpgradeProcessDraftEnum();\n #endif\n UpgradeDataExchV2Defs();\n+ UpgradeEnableVATOptionsForPurchEDoc();\n end;\n \n local procedure UpgradeLogURLMaxLength()\n@@ -63,6 +65,7 @@ codeunit 6168 \"E-Document Upgrade\"\n PerCompanyUpgradeTags.Add(GetUpgradeLogURLMaxLengthUpgradeTag());\n PerCompanyUpgradeTags.Add(GetUpgradeProcessDraftEnumTag());\n PerCompanyUpgradeTags.Add(GetUpgradeDataExchV2DefsTag());\n+ PerCompanyUpgradeTags.Add(GetEnableVATOptionsForPurchEDocTag());\n end;\n \n internal procedure GetUpgradeLogURLMaxLengthUpgradeTag(): Code[250]\n@@ -92,9 +95,30 @@ codeunit 6168 \"E-Document Upgrade\"\n exit('MS-EDoc-ProcessDraftEnum-20260407');\n end;\n \n+ local procedure UpgradeEnableVATOptionsForPurchEDoc()\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ UpgradeTag: Codeunit \"Upgrade Tag\";\n+ begin\n+ if UpgradeTag.HasUpgradeTag(GetEnableVATOptionsForPurchEDocTag()) then\n+ exit;\n+\n+ if PurchasesPayablesSetup.Get() then begin\n+ PurchasesPayablesSetup.\"Apply VAT Diff. For Purch EDoc\" := true;\n+ PurchasesPayablesSetup.\"Resolve VAT Group Purch EDoc\" := true;\n+ PurchasesPayablesSetup.Modify();\n+ end;\n+\n+ UpgradeTag.SetUpgradeTag(GetEnableVATOptionsForPurchEDocTag());\n+ end;\n internal procedure GetUpgradeDataExchV2DefsTag(): Code[250]\n begin\n exit('MS-EDoc-DataExchV2Defs-20260521');\n end;\n+ \n+ internal procedure GetEnableVATOptionsForPurchEDocTag(): Code[250]\n+ begin\n+ exit('MS-EDoc-EnableVATOptionsForPurchEDoc-20260520');\n+ end;\n \n }\n\\ No newline at end of file\n", "FAIL_TO_PASS": [{"codeunitID": 135576, "functionName": ["PreparingPurchaseDraftResolvesVATProductPostingGroupFromLineVATRate", "PreparingDraftIgnoresFullVATSetupWhenResolvingPostingGroup", "PreparingDraftIgnoresSalesTaxSetupWhenResolvingPostingGroup", "PreparingDraftResolvesReverseChargeVATPostingGroup", "PreparingPurchaseDraftSetsVATRateMismatchWhenNoMatchingVATSetup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/EDocument/Test/app.json b/src/Apps/W1/EDocument/Test/app.json\nindex dcc263b2e6..e182d37bc9 100644\n--- a/src/Apps/W1/EDocument/Test/app.json\n+++ b/src/Apps/W1/EDocument/Test/app.json\n@@ -74,7 +74,7 @@\n },\n {\n \"from\": 135575,\n- \"to\": 135575\n+ \"to\": 135576\n },\n {\n \"from\": 135647,\n@@ -94,4 +94,4 @@\n \"features\": [\n \"TranslationFile\"\n ]\n-}\n+}\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/Test/src/Processing/EDocPurchVATTests.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Processing/EDocPurchVATTests.Codeunit.al\nnew file mode 100644\nindex 0000000000..bbc1455dba\n--- /dev/null\n+++ b/src/Apps/W1/EDocument/Test/src/Processing/EDocPurchVATTests.Codeunit.al\n@@ -0,0 +1,416 @@\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+namespace Microsoft.eServices.EDocument.Test;\n+\n+using Microsoft.eServices.EDocument;\n+using Microsoft.eServices.EDocument.Integration;\n+using Microsoft.eServices.EDocument.Processing.Import;\n+using Microsoft.eServices.EDocument.Processing.Import.Purchase;\n+using Microsoft.Finance.Currency;\n+using Microsoft.Finance.GeneralLedger.Setup;\n+using Microsoft.Finance.VAT.Setup;\n+using Microsoft.Foundation.Company;\n+using Microsoft.Purchases.History;\n+using Microsoft.Purchases.Payables;\n+using Microsoft.Purchases.Setup;\n+using Microsoft.Purchases.Vendor;\n+using Microsoft.Sales.Customer;\n+using System.IO;\n+using System.TestLibraries.Utilities;\n+\n+codeunit 135576 \"E-Doc Purch. VAT Tests\"\n+{\n+ Subtype = Test;\n+ TestType = IntegrationTest;\n+\n+ var\n+ Vendor: Record Vendor;\n+ Customer: Record Customer;\n+ EDocumentService: Record \"E-Document Service\";\n+ Assert: Codeunit Assert;\n+ LibraryVariableStorage: Codeunit \"Library - Variable Storage\";\n+ LibraryEDoc: Codeunit \"Library - E-Document\";\n+ EDocImplState: Codeunit \"E-Doc. Impl. State\";\n+ LibraryLowerPermission: Codeunit \"Library - Lower Permissions\";\n+ LibrarySetupStorage: Codeunit \"Library - Setup Storage\";\n+ IsInitialized: Boolean;\n+\n+ [Test]\n+ procedure PreparingPurchaseDraftResolvesVATProductPostingGroupFromLineVATRate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ EDocumentPurchaseHeader: Record \"E-Document Purchase Header\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ TempEDocImportParameters: Record \"E-Doc. Import Parameters\";\n+ Vendor2: Record Vendor;\n+ CompanyInformation: Record \"Company Information\";\n+ VATPostingSetup2: Record \"VAT Posting Setup\";\n+ VATProductPostingGroup: Record \"VAT Product Posting Group\";\n+ EDocumentProcessing: Codeunit \"E-Document Processing\";\n+ EDocImport: Codeunit \"E-Doc. Import\";\n+ LibraryERM: Codeunit \"Library - ERM\";\n+ begin\n+ // [SCENARIO] When a draft line has a VAT Rate and a matching VAT Posting Setup exists, Prepare Draft resolves the VAT Prod. Posting Group\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ SetResolveVATProductGroupInPurchSetup(true);\n+ LibraryEDoc.CreateInboundEDocument(EDocument, EDocumentService);\n+\n+ // [GIVEN] A vendor with a known VAT Bus. Posting Group\n+ CompanyInformation.GetRecordOnce();\n+ Vendor2.\"Country/Region Code\" := CompanyInformation.\"Country/Region Code\";\n+ Vendor2.\"No.\" := 'EDOC001';\n+ Vendor2.\"VAT Registration No.\" := 'XXXXXXX001';\n+ Vendor2.\"VAT Bus. Posting Group\" := Vendor.\"VAT Bus. Posting Group\";\n+ Vendor2.Insert();\n+\n+ // [GIVEN] A VAT Posting Setup with VAT % = 10 for the vendor's bus posting group\n+ LibraryERM.CreateVATProductPostingGroup(VATProductPostingGroup);\n+ VATPostingSetup2.\"VAT Bus. Posting Group\" := Vendor2.\"VAT Bus. Posting Group\";\n+ VATPostingSetup2.\"VAT Prod. Posting Group\" := VATProductPostingGroup.Code;\n+ VATPostingSetup2.\"VAT Calculation Type\" := VATPostingSetup2.\"VAT Calculation Type\"::\"Normal VAT\";\n+ VATPostingSetup2.\"VAT %\" := 10;\n+ VATPostingSetup2.\"Sales VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.\"Purchase VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.Insert();\n+\n+ // [GIVEN] E-Document purchase header and line with VAT Rate = 10\n+ EDocumentPurchaseHeader.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseHeader.\"Vendor VAT Id\" := Vendor2.\"VAT Registration No.\";\n+ EDocumentPurchaseHeader.Insert();\n+ EDocumentPurchaseLine.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseLine.Description := 'Test VAT resolution';\n+ EDocumentPurchaseLine.\"VAT Rate\" := 10;\n+ EDocumentPurchaseLine.Insert();\n+\n+ // [WHEN] Prepare Draft is run\n+ EDocumentProcessing.ModifyEDocumentProcessingStatus(EDocument, \"Import E-Doc. Proc. Status\"::\"Ready for draft\");\n+ TempEDocImportParameters.\"Step to Run\" := \"Import E-Document Steps\"::\"Prepare draft\";\n+ EDocImport.ProcessIncomingEDocument(EDocument, TempEDocImportParameters);\n+\n+ // [THEN] The VAT Prod. Posting Group is resolved from the matching setup\n+ EDocumentPurchaseLine.SetRecFilter();\n+ EDocumentPurchaseLine.FindFirst();\n+ Assert.AreEqual(VATProductPostingGroup.Code, EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\", 'The VAT Prod. Posting Group should be resolved from the matching VAT Posting Setup.');\n+\n+ // Cleanup\n+ Vendor2.SetRecFilter();\n+ Vendor2.Delete();\n+ VATPostingSetup2.SetRecFilter();\n+ VATPostingSetup2.Delete();\n+ VATProductPostingGroup.SetRecFilter();\n+ VATProductPostingGroup.Delete();\n+ end;\n+\n+ [Test]\n+ procedure PreparingPurchaseDraftSetsVATRateMismatchWhenNoMatchingVATSetup()\n+ var\n+ EDocument: Record \"E-Document\";\n+ EDocumentPurchaseHeader: Record \"E-Document Purchase Header\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ TempEDocImportParameters: Record \"E-Doc. Import Parameters\";\n+ Vendor2: Record Vendor;\n+ CompanyInformation: Record \"Company Information\";\n+ EDocumentProcessing: Codeunit \"E-Document Processing\";\n+ EDocImport: Codeunit \"E-Doc. Import\";\n+ begin\n+ // [SCENARIO] When a draft line has a VAT Rate but no matching VAT Posting Setup exists, Prepare Draft leaves the field blank and sets the mismatch flag\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ SetResolveVATProductGroupInPurchSetup(true);\n+ LibraryEDoc.CreateInboundEDocument(EDocument, EDocumentService);\n+\n+ // [GIVEN] A vendor with a known VAT Bus. Posting Group\n+ CompanyInformation.GetRecordOnce();\n+ Vendor2.\"Country/Region Code\" := CompanyInformation.\"Country/Region Code\";\n+ Vendor2.\"No.\" := 'EDOC001';\n+ Vendor2.\"VAT Registration No.\" := 'XXXXXXX001';\n+ Vendor2.\"VAT Bus. Posting Group\" := Vendor.\"VAT Bus. Posting Group\";\n+ Vendor2.Insert();\n+\n+ // [GIVEN] E-Document purchase header and line with VAT Rate = 99 (no matching setup)\n+ EDocumentPurchaseHeader.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseHeader.\"Vendor VAT Id\" := Vendor2.\"VAT Registration No.\";\n+ EDocumentPurchaseHeader.Insert();\n+ EDocumentPurchaseLine.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseLine.Description := 'Test VAT mismatch';\n+ EDocumentPurchaseLine.\"VAT Rate\" := 99;\n+ EDocumentPurchaseLine.Insert();\n+\n+ // [WHEN] Prepare Draft is run\n+ EDocumentProcessing.ModifyEDocumentProcessingStatus(EDocument, \"Import E-Doc. Proc. Status\"::\"Ready for draft\");\n+ TempEDocImportParameters.\"Step to Run\" := \"Import E-Document Steps\"::\"Prepare draft\";\n+ EDocImport.ProcessIncomingEDocument(EDocument, TempEDocImportParameters);\n+\n+ // [THEN] The VAT Prod. Posting Group is blank and mismatch flag is set\n+ EDocumentPurchaseLine.SetRecFilter();\n+ EDocumentPurchaseLine.FindFirst();\n+ Assert.AreEqual('', EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\", 'The VAT Prod. Posting Group should be blank when no matching VAT Posting Setup exists.');\n+\n+ // Cleanup\n+ Vendor2.SetRecFilter();\n+ Vendor2.Delete();\n+ end;\n+\n+ [Test]\n+ procedure PreparingDraftIgnoresFullVATSetupWhenResolvingPostingGroup()\n+ var\n+ EDocument: Record \"E-Document\";\n+ EDocumentPurchaseHeader: Record \"E-Document Purchase Header\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ TempEDocImportParameters: Record \"E-Doc. Import Parameters\";\n+ Vendor2: Record Vendor;\n+ CompanyInformation: Record \"Company Information\";\n+ VATPostingSetup2: Record \"VAT Posting Setup\";\n+ VATProductPostingGroup: Record \"VAT Product Posting Group\";\n+ EDocumentProcessing: Codeunit \"E-Document Processing\";\n+ EDocImport: Codeunit \"E-Doc. Import\";\n+ LibraryERM: Codeunit \"Library - ERM\";\n+ begin\n+ // [SCENARIO] Full VAT setups must not be matched during VAT Posting Group resolution\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ SetResolveVATProductGroupInPurchSetup(true);\n+ LibraryEDoc.CreateInboundEDocument(EDocument, EDocumentService);\n+\n+ // [GIVEN] A vendor\n+ CompanyInformation.GetRecordOnce();\n+ Vendor2.\"Country/Region Code\" := CompanyInformation.\"Country/Region Code\";\n+ Vendor2.\"No.\" := 'EDOC001';\n+ Vendor2.\"VAT Registration No.\" := 'XXXXXXX001';\n+ Vendor2.\"VAT Bus. Posting Group\" := Vendor.\"VAT Bus. Posting Group\";\n+ Vendor2.Insert();\n+\n+ // [GIVEN] A Full VAT Posting Setup with VAT % = 10\n+ LibraryERM.CreateVATProductPostingGroup(VATProductPostingGroup);\n+ VATPostingSetup2.\"VAT Bus. Posting Group\" := Vendor2.\"VAT Bus. Posting Group\";\n+ VATPostingSetup2.\"VAT Prod. Posting Group\" := VATProductPostingGroup.Code;\n+ VATPostingSetup2.\"VAT Calculation Type\" := VATPostingSetup2.\"VAT Calculation Type\"::\"Full VAT\";\n+ VATPostingSetup2.\"VAT %\" := 10;\n+ VATPostingSetup2.\"Sales VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.\"Purchase VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.Insert();\n+\n+ // [GIVEN] E-Document line with VAT Rate = 10\n+ EDocumentPurchaseHeader.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseHeader.\"Vendor VAT Id\" := Vendor2.\"VAT Registration No.\";\n+ EDocumentPurchaseHeader.Insert();\n+ EDocumentPurchaseLine.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseLine.Description := 'Test Full VAT ignored';\n+ EDocumentPurchaseLine.\"VAT Rate\" := 10;\n+ EDocumentPurchaseLine.Insert();\n+\n+ // [WHEN] Prepare Draft is run\n+ EDocumentProcessing.ModifyEDocumentProcessingStatus(EDocument, \"Import E-Doc. Proc. Status\"::\"Ready for draft\");\n+ TempEDocImportParameters.\"Step to Run\" := \"Import E-Document Steps\"::\"Prepare draft\";\n+ EDocImport.ProcessIncomingEDocument(EDocument, TempEDocImportParameters);\n+\n+ // [THEN] Full VAT setup is not matched\n+ EDocumentPurchaseLine.SetRecFilter();\n+ EDocumentPurchaseLine.FindFirst();\n+ Assert.AreEqual('', EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\", 'Full VAT setups must not be matched.');\n+\n+ // Cleanup\n+ Vendor2.SetRecFilter();\n+ Vendor2.Delete();\n+ VATPostingSetup2.SetRecFilter();\n+ VATPostingSetup2.Delete();\n+ VATProductPostingGroup.SetRecFilter();\n+ VATProductPostingGroup.Delete();\n+ end;\n+\n+ [Test]\n+ procedure PreparingDraftIgnoresSalesTaxSetupWhenResolvingPostingGroup()\n+ var\n+ EDocument: Record \"E-Document\";\n+ EDocumentPurchaseHeader: Record \"E-Document Purchase Header\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ TempEDocImportParameters: Record \"E-Doc. Import Parameters\";\n+ Vendor2: Record Vendor;\n+ CompanyInformation: Record \"Company Information\";\n+ VATPostingSetup2: Record \"VAT Posting Setup\";\n+ VATProductPostingGroup: Record \"VAT Product Posting Group\";\n+ EDocumentProcessing: Codeunit \"E-Document Processing\";\n+ EDocImport: Codeunit \"E-Doc. Import\";\n+ LibraryERM: Codeunit \"Library - ERM\";\n+ begin\n+ // [SCENARIO] Sales Tax setups must not be matched during VAT Posting Group resolution\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ SetResolveVATProductGroupInPurchSetup(true);\n+ LibraryEDoc.CreateInboundEDocument(EDocument, EDocumentService);\n+\n+ // [GIVEN] A vendor\n+ CompanyInformation.GetRecordOnce();\n+ Vendor2.\"Country/Region Code\" := CompanyInformation.\"Country/Region Code\";\n+ Vendor2.\"No.\" := 'EDOC001';\n+ Vendor2.\"VAT Registration No.\" := 'XXXXXXX001';\n+ Vendor2.\"VAT Bus. Posting Group\" := Vendor.\"VAT Bus. Posting Group\";\n+ Vendor2.Insert();\n+\n+ // [GIVEN] A Sales Tax Posting Setup with VAT % = 10\n+ LibraryERM.CreateVATProductPostingGroup(VATProductPostingGroup);\n+ VATPostingSetup2.\"VAT Bus. Posting Group\" := Vendor2.\"VAT Bus. Posting Group\";\n+ VATPostingSetup2.\"VAT Prod. Posting Group\" := VATProductPostingGroup.Code;\n+ VATPostingSetup2.\"VAT Calculation Type\" := VATPostingSetup2.\"VAT Calculation Type\"::\"Sales Tax\";\n+ VATPostingSetup2.\"VAT %\" := 10;\n+ VATPostingSetup2.\"Sales VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.\"Purchase VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.Insert();\n+\n+ // [GIVEN] E-Document line with VAT Rate = 10\n+ EDocumentPurchaseHeader.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseHeader.\"Vendor VAT Id\" := Vendor2.\"VAT Registration No.\";\n+ EDocumentPurchaseHeader.Insert();\n+ EDocumentPurchaseLine.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseLine.Description := 'Test Sales Tax ignored';\n+ EDocumentPurchaseLine.\"VAT Rate\" := 10;\n+ EDocumentPurchaseLine.Insert();\n+\n+ // [WHEN] Prepare Draft is run\n+ EDocumentProcessing.ModifyEDocumentProcessingStatus(EDocument, \"Import E-Doc. Proc. Status\"::\"Ready for draft\");\n+ TempEDocImportParameters.\"Step to Run\" := \"Import E-Document Steps\"::\"Prepare draft\";\n+ EDocImport.ProcessIncomingEDocument(EDocument, TempEDocImportParameters);\n+\n+ // [THEN] Sales Tax setup is not matched\n+ EDocumentPurchaseLine.SetRecFilter();\n+ EDocumentPurchaseLine.FindFirst();\n+ Assert.AreEqual('', EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\", 'Sales Tax setups must not be matched.');\n+\n+ // Cleanup\n+ Vendor2.SetRecFilter();\n+ Vendor2.Delete();\n+ VATPostingSetup2.SetRecFilter();\n+ VATPostingSetup2.Delete();\n+ VATProductPostingGroup.SetRecFilter();\n+ VATProductPostingGroup.Delete();\n+ end;\n+\n+ [Test]\n+ procedure PreparingDraftResolvesReverseChargeVATPostingGroup()\n+ var\n+ EDocument: Record \"E-Document\";\n+ EDocumentPurchaseHeader: Record \"E-Document Purchase Header\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ TempEDocImportParameters: Record \"E-Doc. Import Parameters\";\n+ Vendor2: Record Vendor;\n+ CompanyInformation: Record \"Company Information\";\n+ VATPostingSetup2: Record \"VAT Posting Setup\";\n+ VATProductPostingGroup: Record \"VAT Product Posting Group\";\n+ EDocumentProcessing: Codeunit \"E-Document Processing\";\n+ EDocImport: Codeunit \"E-Doc. Import\";\n+ LibraryERM: Codeunit \"Library - ERM\";\n+ begin\n+ // [SCENARIO] Reverse Charge VAT setups should be matched during VAT Posting Group resolution\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ SetResolveVATProductGroupInPurchSetup(true);\n+ LibraryEDoc.CreateInboundEDocument(EDocument, EDocumentService);\n+\n+ // [GIVEN] A vendor\n+ CompanyInformation.GetRecordOnce();\n+ Vendor2.\"Country/Region Code\" := CompanyInformation.\"Country/Region Code\";\n+ Vendor2.\"No.\" := 'EDOC001';\n+ Vendor2.\"VAT Registration No.\" := 'XXXXXXX001';\n+ Vendor2.\"VAT Bus. Posting Group\" := Vendor.\"VAT Bus. Posting Group\";\n+ Vendor2.Insert();\n+\n+ // [GIVEN] A Reverse Charge VAT Posting Setup with VAT % = 20\n+ LibraryERM.CreateVATProductPostingGroup(VATProductPostingGroup);\n+ VATPostingSetup2.\"VAT Bus. Posting Group\" := Vendor2.\"VAT Bus. Posting Group\";\n+ VATPostingSetup2.\"VAT Prod. Posting Group\" := VATProductPostingGroup.Code;\n+ VATPostingSetup2.\"VAT Calculation Type\" := VATPostingSetup2.\"VAT Calculation Type\"::\"Reverse Charge VAT\";\n+ VATPostingSetup2.\"VAT %\" := 20;\n+ VATPostingSetup2.\"Sales VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.\"Purchase VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.\"Reverse Chrg. VAT Acc.\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.Insert();\n+\n+ // [GIVEN] E-Document line with VAT Rate = 20\n+ EDocumentPurchaseHeader.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseHeader.\"Vendor VAT Id\" := Vendor2.\"VAT Registration No.\";\n+ EDocumentPurchaseHeader.Insert();\n+ EDocumentPurchaseLine.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseLine.Description := 'Test Reverse Charge resolved';\n+ EDocumentPurchaseLine.\"VAT Rate\" := 20;\n+ EDocumentPurchaseLine.Insert();\n+\n+ // [WHEN] Prepare Draft is run\n+ EDocumentProcessing.ModifyEDocumentProcessingStatus(EDocument, \"Import E-Doc. Proc. Status\"::\"Ready for draft\");\n+ TempEDocImportParameters.\"Step to Run\" := \"Import E-Document Steps\"::\"Prepare draft\";\n+ EDocImport.ProcessIncomingEDocument(EDocument, TempEDocImportParameters);\n+\n+ // [THEN] Reverse Charge VAT setup is matched\n+ EDocumentPurchaseLine.SetRecFilter();\n+ EDocumentPurchaseLine.FindFirst();\n+ Assert.AreEqual(VATProductPostingGroup.Code, EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\", 'Reverse Charge VAT setups should be matched.');\n+\n+ // Cleanup\n+ Vendor2.SetRecFilter();\n+ Vendor2.Delete();\n+ VATPostingSetup2.SetRecFilter();\n+ VATPostingSetup2.Delete();\n+ VATProductPostingGroup.SetRecFilter();\n+ VATProductPostingGroup.Delete();\n+ end;\n+\n+ local procedure Initialize(Integration: Enum \"Service Integration\")\n+ var\n+ TransformationRule: Record \"Transformation Rule\";\n+ EDocument: Record \"E-Document\";\n+ EDocDataStorage: Record \"E-Doc. Data Storage\";\n+ EDocumentServiceStatus: Record \"E-Document Service Status\";\n+ EDocPurchLineFieldSetup: Record \"ED Purchase Line Field Setup\";\n+ PurchInvHeader: Record \"Purch. Inv. Header\";\n+ VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ GLSetup: Record \"General Ledger Setup\";\n+ Currency: Record Currency;\n+ LibraryERM: Codeunit \"Library - ERM\";\n+ begin\n+ LibrarySetupStorage.Restore();\n+ LibraryLowerPermission.SetOutsideO365Scope();\n+ LibraryVariableStorage.Clear();\n+ Clear(EDocImplState);\n+ EDocPurchLineFieldSetup.DeleteAll();\n+\n+ PurchInvHeader.DeleteAll();\n+ VendorLedgerEntry.DeleteAll();\n+\n+ if IsInitialized then\n+ exit;\n+\n+ GLSetup.GetRecordOnce();\n+ GLSetup.\"VAT Reporting Date Usage\" := GLSetup.\"VAT Reporting Date Usage\"::Disabled;\n+ GLSetup.Modify();\n+\n+ // Set a currency that can be used across all localizations\n+ Currency.Init();\n+ Currency.Validate(Code, 'XYZ');\n+ if Currency.Insert(true) then\n+ LibraryERM.CreateExchangeRate(Currency.Code, WorkDate(), 1.0, 1.0);\n+\n+ EDocument.DeleteAll();\n+ EDocumentServiceStatus.DeleteAll();\n+ EDocumentService.DeleteAll();\n+ EDocDataStorage.DeleteAll();\n+\n+ LibraryEDoc.SetupStandardVAT();\n+ LibraryEDoc.SetupStandardSalesScenario(Customer, EDocumentService, Enum::\"E-Document Format\"::Mock, Integration);\n+ LibraryEDoc.SetupStandardPurchaseScenario(Vendor, EDocumentService, Enum::\"E-Document Format\"::Mock, Integration);\n+ EDocumentService.\"Import Process\" := \"E-Document Import Process\"::\"Version 2.0\";\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ TransformationRule.DeleteAll();\n+ TransformationRule.CreateDefaultTransformations();\n+ LibrarySetupStorage.SavePurchasesSetup();\n+\n+ IsInitialized := true;\n+ end;\n+\n+ local procedure SetResolveVATProductGroupInPurchSetup(NewResolveVATProductGroup: Boolean)\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ begin\n+ PurchasesPayablesSetup.Get();\n+ PurchasesPayablesSetup.Validate(\"Resolve VAT Group Purch EDoc\", NewResolveVATProductGroup);\n+ PurchasesPayablesSetup.Modify();\n+ end;\n+}\ndiff --git a/src/Apps/W1/EDocument/Test/src/Processing/EDocStructuredValidations.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Processing/EDocStructuredValidations.Codeunit.al\nindex 98a99e284b..8245505fa7 100644\n--- a/src/Apps/W1/EDocument/Test/src/Processing/EDocStructuredValidations.Codeunit.al\n+++ b/src/Apps/W1/EDocument/Test/src/Processing/EDocStructuredValidations.Codeunit.al\n@@ -56,7 +56,7 @@ codeunit 139894 \"EDoc Structured Validations\"\n Assert.AreEqual('A123', EDocumentPurchaseLine.\"Product Code\", 'The product code in the purchase line does not allign with the mock data.');\n Assert.AreEqual('hours', EDocumentPurchaseLine.\"Unit of Measure\", 'The unit of measure in the purchase line does not allign with the mock data.');\n Assert.AreEqual(DMY2Date(4, 3, 2021), EDocumentPurchaseLine.Date, 'The date in the purchase line does not allign with the mock data.');\n- Assert.AreEqual(6, EDocumentPurchaseLine.\"VAT Rate\", 'The amount in the purchase line does not allign with the mock data.');\n+ Assert.AreEqual(10, EDocumentPurchaseLine.\"VAT Rate\", 'The VAT rate in the purchase line does not match the expected percentage.');\n \n EDocumentPurchaseLine.Next();\n Assert.AreEqual(30, EDocumentPurchaseLine.\"Sub Total\", 'The amount in the purchase line does not allign with the mock data.');\n@@ -67,7 +67,7 @@ codeunit 139894 \"EDoc Structured Validations\"\n Assert.AreEqual('B456', EDocumentPurchaseLine.\"Product Code\", 'The product code in the purchase line does not allign with the mock data.');\n Assert.AreEqual('', EDocumentPurchaseLine.\"Unit of Measure\", 'The unit of measure in the purchase line does not allign with the mock data.');\n Assert.AreEqual(DMY2Date(5, 3, 2021), EDocumentPurchaseLine.Date, 'The date in the purchase line does not allign with the mock data.');\n- Assert.AreEqual(3, EDocumentPurchaseLine.\"VAT Rate\", 'The amount in the purchase line does not allign with the mock data.');\n+ Assert.AreEqual(10, EDocumentPurchaseLine.\"VAT Rate\", 'The VAT rate in the purchase line does not match the expected percentage.');\n \n EDocumentPurchaseLine.Next();\n Assert.AreEqual(10, EDocumentPurchaseLine.\"Sub Total\", 'The amount does not allign with the mock data.');\n@@ -77,7 +77,7 @@ codeunit 139894 \"EDoc Structured Validations\"\n Assert.AreEqual('C789', EDocumentPurchaseLine.\"Product Code\", 'The product code does not allign with the mock data.');\n Assert.AreEqual('pages', EDocumentPurchaseLine.\"Unit of Measure\", 'The unit of measure does not allign with the mock data.');\n Assert.AreEqual(DMY2Date(6, 3, 2021), EDocumentPurchaseLine.Date, 'The date does not allign with the mock data.');\n- Assert.AreEqual(1, EDocumentPurchaseLine.\"VAT Rate\", 'The amount does not allign with the mock data.');\n+ Assert.AreEqual(10, EDocumentPurchaseLine.\"VAT Rate\", 'The VAT rate in the purchase line does not match the expected percentage.');\n end;\n \n internal procedure AssertMinimalCAPIDocumentParsed(EDocumentEntryNo: Integer)\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7414", "base_commit": "f2762782853b2527241f8ddd024f8153dda0a1ad", "created_at": "2026-03-26T20:40:25Z", "environment_setup_version": "28.0", "project_paths": ["src\\Apps\\W1\\Shopify\\App", "src\\Apps\\W1\\Shopify\\Test"], "patch": "diff --git a/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al b/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al\nindex 48dc876162..5cb2a5d3c1 100644\n--- a/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al\n+++ b/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al\n@@ -170,6 +170,10 @@ page 30101 \"Shpfy Shop Card\"\n {\n ApplicationArea = All;\n }\n+ field(SyncHSCodeAndCountry; Rec.\"Sync HS Code and Country\")\n+ {\n+ ApplicationArea = All;\n+ }\n field(UOMAsVariant; Rec.\"UoM as Variant\")\n {\n ApplicationArea = All;\ndiff --git a/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al b/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al\nindex 311f89bf8e..8b29c15807 100644\n--- a/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al\n+++ b/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al\n@@ -950,6 +950,13 @@ table 30102 \"Shpfy Shop\"\n DataClassification = SystemMetadata;\n InitValue = true;\n }\n+ field(209; \"Sync HS Code and Country\"; Boolean)\n+ {\n+ Caption = 'Sync HS Code and Country of Origin';\n+ ToolTip = 'Specifies whether the Tariff No. (as harmonized system code) and Country/Region of Origin Code are synchronized to Shopify variants. Required for AI channel distribution and customs-aware selling.';\n+ DataClassification = SystemMetadata;\n+ InitValue = true;\n+ }\n }\n \n keys\ndiff --git a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyCreateProduct.Codeunit.al b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyCreateProduct.Codeunit.al\nindex 2f9c67bf2b..8dafe40875 100644\n--- a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyCreateProduct.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyCreateProduct.Codeunit.al\n@@ -110,6 +110,10 @@ codeunit 30174 \"Shpfy Create Product\"\n TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item.\"No.\", ItemVariant.Code, Item.\"Vendor Item No.\");\n TempShopifyVariant.Taxable := true;\n TempShopifyVariant.Weight := ItemUnitofMeasure.\"Qty. per Unit of Measure\" > 0 ? Item.\"Gross Weight\" * ItemUnitofMeasure.\"Qty. per Unit of Measure\" : Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ TempShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ TempShopifyVariant.\"Country/Region of Origin Code\" := ProductExport.GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n TempShopifyVariant.\"Option 1 Name\" := 'Variant';\n TempShopifyVariant.\"Option 1 Value\" := ItemVariant.Code;\n TempShopifyVariant.\"Option 2 Name\" := Shop.\"Option Name for UoM\";\n@@ -132,6 +136,10 @@ codeunit 30174 \"Shpfy Create Product\"\n TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item.\"No.\", ItemVariant.Code, GetVendorItemNo(Item.\"No.\", ItemVariant.Code, Item.\"Sales Unit of Measure\"));\n TempShopifyVariant.Taxable := true;\n TempShopifyVariant.Weight := Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ TempShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ TempShopifyVariant.\"Country/Region of Origin Code\" := ProductExport.GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n TempShopifyVariant.\"Option 1 Name\" := 'Variant';\n TempShopifyVariant.\"Option 1 Value\" := ItemVariant.Code;\n TempShopifyVariant.\"Shop Code\" := Shop.Code;\n@@ -158,6 +166,10 @@ codeunit 30174 \"Shpfy Create Product\"\n TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item.\"No.\", '', Item.\"Vendor Item No.\");\n TempShopifyVariant.Taxable := true;\n TempShopifyVariant.Weight := ItemUnitofMeasure.\"Qty. per Unit of Measure\" > 0 ? Item.\"Gross Weight\" * ItemUnitofMeasure.\"Qty. per Unit of Measure\" : Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ TempShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ TempShopifyVariant.\"Country/Region of Origin Code\" := ProductExport.GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n TempShopifyVariant.\"Option 1 Name\" := Shop.\"Option Name for UoM\";\n TempShopifyVariant.\"Option 1 Value\" := ItemUnitofMeasure.Code;\n TempShopifyVariant.\"Shop Code\" := Shop.Code;\n@@ -239,6 +251,10 @@ codeunit 30174 \"Shpfy Create Product\"\n TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item.\"No.\", '', Item.\"Vendor Item No.\");\n TempShopifyVariant.Taxable := true;\n TempShopifyVariant.Weight := Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ TempShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ TempShopifyVariant.\"Country/Region of Origin Code\" := ProductExport.GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n TempShopifyVariant.\"Shop Code\" := Shop.Code;\n TempShopifyVariant.\"Item SystemId\" := Item.SystemId;\n TempShopifyVariant.Insert(false);\n@@ -285,4 +301,5 @@ codeunit 30174 \"Shpfy Create Product\"\n Page.Run(Page::\"Shpfy Shop Locations Mapping\", ShopLocation);\n end;\n end;\n+\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\nindex 75bd1bd20a..02a2e95b62 100644\n--- a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\n@@ -5,6 +5,7 @@\n \n namespace Microsoft.Integration.Shopify;\n \n+using Microsoft.Foundation.Address;\n using Microsoft.Foundation.ExtendedText;\n using Microsoft.Inventory.Item;\n using Microsoft.Inventory.Item.Attribute;\n@@ -368,6 +369,10 @@ codeunit 30178 \"Shpfy Product Export\"\n end;\n ShopifyVariant.Taxable := true;\n ShopifyVariant.Weight := ItemUnitofMeasure.\"Qty. per Unit of Measure\" > 0 ? Item.\"Gross Weight\" * ItemUnitofMeasure.\"Qty. per Unit of Measure\" : Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ ShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ ShopifyVariant.\"Country/Region of Origin Code\" := GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n ShopifyVariant.\"Option 1 Name\" := Shop.\"Option Name for UoM\";\n ShopifyVariant.\"Option 1 Value\" := ItemUnitofMeasure.Code;\n ShopifyVariant.\"Shop Code\" := Shop.Code;\n@@ -424,6 +429,10 @@ codeunit 30178 \"Shpfy Product Export\"\n end;\n ShopifyVariant.Taxable := true;\n ShopifyVariant.Weight := Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ ShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ ShopifyVariant.\"Country/Region of Origin Code\" := GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n if ShopifyVariant.\"Option 1 Name\" = '' then\n ShopifyVariant.\"Option 1 Name\" := 'Variant';\n if ShopifyVariant.\"Option 1 Name\" = 'Variant' then\n@@ -479,6 +488,10 @@ codeunit 30178 \"Shpfy Product Export\"\n end;\n ShopifyVariant.Taxable := true;\n ShopifyVariant.Weight := ItemUnitofMeasure.\"Qty. per Unit of Measure\" > 0 ? Item.\"Gross Weight\" * ItemUnitofMeasure.\"Qty. per Unit of Measure\" : Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ ShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ ShopifyVariant.\"Country/Region of Origin Code\" := GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n ShopifyVariant.\"Option 1 Name\" := 'Variant';\n ShopifyVariant.\"Option 1 Value\" := ItemVariant.Code;\n ShopifyVariant.\"Option 2 Name\" := Shop.\"Option Name for UoM\";\n@@ -1359,4 +1372,15 @@ codeunit 30178 \"Shpfy Product Export\"\n exit(true);\n end;\n #endregion\n+\n+ internal procedure GetCountryISOCode(CountryRegionCode: Code[10]): Code[10]\n+ var\n+ CountryRegion: Record \"Country/Region\";\n+ begin\n+ if CountryRegionCode = '' then\n+ exit('');\n+ if CountryRegion.Get(CountryRegionCode) then\n+ exit(CountryRegion.\"ISO Code\");\n+ exit(CountryRegionCode);\n+ end;\n }\ndiff --git a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al\nindex 2889cd32fd..99d52b1cb7 100644\n--- a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al\n@@ -189,7 +189,7 @@ codeunit 30189 \"Shpfy Variant API\"\n HasChange := true;\n GraphQuery.Append(', compareAtPrice: null');\n end;\n- if (ShopifyVariant.\"Unit Cost\" <> xShopifyVariant.\"Unit Cost\") or (ShopifyVariant.Weight <> xShopifyVariant.Weight) or (ShopifyVariant.SKU <> xShopifyVariant.SKU) then begin\n+ if (ShopifyVariant.\"Unit Cost\" <> xShopifyVariant.\"Unit Cost\") or (ShopifyVariant.Weight <> xShopifyVariant.Weight) or (ShopifyVariant.SKU <> xShopifyVariant.SKU) or (ShopifyVariant.\"Tariff No.\" <> xShopifyVariant.\"Tariff No.\") or (ShopifyVariant.\"Country/Region of Origin Code\" <> xShopifyVariant.\"Country/Region of Origin Code\") then begin\n HasChange := true;\n GraphQuery.Append(', inventoryItem: {tracked: ');\n if Shop.\"Inventory Tracked\" then\n@@ -206,6 +206,20 @@ codeunit 30189 \"Shpfy Variant API\"\n GraphQuery.Append(ShopifyVariant.SKU);\n GraphQuery.Append('\\\"');\n end;\n+ if ShopifyVariant.\"Tariff No.\" <> xShopifyVariant.\"Tariff No.\" then begin\n+ HasChange := true;\n+ GraphQuery.Append(', harmonizedSystemCode: \\\"');\n+ GraphQuery.Append(CommunicationMgt.EscapeGraphQLData(ShopifyVariant.\"Tariff No.\"));\n+ GraphQuery.Append('\\\"');\n+ end;\n+ if ShopifyVariant.\"Country/Region of Origin Code\" <> xShopifyVariant.\"Country/Region of Origin Code\" then begin\n+ HasChange := true;\n+ GraphQuery.Append(', countryCodeOfOrigin: ');\n+ if ShopifyVariant.\"Country/Region of Origin Code\" = '' then\n+ GraphQuery.Append('null')\n+ else\n+ GraphQuery.Append(ShopifyVariant.\"Country/Region of Origin Code\");\n+ end;\n if ShopifyVariant.Weight <> xShopifyVariant.Weight then begin\n GraphQuery.Append(', measurement: {weight: {value:');\n GraphQuery.Append(Format(ShopifyVariant.Weight, 0, 9));\n@@ -283,6 +297,15 @@ codeunit 30189 \"Shpfy Variant API\"\n GraphQuery.Append(CommunicationMgt.EscapeGraphQLData(ShopifyVariant.SKU));\n GraphQuery.Append('\\\"');\n end;\n+ if ShopifyVariant.\"Tariff No.\" <> '' then begin\n+ GraphQuery.Append(', harmonizedSystemCode: \\\"');\n+ GraphQuery.Append(CommunicationMgt.EscapeGraphQLData(ShopifyVariant.\"Tariff No.\"));\n+ GraphQuery.Append('\\\"');\n+ end;\n+ if ShopifyVariant.\"Country/Region of Origin Code\" <> '' then begin\n+ GraphQuery.Append(', countryCodeOfOrigin: ');\n+ GraphQuery.Append(ShopifyVariant.\"Country/Region of Origin Code\");\n+ end;\n if ShopifyVariant.Weight > 0 then begin\n GraphQuery.Append(', measurement: {weight: {value:');\n GraphQuery.Append(Format(ShopifyVariant.Weight, 0, 9));\ndiff --git a/src/Apps/W1/Shopify/App/src/Products/Tables/ShpfyVariant.Table.al b/src/Apps/W1/Shopify/App/src/Products/Tables/ShpfyVariant.Table.al\nindex 9538e494cf..d5a73a41bd 100644\n--- a/src/Apps/W1/Shopify/App/src/Products/Tables/ShpfyVariant.Table.al\n+++ b/src/Apps/W1/Shopify/App/src/Products/Tables/ShpfyVariant.Table.al\n@@ -202,6 +202,16 @@ table 30129 \"Shpfy Variant\"\n {\n DataClassification = SystemMetadata;\n }\n+ field(109; \"Tariff No.\"; Code[20])\n+ {\n+ Caption = 'Tariff No.';\n+ DataClassification = CustomerContent;\n+ }\n+ field(110; \"Country/Region of Origin Code\"; Code[10])\n+ {\n+ Caption = 'Country/Region of Origin Code';\n+ DataClassification = CustomerContent;\n+ }\n }\n keys\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139601, "functionName": ["UnitTestCreateTempProductSetsHSCodeAndCountryOfOrigin", "UnitTestCreateTempProductWithVariantsSetsHSCodeAndCountryOfOrigin", "UnitTestCreateTempProductEmptyHSCodeAndCountryOfOrigin"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Shopify/Test/Products/ShpfyCreateProductTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Products/ShpfyCreateProductTest.Codeunit.al\nindex 415db40208..70335c56fb 100644\n--- a/src/Apps/W1/Shopify/Test/Products/ShpfyCreateProductTest.Codeunit.al\n+++ b/src/Apps/W1/Shopify/Test/Products/ShpfyCreateProductTest.Codeunit.al\n@@ -2958,4 +2958,120 @@ codeunit 139601 \"Shpfy Create Product Test\"\n \n until TempShopifyVariant.Next() = 0;\n end;\n+\n+ [Test]\n+ procedure UnitTestCreateTempProductSetsHSCodeAndCountryOfOrigin()\n+ var\n+ Item: Record Item;\n+ TempShopifyProduct: Record \"Shpfy Product\" temporary;\n+ Shop: Record \"Shpfy Shop\";\n+ TempShopifyVariant: Record \"Shpfy Variant\" temporary;\n+ TempTag: Record \"Shpfy Tag\" temporary;\n+ CreateProduct: Codeunit \"Shpfy Create Product\";\n+ InitializeTest: Codeunit \"Shpfy Initialize Test\";\n+ ProductInitTest: Codeunit \"Shpfy Product Init Test\";\n+ begin\n+ // [SCENARIO] Creating a temp product from an Item with Tariff No. and Country/Region of Origin Code\n+ // should populate those fields on the Shopify variant.\n+\n+ // [GIVEN] A shop with HS/Country sync enabled\n+ Shop := InitializeTest.CreateShop();\n+ Shop.\"SKU Mapping\" := \"Shpfy SKU Mapping\"::\" \";\n+ Shop.\"Sync HS Code and Country\" := true;\n+ Shop.Modify();\n+ CreateProduct.SetShop(Shop);\n+\n+ // [GIVEN] An item with Tariff No. and Country/Region of Origin Code\n+ Item := ProductInitTest.CreateItem(Shop.\"Item Templ. Code\", Any.DecimalInRange(10, 100, 2), Any.DecimalInRange(100, 1000, 2));\n+ Item.\"Tariff No.\" := '6402.99.0000';\n+ Item.\"Country/Region of Origin Code\" := 'US';\n+ Item.Modify();\n+ Item.SetRecFilter();\n+\n+ // [WHEN] CreateTempProduct is called\n+ CreateProduct.CreateTempProduct(Item, TempShopifyProduct, TempShopifyVariant, TempTag);\n+\n+ // [THEN] The variant has Tariff No. populated\n+ LibraryAssert.AreEqual('6402.99.0000', TempShopifyVariant.\"Tariff No.\", 'TempShopifyVariant.\"Tariff No.\" should match Item.\"Tariff No.\"');\n+\n+ // [THEN] The variant has Country/Region of Origin Code populated\n+ LibraryAssert.AreEqual('US', TempShopifyVariant.\"Country/Region of Origin Code\", 'TempShopifyVariant.\"Country/Region of Origin Code\" should match Item.\"Country/Region of Origin Code\"');\n+ end;\n+\n+ [Test]\n+ procedure UnitTestCreateTempProductEmptyHSCodeAndCountryOfOrigin()\n+ var\n+ Item: Record Item;\n+ TempShopifyProduct: Record \"Shpfy Product\" temporary;\n+ Shop: Record \"Shpfy Shop\";\n+ TempShopifyVariant: Record \"Shpfy Variant\" temporary;\n+ TempTag: Record \"Shpfy Tag\" temporary;\n+ CreateProduct: Codeunit \"Shpfy Create Product\";\n+ InitializeTest: Codeunit \"Shpfy Initialize Test\";\n+ ProductInitTest: Codeunit \"Shpfy Product Init Test\";\n+ begin\n+ // [SCENARIO] Creating a temp product from an Item without Tariff No. and Country/Region of Origin Code\n+ // should leave those fields empty on the Shopify variant.\n+\n+ // [GIVEN] A shop with HS/Country sync enabled\n+ Shop := InitializeTest.CreateShop();\n+ Shop.\"SKU Mapping\" := \"Shpfy SKU Mapping\"::\" \";\n+ Shop.\"Sync HS Code and Country\" := true;\n+ Shop.Modify();\n+ CreateProduct.SetShop(Shop);\n+\n+ // [GIVEN] An item without Tariff No. and Country/Region of Origin Code\n+ Item := ProductInitTest.CreateItem(Shop.\"Item Templ. Code\", Any.DecimalInRange(10, 100, 2), Any.DecimalInRange(100, 1000, 2));\n+ Item.SetRecFilter();\n+\n+ // [WHEN] CreateTempProduct is called\n+ CreateProduct.CreateTempProduct(Item, TempShopifyProduct, TempShopifyVariant, TempTag);\n+\n+ // [THEN] The variant has empty Tariff No.\n+ LibraryAssert.AreEqual('', TempShopifyVariant.\"Tariff No.\", 'TempShopifyVariant.\"Tariff No.\" should be empty');\n+\n+ // [THEN] The variant has empty Country/Region of Origin Code\n+ LibraryAssert.AreEqual('', TempShopifyVariant.\"Country/Region of Origin Code\", 'TempShopifyVariant.\"Country/Region of Origin Code\" should be empty');\n+ end;\n+\n+ [Test]\n+ procedure UnitTestCreateTempProductWithVariantsSetsHSCodeAndCountryOfOrigin()\n+ var\n+ Item: Record Item;\n+ TempShopifyProduct: Record \"Shpfy Product\" temporary;\n+ Shop: Record \"Shpfy Shop\";\n+ TempShopifyVariant: Record \"Shpfy Variant\" temporary;\n+ TempTag: Record \"Shpfy Tag\" temporary;\n+ CreateProduct: Codeunit \"Shpfy Create Product\";\n+ InitializeTest: Codeunit \"Shpfy Initialize Test\";\n+ ProductInitTest: Codeunit \"Shpfy Product Init Test\";\n+ begin\n+ // [SCENARIO] Creating a temp product with variants from an Item with Tariff No. and Country/Region of Origin Code\n+ // should populate both fields on all variant records.\n+\n+ // [GIVEN] A shop with HS/Country sync enabled\n+ Shop := InitializeTest.CreateShop();\n+ Shop.\"SKU Mapping\" := \"Shpfy SKU Mapping\"::\" \";\n+ Shop.\"Sync HS Code and Country\" := true;\n+ Shop.Modify();\n+ CreateProduct.SetShop(Shop);\n+\n+ // [GIVEN] An item with variants and Tariff No.\n+ Item := ProductInitTest.CreateItem(Shop.\"Item Templ. Code\", Any.DecimalInRange(10, 100, 2), Any.DecimalInRange(100, 1000, 2), true);\n+ Item.\"Tariff No.\" := '8471.30.0100';\n+ Item.\"Country/Region of Origin Code\" := 'DE';\n+ Item.Modify();\n+ Item.SetRecFilter();\n+\n+ // [WHEN] CreateTempProduct is called\n+ CreateProduct.CreateTempProduct(Item, TempShopifyProduct, TempShopifyVariant, TempTag);\n+\n+ // [THEN] All variants have Tariff No. and Country of Origin populated\n+ TempShopifyVariant.Reset();\n+ if TempShopifyVariant.FindSet() then\n+ repeat\n+ LibraryAssert.AreEqual('8471.30.0100', TempShopifyVariant.\"Tariff No.\", 'Each variant should have Tariff No.');\n+ LibraryAssert.AreEqual('DE', TempShopifyVariant.\"Country/Region of Origin Code\", 'Each variant should have Country/Region of Origin Code');\n+ until TempShopifyVariant.Next() = 0;\n+ end;\n }\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "1b05b19c9b6ecee6e567858fc839d2342c6a0526", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.0", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} diff --git a/dataset/problemstatement/microsoft__BCApps-7414/README.md b/dataset/problemstatement/microsoft__BCApps-7414/README.md new file mode 100644 index 000000000..a92c723d0 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-7414/README.md @@ -0,0 +1,19 @@ +# [Shopify] Sync HS Code and Country of Origin on variant export + +## Summary + +Addresses gaps identified in the Shopify Agentic Plan Product Sync Guide to ensure BC product catalogs meet the data requirements for AI channel distribution. + +- **Harmonized System Code**: Sync `Item."Tariff No."` as `harmonizedSystemCode` on variant export (both create and update paths) +- **Country of Origin**: Sync `Item."Country/Region of Origin Code"` as `countryCodeOfOrigin` on variant export +- New fields added to `Shpfy Variant` table and populated in `CreateTempProduct` (4 code paths) and `FillInProductVariantData` (3 overloads) +- New `Sync HS Code and Country of Origin` boolean on the Shop card (default on) gates the variant-field population, matching the pattern used by `Sync Item Extended Text` / `Marketing Text` / `Attributes` +- Tests added for HS code and country of origin field population + +Related docs PR for External URL extensibility example: MicrosoftDocs/dynamics365smb-devitpro#7259 + +Fixes [AB#632223](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/632223) + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-7831/README.md b/dataset/problemstatement/microsoft__BCApps-7831/README.md new file mode 100644 index 000000000..cba375c5a --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-7831/README.md @@ -0,0 +1,20 @@ +# Bug 620556: [Subcontracting] Align Subcontracting app with changes to the "Description 2" on various tables + +## Summary + +- **SubcPurchaseOrderCreator**: copy `Description 2` from `ProdOrderComponent` (not `Item`) to `PurchaseLine`; copy from `ProdOrderRoutingLine` (not blank) to `RequisitionLine` +- **SubcTempDataInitializer**: propagate `Description 2` from `RoutingLine` → temp `ProdOrderRoutingLine` and from `ProductionBOMLine` → temp `ProdOrderComponent` +- **SubcCreateProdOrdOpt**: include `Description 2` in `SetLoadFields`; propagate it to `PurchaseLine`, `ProductionBOMHeader`, `RoutingHeader`, `ProdOrderComponent`, and `ProdOrderRoutingLine` when committing wizard data +- **Pages**: surface `Description 2` (hidden) on `SubcProdOrderComponents`, `SubcPurchProvisionWizard`, and all four wizard list part pages + +## Root cause + +Bug 617366 added the `Description 2` field to manufacturing tables in the base app. The Subcontracting app was not updated to propagate that field through its wizard pipeline or purchase order creation flow, causing the field to be lost or blanked. + +Fixes [AB#620556](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/620556) + +🤖 Generated with [Claude Code](https://claude.com/claude-code) + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-8251/README.md b/dataset/problemstatement/microsoft__BCApps-8251/README.md new file mode 100644 index 000000000..98eed2f42 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8251/README.md @@ -0,0 +1,23 @@ +# Add VAT rate resolution and VAT amount difference for E-Document purchases + +## Why + +When importing e-documents for purchase processing, the system did not automatically resolve VAT Product Posting Groups from extracted VAT rates. Users had to manually identify and assign the correct VAT posting group for each line, which was error-prone and time-consuming. Additionally, rounding differences between the document's total VAT and the computed line-level VAT amounts were not reconciled, leading to posting discrepancies. + +## Summary + +- **Added** VAT Product Posting Group resolution during Prepare Draft — matches the extracted VAT rate against VAT Posting Setup entries (Normal VAT and Reverse Charge VAT only) for the vendor's VAT Bus. Posting Group +- **Added** `[BC] VAT Prod. Posting Group` and `[BC] VAT Rate Mismatch` fields on E-Document Purchase Line with OnValidate/OnLookup support +- **Added** VAT amount difference computation and application to purchase lines when finalizing drafts, respecting Allow VAT Difference and Max. VAT Difference Allowed settings +- **Added** "Resolve VAT Group Purch EDoc" and "Apply VAT Diff. For Purch EDoc" toggles on Purchases & Payables Setup +- **Improved** ADI handler to prefer the unambiguous `taxRate` field and properly disambiguate the `tax` field between percentage and monetary values +- **Added** comprehensive test codeunit `E-Doc Purch. VAT Tests` covering resolution, mismatch detection, OnValidate behavior, and VAT calculation type filtering +- **Updated** existing structured validation tests to reflect corrected VAT rate expectations + +Fixes [AB#619564](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/619564) + + + + + + From 1fa5439683689a448805638ef9bab58382090f5d Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Thu, 28 May 2026 15:40:22 +0200 Subject: [PATCH 03/14] 8253 & 7831 - commits changes --- dataset/bcbench.jsonl | 7 +- .../microsoft__BCApps-7414/README.md | 19 ---- .../microsoft__BCApps-7831/README.md | 56 +++++++---- .../microsoft__BCApps-7953/README.md | 20 ---- .../microsoft__BCApps-8251/README.md | 23 ----- .../microsoft__BCApps-8253/README.md | 97 ++++++++++++++----- 6 files changed, 111 insertions(+), 111 deletions(-) delete mode 100644 dataset/problemstatement/microsoft__BCApps-7414/README.md delete mode 100644 dataset/problemstatement/microsoft__BCApps-7953/README.md delete mode 100644 dataset/problemstatement/microsoft__BCApps-8251/README.md diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index 001c5febb..438edba3f 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -100,8 +100,5 @@ {"metadata": {"area": "inventory", "image_count": 7}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-176082", "base_commit": "cb30d50fe1ed2c716c6349370fdc31c6bd0ce956", "created_at": "2024-02-23", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137038, "functionName": ["GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\nindex e0b3ba5f0bf7..ffa98cfbb351 100644\n--- a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n@@ -48,6 +48,7 @@\n UndoneTransLineQtyErr: Label 'Expected Quantity to be 0 after Transfer Shipment was undone';\n DerivedTransLineErr: Label 'Expected no Derived Transfer Line i.e. line with \"Derived From Line No.\" equal to original transfer line.';\n IncorrectSNUndoneErr: Label 'The Serial No. of the item on the transfer shipment line that was undone was different from the SN on the corresponding transfer line.';\n+ ApplToItemEntryErr: Label '%1 must be %2 in %3.', Comment = '%1 is Appl-to Item Entry, %2 is Item Ledger Entry No. and %3 is Transfer Line';\n \n [Test]\n [HandlerFunctions('MessageHandler')]\n@@ -3655,6 +3656,99 @@\n ItemLedgerEntry.TestField(\"Cost Amount (Actual)\", NewCost);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('PostedPurchaseReceiptsModalPageHandler,PostedPurchRcptLinesModalPageHandler')]\n+ procedure GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines()\n+ var\n+ Item: Record Item;\n+ Vendor: Record Vendor;\n+ Location: Record Location;\n+ Location2: Record Location;\n+ Location3: Record Location;\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseHeader2: Record \"Purchase Header\";\n+ PurchaseHeader3: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ PurchaseLine2: Record \"Purchase Line\";\n+ PurchaseLine3: Record \"Purchase Line\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ TransferHeader: Record \"Transfer Header\";\n+ TransferLine: Record \"Transfer Line\";\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ ItemLedgerEntryNo: Integer;\n+ PurchaseReceiptNo: Code[20];\n+ TransferOrder: TestPage \"Transfer Order\";\n+ begin\n+ // [SCENARIO 500597] Get Receipt Lines action on Transfer Order shows list of Posted Purchase Receipts having Transfer-from Code in Location Code of Purch Rcpt Lines and after selecting it populates Appl-to Item Entry field in Transfer Lines.\n+ Initialize();\n+\n+ // [GIVEN] Create an Item and Validate Costing Method.\n+ LibraryInventory.CreateItem(Item);\n+ Item.Validate(\"Costing Method\", Item.\"Costing Method\"::FIFO);\n+ Item.Modify(true);\n+\n+ // [GIVEN] Create two Locations with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location2);\n+\n+ // [GIVEN] Create another Location with Inventory Posting Setup \n+ // And Validate Use As In-Transit.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location3);\n+ Location3.Validate(\"Use As In-Transit\", true);\n+ Location3.Modify(true);\n+\n+ // [GIVEN] Create a Vendor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+\n+ // [GIVEN] Create and Post Purchase Receipt with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader, PurchaseLine, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 2 with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader2, PurchaseLine2, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 3 with Location Code on Line.\n+ PurchaseReceiptNo := CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ PurchaseHeader3,\n+ PurchaseLine3,\n+ Vendor,\n+ Item,\n+ Location);\n+\n+ // [GIVEN] Find and save Item Ledger Entry No. in a Variable.\n+ ItemLedgerEntry.SetRange(\"Document No.\", PurchaseReceiptNo);\n+ ItemLedgerEntry.FindFirst();\n+ ItemLedgerEntryNo := ItemLedgerEntry.\"Entry No.\";\n+\n+ // [GIVEN] Find Purch. Rcpt Line.\n+ FindRandomReceiptLine(PurchaseReceiptNo, PurchRcptLine);\n+\n+ // [GIVEN] Create Transfer Header.\n+ LibraryInventory.CreateTransferHeader(TransferHeader, Location.Code, Location2.Code, Location3.Code);\n+\n+ // [GIVEN] Open Transfer Order page and run Get Receipt Line action.\n+ TransferOrder.OpenEdit();\n+ TransferOrder.GoToRecord(TransferHeader);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchRcptLine.\"No.\");\n+ TransferOrder.GetReceiptLines.Invoke();\n+\n+ // [WHEN] Find Transfer Line.\n+ TransferLine.SetRange(\"Document No.\", TransferHeader.\"No.\");\n+ TransferLine.FindFirst();\n+\n+ // [VERIFY] Appl-to Item Entry and Item Ledger Entry No. are same.\n+ Assert.AreEqual(\n+ ItemLedgerEntryNo,\n+ TransferLine.\"Appl.-to Item Entry\",\n+ StrSubstNo(\n+ ApplToItemEntryErr,\n+ TransferLine.FieldCaption(\"Appl.-to Item Entry\"),\n+ ItemLedgerEntryNo,\n+ TransferLine.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -5168,6 +5262,52 @@\n Assert.AreEqual(LineCount, TransferReceiptLine.Count(), '');\n end;\n \n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchHeader(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location)\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ PurchaseHeader.Validate(\"Location Code\", Location.Code);\n+ PurchaseHeader.Modify(true);\n+\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+ end;\n+\n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location): Code[20]\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Location Code\", Location.Code);\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ exit(LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false));\n+ end;\n+\n [MessageHandler]\n [Scope('OnPrem')]\n procedure MessageHandler(Message: Text[1024])\n@@ -5394,5 +5534,19 @@\n // 0 = Item.Type::Inventory\n Assert.AreEqual('0', ItemList.Filter.GetFilter(\"Type\"), 'Item List contains non-inventory items.');\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure PostedPurchRcptLinesModalPageHandler(var PostedPurchaseReceiptLines: Page \"Posted Purchase Receipt Lines\"; var Response: Action)\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ begin\n+ PurchRcptLine.SetRange(\"Document No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.SetRange(\"No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.FindFirst();\n+ PostedPurchaseReceiptLines.SetRecord(PurchRcptLine);\n+\n+ Response := ACTION::LookupOK;\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\nindex 5fe44b4568d1..c16ab8669925 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n@@ -1304,7 +1304,7 @@ table 5740 \"Transfer Header\"\n TempPurchRcptHeader: Record \"Purch. Rcpt. Header\" temporary;\n PostedPurchaseReceipts: Page \"Posted Purchase Receipts\";\n begin\n- PurchRcptHeader.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ FindPurchRcptHeader(PurchRcptHeader);\n PostedPurchaseReceipts.SetTableView(PurchRcptHeader);\n PostedPurchaseReceipts.LookupMode := true;\n if PostedPurchaseReceipts.RunModal() = ACTION::LookupOK then begin\n@@ -1376,6 +1376,8 @@ table 5740 \"Transfer Header\"\n PurchRcptLine.FilterPstdDocLnItemLedgEntries(ItemLedgerEntry);\n ItemTrackingDocMgt.CopyItemLedgerEntriesToTemp(TempItemLedgerEntry, ItemLedgerEntry);\n ItemTrackingMgt.CopyItemLedgEntryTrkgToTransferLine(TempItemLedgerEntry, TransferLine);\n+ TransferLine.\"Appl.-to Item Entry\" := ItemLedgerEntry.\"Entry No.\";\n+ TransferLine.Modify(true);\n \n OnAfterAddTransferLineFromReceiptLine(TransferLine, PurchRcptLine, TempItemLedgerEntry, Rec);\n end;\n@@ -1546,6 +1548,31 @@ table 5740 \"Transfer Header\"\n end;\n end;\n \n+ local procedure FindPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\")\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ DocumentNo: Code[20];\n+ begin\n+ PurchRcptLine.SetLoadFields(\"Document No.\", \"Location Code\");\n+ PurchRcptLine.SetCurrentKey(\"Document No.\");\n+ PurchRcptLine.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ if PurchRcptLine.FindSet() then\n+ repeat\n+ GetPurchRcptHeader(PurchRcptHeader, PurchRcptLine, DocumentNo);\n+ until PurchRcptLine.Next() = 0;\n+ PurchRcptHeader.MarkedOnly(true);\n+ end;\n+\n+ local procedure GetPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var DocumentNo: Code[20])\n+ begin\n+ if PurchRcptLine.\"Document No.\" = DocumentNo then\n+ exit;\n+\n+ PurchRcptHeader.Get(PurchRcptLine.\"Document No.\");\n+ PurchRcptHeader.Mark(true);\n+ DocumentNo := PurchRcptLine.\"Document No.\";\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnAddTransferLineFromReceiptLineOnBeforeTransferLineInsert(var TransferLine: Record \"Transfer Line\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var TransferHeader: Record \"Transfer Header\")\n begin\n"} {"metadata": {"area": "crm", "image_count": 8}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-174087", "base_commit": "74a0b7c175da3f9a272745bd34453a4712b73e7b", "created_at": "2024-02-02", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\Marketing"], "FAIL_TO_PASS": [{"codeunitID": 136208, "functionName": ["PopulateEvaluationFieldInInteractionLogEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\nindex 4c4c73700d2a..59fff6e2be93 100644\n--- a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n+++ b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n@@ -45,6 +45,7 @@ codeunit 136208 \"Marketing Interaction\"\n LoggedSegemntEntriesCreateMsg: Label 'Logged Segment entry was created';\n AttachmentFileShouldNotBeBlankErr: Label 'Attachment File should not be blank.';\n TxtFileExt: Label 'txt';\n+ EvaluationErr: Label '%1 must be %2 in %3', Comment = '%1 = Evaluation, %2 = Positive, %3 = Interaction Log Entry';\n \n [Test]\n [Scope('OnPrem')]\n@@ -2998,6 +2999,50 @@ codeunit 136208 \"Marketing Interaction\"\n VerifyAttachmentFileIsNotBlankOnInteractionLogEntry(Contact.\"No.\");\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('CreateInteractionFromContactPageHandler')]\n+ procedure PopulateEvaluationFieldInInteractionLogEntry()\n+ var\n+ Contact: Record Contact;\n+ InteractionTemplate: Record \"Interaction Template\";\n+ InteractionLogEntry: Record \"Interaction Log Entry\";\n+ ContactCard: TestPage \"Contact Card\";\n+ InteractionEvaluation: Enum \"Interaction Evaluation\";\n+ begin\n+ // [SCENARIO 498395] When stan creates an Interaction using Create Interaction action from Contact, Evaluation field should be populated in Interaction Log Entry.\n+ Initialize();\n+\n+ // [GIVEN] Create a Contact.\n+ LibraryMarketing.CreateCompanyContact(Contact);\n+\n+ // [GIVEN] Create an Interaction Template and Validate Information Flow.\n+ LibraryMarketing.CreateInteractionTemplate(InteractionTemplate);\n+ InteractionTemplate.Validate(\"Information Flow\", InteractionTemplate.\"Information Flow\"::Outbound);\n+ InteractionTemplate.Modify(true);\n+\n+ // [GIVEN] Open Contact Card and Create Interaction.\n+ ContactCard.OpenEdit();\n+ ContactCard.GoToRecord(Contact);\n+ LibraryVariableStorage.Enqueue(InteractionTemplate.Code);\n+ LibraryVariableStorage.Enqueue(Format(InteractionEvaluation::Positive));\n+ ContactCard.\"Create &Interaction\".Invoke();\n+\n+ // [WHEN] Find Interaction Log Entry.\n+ InteractionLogEntry.SetRange(\"Contact No.\", Contact.\"No.\");\n+ InteractionLogEntry.FindFirst();\n+\n+ // [VERIFY] Interaction Log Entry has Evaluation field populated as Positive.\n+ Assert.AreEqual(\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.Evaluation,\n+ StrSubstNo(\n+ EvaluationErr,\n+ InteractionLogEntry.FieldCaption(Evaluation),\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibrarySales: Codeunit \"Library - Sales\";\n@@ -4309,5 +4354,16 @@ CopyStr(StorageLocation, 1, MaxStrLen(MarketingSetup.\"Attachment Storage Locatio\n CreateInteraction.NextInteraction.Invoke();\n CreateInteraction.Finish.Invoke();\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure CreateInteractionFromContactPageHandler(var CreateInteraction: TestPage \"Create Interaction\")\n+ begin\n+ CreateInteraction.\"Interaction Template Code\".SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.Evaluation.SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.FinishInteraction.Invoke();\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\nindex ff43f4ff6a7b..05a21a6196bf 100644\n--- a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n+++ b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n@@ -694,6 +694,7 @@ page 5077 \"Create Interaction\"\n end;\n Step::\"Step 4\":\n begin\n+ InteractionLogEntry.CopyFromSegment(Rec);\n InteractionLogEntry.Modify();\n CurrPage.Close();\n end;\n"} {"metadata": {"area": "peppol", "image_count": 1}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8059", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-08T09:31:42Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\PEPPOL\\App", "src\\Apps\\W1\\PEPPOL\\Test"], "patch": "diff --git a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\nindex 30f5f792bd..c7981a46fa 100644\n--- a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n@@ -798,6 +798,8 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n InvoiceLineNote := DelChr(Format(SalesLine.Type), '<>');\n InvoicedQuantity := Format(SalesLine.Quantity, 0, 9);\n SalesLineLineAmount := SalesLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesLineLineAmount := Round(SalesLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n InvoiceLineExtensionAmount := Format(SalesLineLineAmount, 0, 9);\n LineExtensionAmountCurrencyID := GetSalesDocCurrencyCode(SalesHeader);\n InvoiceLineAccountingCost := '';\n@@ -869,7 +871,10 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n \n InvLnAllowanceChargeIndicator := 'false';\n InvLnAllowanceChargeReason := LineDisAmtTxt;\n- InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ InvLnAllowanceChargeAmount := Format(Round(SalesLine.\"Line Discount Amount\" / (1 + SalesLine.\"VAT %\" / 100), 0.01), 0, 9)\n+ else\n+ InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n InvLnAllowanceChargeAmtCurrID := GetSalesDocCurrencyCode(SalesHeader);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139235, "functionName": ["LineAmountsConsistentWhenPricesInclVATNoDiscount"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\nindex 36931d56ed..cd237011d5 100644\n--- a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n@@ -3349,6 +3349,68 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual('', CustTaxSchemeID, 'Tax Scheme ID should be empty for Tax Category O.');\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ procedure LineAmountsConsistentWhenPricesInclVATNoDiscount()\n+ var\n+ SalesHeader: Record \"Sales Header\";\n+ SalesLine: Record \"Sales Line\";\n+ Customer: Record Customer;\n+ Item: Record Item;\n+ SalesInvoiceHeader: Record \"Sales Invoice Header\";\n+ SalesInvoiceLine: Record \"Sales Invoice Line\";\n+ PEPPOLLineInfoProvider: Interface \"PEPPOL Line Info Provider\";\n+ InvoiceLineID: Text;\n+ InvoiceLineNote: Text;\n+ InvoicedQuantity: Text;\n+ InvoiceLineExtensionAmount: Text;\n+ LineExtensionAmountCurrencyID: Text;\n+ InvoiceLineAccountingCost: Text;\n+ InvoiceLinePriceAmount: Text;\n+ InvLinePriceAmountCurrencyID: Text;\n+ BaseQuantity: Text;\n+ UnitCode: Text;\n+ PriceAmount: Decimal;\n+ LineExtensionAmt: Decimal;\n+ SalesInvoiceNo: Code[20];\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 630795] PEPPOL LineExtensionAmount equals PriceAmount times Quantity when Prices Including VAT is used\n+ Initialize();\n+\n+ // [GIVEN] Customer \"C\" with PEPPOL identifier\n+ LibrarySales.CreateCustomer(Customer);\n+ AddCustPEPPOLIdentifier(Customer.\"No.\");\n+\n+ // [GIVEN] Sales Invoice for \"C\" with \"Prices Including VAT\" = TRUE and Quantity = 7\n+ CreateItemWithPrice(Item, 139);\n+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader.\"Document Type\"::Invoice, Customer.\"No.\");\n+ SalesHeader.Validate(\"Prices Including VAT\", true);\n+ SalesHeader.Modify(true);\n+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item.\"No.\", 7);\n+\n+ // [WHEN] Post the Sales Invoice and retrieve PEPPOL line amounts\n+ SalesInvoiceNo := LibrarySales.PostSalesDocument(SalesHeader, true, true);\n+ SalesInvoiceHeader.Get(SalesInvoiceNo);\n+ SalesHeader.TransferFields(SalesInvoiceHeader);\n+ FindSalesInvoiceLine(SalesInvoiceLine, SalesInvoiceNo);\n+ SalesLine.TransferFields(SalesInvoiceLine);\n+\n+ PEPPOLLineInfoProvider := GetFormat();\n+ PEPPOLLineInfoProvider.GetLineGeneralInfo(\n+ SalesLine, SalesHeader, InvoiceLineID, InvoiceLineNote, InvoicedQuantity,\n+ InvoiceLineExtensionAmount, LineExtensionAmountCurrencyID, InvoiceLineAccountingCost);\n+ PEPPOLLineInfoProvider.GetLinePriceInfo(\n+ SalesLine, SalesHeader, InvoiceLinePriceAmount, InvLinePriceAmountCurrencyID,\n+ BaseQuantity, UnitCode);\n+\n+ // [THEN] LineExtensionAmount equals PriceAmount times Quantity per PEPPOL BIS 3.0\n+ Evaluate(PriceAmount, InvoiceLinePriceAmount, 9);\n+ Evaluate(LineExtensionAmt, InvoiceLineExtensionAmount, 9);\n+ Assert.AreEqual(PriceAmount * SalesInvoiceLine.Quantity, LineExtensionAmt,\n+ 'LineExtensionAmount must equal PriceAmount * Quantity per PEPPOL BIS 3.0');\n+ end;\n+\n var\n local procedure Initialize()\n var\n@@ -3993,6 +4055,8 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual(UnitOfMeasure.\"International Standard Code\", unitCode, '');\n Assert.AreEqual('UNECERec20', unitCodeListID, '');\n SalesInvoiceLineLineAmount := SalesInvoiceLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesInvoiceLineLineAmount := Round(SalesInvoiceLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n Assert.AreEqual(Format(SalesInvoiceLineLineAmount, 0, 9), InvoiceLineExtensionAmount, '');\n Assert.AreEqual(SalesHeader.\"Currency Code\", LineExtensionAmountCurrencyID, '');\n Assert.AreEqual('', InvoiceLineAccountingCost, '');\n"} -{"metadata": {"area": "manufacturing", "image_count": 0}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "bb325c49266ab81baa1c3c2a1154c182019929d4", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} -{"metadata": {"area": "null", "image_count": 0}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7953", "base_commit": "907fd4ab20c5a3156d2d3dac5787bce3a272bb57", "created_at": "2026-05-04T20:30:22Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\EDocument\\App", "src\\Apps\\W1\\EDocument\\Test"], "patch": "diff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al\nnew file mode 100644\nindex 0000000000..45c2b7121f\n--- /dev/null\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchDefPostingDate.Enum.al\n@@ -0,0 +1,20 @@\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+namespace Microsoft.eServices.EDocument;\n+\n+enum 6162 \"E-Doc. Purch.Def. Posting Date\"\n+{\n+ Extensible = false;\n+ Caption = 'Purchase Invoice Posting Date (E-Docs)';\n+\n+ value(0; \"Work Date\")\n+ {\n+ Caption = 'Work Date';\n+ }\n+ value(1; \"Document Date\")\n+ {\n+ Caption = 'Document Date';\n+ }\n+}\ndiff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\nindex 08b2a7a822..556fbad792 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n@@ -21,6 +21,11 @@ pageextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n ApplicationArea = All;\n ToolTip = 'Specifies whether Copilot E-Document line matchings are learned by default (Item References and Text To Account Mappings). This can be overwritten on the matching page.';\n }\n+ field(\"E-Doc. Def. Posting Date\"; Rec.\"E-Doc. Def. Posting Date\")\n+ {\n+ ApplicationArea = All;\n+ ToolTip = 'Specifies how the posting date is set on purchase invoices created from e-documents. Work Date uses the current work date. Document Date uses the document date from the e-document.';\n+ }\n }\n }\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\nindex 24013c63c5..2dc0c9ccec 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n@@ -21,5 +21,10 @@ tableextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n Caption = 'E-Document Learn Copilot Matchings';\n DataClassification = SystemMetadata;\n }\n+ field(6102; \"E-Doc. Def. Posting Date\"; Enum \"E-Doc. Purch.Def. Posting Date\")\n+ {\n+ Caption = 'E-Document Default Posting Date';\n+ DataClassification = CustomerContent;\n+ }\n }\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\nindex b97c6db072..14907342c4 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchCrMemo.Codeunit.al\n@@ -100,6 +100,7 @@ codeunit 6404 \"E-Doc. Create Purch. Cr. Memo\" implements IEDocumentFinishDraft,\n if EDocumentPurchaseHeader.\"Purchase Order No.\" <> '' then\n PurchaseHeader.\"Vendor Order No.\" := CopyStr(EDocumentPurchaseHeader.\"Purchase Order No.\", 1, MaxStrLen(PurchaseHeader.\"Vendor Order No.\"));\n PurchaseHeader.Insert(true);\n+ EDocPurchaseDocumentHelper.ApplyDefaultPostingDateFromSetup(PurchaseHeader, EDocumentPurchaseHeader);\n PurchaseHeader.Modify();\n \n GLSetup.GetRecordOnce();\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\nindex 0f2b7905d4..f79acb69fe 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n@@ -129,6 +129,7 @@ codeunit 6117 \"E-Doc. Create Purchase Invoice\" implements IEDocumentFinishDraft,\n PurchaseHeader.\"Vendor Order No.\" := CopyStr(EDocumentPurchaseHeader.\"Purchase Order No.\", 1, MaxStrLen(PurchaseHeader.\"Vendor Order No.\"));\n PurchaseHeader.Insert(true);\n \n+ EDocPurchaseDocumentHelper.ApplyDefaultPostingDateFromSetup(PurchaseHeader, EDocumentPurchaseHeader);\n PurchaseHeader.\"Invoice Received Date\" := PurchaseHeader.\"Document Date\";\n PurchaseHeader.Modify();\n \ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\nindex dd97e61275..d21ea96b71 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n@@ -11,6 +11,7 @@ using Microsoft.Finance.Dimension;\n using Microsoft.Foundation.Attachment;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.Posting;\n+using Microsoft.Purchases.Setup;\n \n /// \n /// Shared logic for creating BC purchase documents (invoices and credit memos) from e-document draft data.\n@@ -137,4 +138,16 @@ codeunit 6402 \"E-Doc. Purch. Doc. Helper\"\n Clear(PurchaseHeader.\"E-Document Link\");\n PurchaseHeader.Modify();\n end;\n+\n+ procedure ApplyDefaultPostingDateFromSetup(var PurchaseHeader: Record \"Purchase Header\"; EDocumentPurchaseHeader: Record \"E-Document Purchase Header\")\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ begin\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ if (PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" <> PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\"::\"Document Date\") then\n+ exit;\n+ if EDocumentPurchaseHeader.\"Document Date\" = 0D then\n+ exit;\n+ PurchaseHeader.Validate(\"Posting Date\", EDocumentPurchaseHeader.\"Document Date\");\n+ end;\n }\n", "FAIL_TO_PASS": [{"codeunitID": 139883, "functionName": ["InvoicePostingDateUsesDocumentDateWhenSettingIsDocumentDate", "InvoicePostingDateDefaultsToWorkDateWhenSettingIsWorkDate", "CreditMemoPostingDateDefaultsToWorkDateWhenSettingIsWorkDate", "CreditMemoPostingDateUsesDocumentDateWhenSettingIsDocumentDate"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml\nnew file mode 100644\nindex 0000000000..52cd211620\n--- /dev/null\n+++ b/src/Apps/W1/EDocument/Test/.resources/peppol/peppol-invoice-no-currency.xml\n@@ -0,0 +1,200 @@\n+\n+\n+\turn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0\n+\turn:fdc:peppol.eu:2017:poacc:billing:01:1.0\n+\t103033\n+\t2026-01-22\n+\t2026-02-22\n+\t380\n+\t1\n+\t\n+\t\t2\n+\t\n+\t\n+\t\t103033\n+\t\n+\t\n+\t\t103033\n+\t\t\n+\t\t\n+\t\t\t\n+\t\t\t\t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MzAxMjE5MDBaKS9Nb2REYXRlKEQ6MjAyMjA2MTUxMzEzMDBaKT4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAzIDAgUi9MYW5nKGVuLVVTKS9NZXRhZGF0YSA0IDAgUj4+DQplbmRvYmoNCjMgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWzUgMCBSXT4+DQplbmRvYmoNCjQgMCBvYmoNCjw8L1R5cGUvTWV0YWRhdGEvU3VidHlwZS9YTUwvTGVuZ3RoIDIxIDAgUj4+c3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJQREZOZXQiPgo8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgo8eG1wOkNyZWF0ZURhdGU+MjAxNy0wMS0zMFQxMjoxOTowMFo8L3htcDpDcmVhdGVEYXRlPgo8eG1wOk1vZGlmeURhdGU+MjAyMi0wNi0xNVQxMzoxMzowMFo8L3htcDpNb2RpZnlEYXRlPgo8eG1wOkNyZWF0b3JUb29sPk1pY3Jvc29mdCBPZmZpY2UgV29yZDwveG1wOkNyZWF0b3JUb29sPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KPGRjOmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KPGRjOnRpdGxlPgo8cmRmOkFsdD4KPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5TYWxlcyAtIEludm9pY2U8L3JkZjpsaT4KPC9yZGY6QWx0Pgo8L2RjOnRpdGxlPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6cGRmPSJodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8xLjMvIj4KPHBkZjpQcm9kdWNlcj5Bc3Bvc2UuV29yZHMgZm9yIC5ORVQgMjMuOS4wPC9wZGY6UHJvZHVjZXI+CjwvcmRmOkRlc2NyaXB0aW9uPgo8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJ3Ij8+Cg0KZW5kc3RyZWFtDQplbmRvYmoNCjIxIDAgb2JqDQo4NTQNCmVuZG9iag0KMTYgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCRytTZWdvZVVJLUJvbGQvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nL0ZpcnN0Q2hhciAzMi9MYXN0Q2hhciAxNjMvV2lkdGhzIDE3IDAgUi9Gb250RGVzY3JpcHRvciAxOCAwIFI+Pg0KZW5kb2JqDQoxNyAwIG9iag0KWzI3NiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMjcxIDAgMjcxIDAgNTc1IDU3NSA1NzUgMCA1NzUgNTc1IDAgNTc1IDAgNTc1IDAgMCAwIDAgMCAwIDAgNzAzIDY0MSA2MjQgMCAwIDAgNzExIDAgMCAwIDY0OSA1MTEgOTU3IDAgMCA2MTQgMCAwIDU2MSA1ODYgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNTM4IDAgMCA2MTkgNTQxIDAgNjE5IDYwMiAyODQgMCA1NTkgMjg0IDkxNiA2MDUgNjExIDYyMCA2MTkgMzk4IDAgMzg5IDYwNSAwIDAgMCA1MzggMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDU3NV0NCmVuZG9iag0KMTggMCBvYmoNCjw8L1R5cGUvRm9udERlc2NyaXB0b3IvRm9udE5hbWUvRkFBQUJHK1NlZ29lVUktQm9sZC9TdGVtViA4MC9EZXNjZW50IC0yNTEvQXNjZW50IDEwNzkvQ2FwSGVpZ2h0IDcwMC9GbGFncyAyNjIxNzYvSXRhbGljQW5nbGUgMC9Gb250QkJveFstNTczIC00MzEgMTk5OSAxMjk4XS9Gb250RmlsZTIgMTUgMCBSPj4NCmVuZG9iag0KMTIgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCQytTZWdvZVVJLUxpZ2h0L0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTE4L1dpZHRocyAxMyAwIFIvRm9udERlc2NyaXB0b3IgMTQgMCBSPj4NCmVuZG9iag0KMTMgMCBvYmoNClsyNzQgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDIyMiAwIDIyMiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCA2MjkgNTQ0IDYyMSAwIDAgMCAwIDAgMjI4IDAgMCAwIDAgNzA5IDc2MSAwIDAgNTU1IDQ5NyAwIDY0OCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNDk0IDAgNDQ0IDAgNTA1IDAgNTYwIDUzNSAyMDUgMCAwIDAgODIyIDUzNSA1NjEgMCAwIDMzMCAwIDAgMCA0NTNdDQplbmRvYmoNCjE0IDAgb2JqDQo8PC9UeXBlL0ZvbnREZXNjcmlwdG9yL0ZvbnROYW1lL0ZBQUFCQytTZWdvZVVJLUxpZ2h0L1N0ZW1WIDgwL0Rlc2NlbnQgLTI1MS9Bc2NlbnQgMTA3OS9DYXBIZWlnaHQgNzAwL0ZsYWdzIDMyL0l0YWxpY0FuZ2xlIDAvRm9udEJCb3hbLTU4NyAtMzk2IDE5OTkgMTI5OV0vRm9udEZpbGUyIDExIDAgUj4+DQplbmRvYmoNCjggMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFBSStTZWdvZVVJL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTIxL1dpZHRocyA5IDAgUi9Gb250RGVzY3JpcHRvciAxMCAwIFI+Pg0KZW5kb2JqDQo5IDAgb2JqDQpbMjc0IDAgMCAwIDAgODE4IDAgMCAwIDAgMCA2ODQgMjE3IDQwMCAyMTcgMzkwIDUzOSA1MzkgNTM5IDUzOSA1MzkgNTM5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MODW9nYEFJ/+03vN/EfC/wC1cf8ACIPH+01vN/EfCv7Vx/wiC9HFLTNYMWxuxVMjJqiy2qjoJ5oteR76aBkTnN1AOhLdRqEGNd+9i8S6h9v59vcxrLjbrca2G5UdwtckcdRDV07ZGRP+VjkY5ukjgWlvEd4PFBULn/lQbnWuaon243CsOW0DdXQ0d4jntNby6ahg8MVUL3Ds1L2A9ug7EEart5fvVtaJSx21Elxi1+TqaC62qoY7QAk8ravnHbp7TRr3IOtUvRP1U1kvhQ7LX1jg0u5pzTQN0H5807G6+rVBlPFvLW6qMhkjF0xuzYVBIW/9zervTPAaeOpZbjWvGnoLdfUgnPtB5VeB49U0l33izCpz2ohIe7F7Sx9ttpcO1k1Rzmpmb62GE/1haTjuOWDEbLb8cxay0WPWG1R+DbrPb4GU9NCzUnRkcYDRqSSeHE8TxQc0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIP/2Q0KZW5kc3RyZWFtDQplbmRvYmoNCjIyIDAgb2JqDQoxNTE2OA0KZW5kb2JqDQoxNSAwIG9iag0KPDwvTGVuZ3RoMSAyMyAwIFIvTGVuZ3RoIDI0IDAgUi9GaWx0ZXIvRmxhdGVEZWNvZGU+PnN0cmVhbQ0KeJzsfAl4VFWW8LlvqX1PVVJJBfIqlbAVppJUAokgKcjCEoghCZgCgilIQgKBBBJAVBaHIBpXRFRwaVptRntorWCPHVFbnHZp/XXcp8Vuu22l3RqQ7kb0Q/Jqzr3vVVJhcfz7m+lv5vt4lXffufeee+/Z7jnnPqoAAgBm2AI8VF9eG8hvvDX0Abb8Du/GpSsjnbpb9Q4AMhnvuqXruqWNk9paALjbAQw5LZ3LVs6seX8ZgOkQ1hcta9/Q8tD8f3oMICUdwHWktTnSdB9kcACX4HQwoRUbnBbdp1gvwnpW68ruqx5/0erF+iKs39fesTQC5KHrsf4t1veujFzVyT9t/hAg5x6sS6siK5s/tq57A+v9AGOyOju6umNzYT3AfEqv1LmmuXPFX9J1WD8DIFwCvNDPPQMi6MQ9YhA58ChP/i1o4Rw6kTPqOAE/HH8EcmKH4MhmnEVPSZ1TK0kggTk2IL4jzyVm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\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t103033\n+\t\t\n+\t\t\n+\t\t\t\n+\t\t\t\t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MzAxMjE5MDBaKS9Nb2REYXRlKEQ6MjAyMjA2MTUxMzEzMDBaKT4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAzIDAgUi9MYW5nKGVuLVVTKS9NZXRhZGF0YSA0IDAgUj4+DQplbmRvYmoNCjMgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWzUgMCBSXT4+DQplbmRvYmoNCjQgMCBvYmoNCjw8L1R5cGUvTWV0YWRhdGEvU3VidHlwZS9YTUwvTGVuZ3RoIDIxIDAgUj4+c3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJQREZOZXQiPgo8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgo8eG1wOkNyZWF0ZURhdGU+MjAxNy0wMS0zMFQxMjoxOTowMFo8L3htcDpDcmVhdGVEYXRlPgo8eG1wOk1vZGlmeURhdGU+MjAyMi0wNi0xNVQxMzoxMzowMFo8L3htcDpNb2RpZnlEYXRlPgo8eG1wOkNyZWF0b3JUb29sPk1pY3Jvc29mdCBPZmZpY2UgV29yZDwveG1wOkNyZWF0b3JUb29sPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KPGRjOmZvcm1hdD5hcHBsaWNhdGlvbi9wZGY8L2RjOmZvcm1hdD4KPGRjOnRpdGxlPgo8cmRmOkFsdD4KPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5TYWxlcyAtIEludm9pY2U8L3JkZjpsaT4KPC9yZGY6QWx0Pgo8L2RjOnRpdGxlPgo8L3JkZjpEZXNjcmlwdGlvbj4KPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6cGRmPSJodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8xLjMvIj4KPHBkZjpQcm9kdWNlcj5Bc3Bvc2UuV29yZHMgZm9yIC5ORVQgMjMuOS4wPC9wZGY6UHJvZHVjZXI+CjwvcmRmOkRlc2NyaXB0aW9uPgo8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJ3Ij8+Cg0KZW5kc3RyZWFtDQplbmRvYmoNCjIxIDAgb2JqDQo4NTQNCmVuZG9iag0KMTYgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCRytTZWdvZVVJLUJvbGQvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nL0ZpcnN0Q2hhciAzMi9MYXN0Q2hhciAxNjMvV2lkdGhzIDE3IDAgUi9Gb250RGVzY3JpcHRvciAxOCAwIFI+Pg0KZW5kb2JqDQoxNyAwIG9iag0KWzI3NiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMjcxIDAgMjcxIDAgNTc1IDU3NSA1NzUgMCA1NzUgNTc1IDAgNTc1IDAgNTc1IDAgMCAwIDAgMCAwIDAgNzAzIDY0MSA2MjQgMCAwIDAgNzExIDAgMCAwIDY0OSA1MTEgOTU3IDAgMCA2MTQgMCAwIDU2MSA1ODYgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNTM4IDAgMCA2MTkgNTQxIDAgNjE5IDYwMiAyODQgMCA1NTkgMjg0IDkxNiA2MDUgNjExIDYyMCA2MTkgMzk4IDAgMzg5IDYwNSAwIDAgMCA1MzggMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDU3NV0NCmVuZG9iag0KMTggMCBvYmoNCjw8L1R5cGUvRm9udERlc2NyaXB0b3IvRm9udE5hbWUvRkFBQUJHK1NlZ29lVUktQm9sZC9TdGVtViA4MC9EZXNjZW50IC0yNTEvQXNjZW50IDEwNzkvQ2FwSGVpZ2h0IDcwMC9GbGFncyAyNjIxNzYvSXRhbGljQW5nbGUgMC9Gb250QkJveFstNTczIC00MzEgMTk5OSAxMjk4XS9Gb250RmlsZTIgMTUgMCBSPj4NCmVuZG9iag0KMTIgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFCQytTZWdvZVVJLUxpZ2h0L0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTE4L1dpZHRocyAxMyAwIFIvRm9udERlc2NyaXB0b3IgMTQgMCBSPj4NCmVuZG9iag0KMTMgMCBvYmoNClsyNzQgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDIyMiAwIDIyMiAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCA2MjkgNTQ0IDYyMSAwIDAgMCAwIDAgMjI4IDAgMCAwIDAgNzA5IDc2MSAwIDAgNTU1IDQ5NyAwIDY0OCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNDk0IDAgNDQ0IDAgNTA1IDAgNTYwIDUzNSAyMDUgMCAwIDAgODIyIDUzNSA1NjEgMCAwIDMzMCAwIDAgMCA0NTNdDQplbmRvYmoNCjE0IDAgb2JqDQo8PC9UeXBlL0ZvbnREZXNjcmlwdG9yL0ZvbnROYW1lL0ZBQUFCQytTZWdvZVVJLUxpZ2h0L1N0ZW1WIDgwL0Rlc2NlbnQgLTI1MS9Bc2NlbnQgMTA3OS9DYXBIZWlnaHQgNzAwL0ZsYWdzIDMyL0l0YWxpY0FuZ2xlIDAvRm9udEJCb3hbLTU4NyAtMzk2IDE5OTkgMTI5OV0vRm9udEZpbGUyIDExIDAgUj4+DQplbmRvYmoNCjggMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL0Jhc2VGb250L0ZBQUFBSStTZWdvZVVJL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTIxL1dpZHRocyA5IDAgUi9Gb250RGVzY3JpcHRvciAxMCAwIFI+Pg0KZW5kb2JqDQo5IDAgb2JqDQpbMjc0IDAgMCAwIDAgODE4IDAgMCAwIDAgMCA2ODQgMjE3IDQwMCAyMTcgMzkwIDUzOSA1MzkgNTM5IDUzOSA1MzkgNTM5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MODW9nYEFJ/+03vN/EfC/wC1cf8ACIPH+01vN/EfCv7Vx/wiC9HFLTNYMWxuxVMjJqiy2qjoJ5oteR76aBkTnN1AOhLdRqEGNd+9i8S6h9v59vcxrLjbrca2G5UdwtckcdRDV07ZGRP+VjkY5ukjgWlvEd4PFBULn/lQbnWuaon243CsOW0DdXQ0d4jntNby6ahg8MVUL3Ds1L2A9ug7EEart5fvVtaJSx21Elxi1+TqaC62qoY7QAk8ravnHbp7TRr3IOtUvRP1U1kvhQ7LX1jg0u5pzTQN0H5807G6+rVBlPFvLW6qMhkjF0xuzYVBIW/9zervTPAaeOpZbjWvGnoLdfUgnPtB5VeB49U0l33izCpz2ohIe7F7Sx9ttpcO1k1Rzmpmb62GE/1haTjuOWDEbLb8cxay0WPWG1R+DbrPb4GU9NCzUnRkcYDRqSSeHE8TxQc0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIP/2Q0KZW5kc3RyZWFtDQplbmRvYmoNCjIyIDAgb2JqDQoxNTE2OA0KZW5kb2JqDQoxNSAwIG9iag0KPDwvTGVuZ3RoMSAyMyAwIFIvTGVuZ3RoIDI0IDAgUi9GaWx0ZXIvRmxhdGVEZWNvZGU+PnN0cmVhbQ0KeJzsfAl4VFWW8LlvqX1PVVJJBfIqlbAVppJUAokgKcjCEoghCZgCgilIQgKBBBJAVBaHIBpXRFRwaVptRntorWCPHVFbnHZp/XXcp8Vuu22l3RqQ7kb0Q/Jqzr3vVVJhcfz7m+lv5vt4lXffufeee+/Z7jnnPqoAAgBm2AI8VF9eG8hvvDX0Abb8Du/GpSsjnbpb9Q4AMhnvuqXruqWNk9paALjbAQw5LZ3LVs6seX8ZgOkQ1hcta9/Q8tD8f3oMICUdwHWktTnSdB9kcACX4HQwoRUbnBbdp1gvwnpW68ruqx5/0erF+iKs39fesTQC5KHrsf4t1veujFzVyT9t/hAg5x6sS6siK5s/tq57A+v9AGOyOju6umNzYT3AfEqv1LmmuXPFX9J1WD8DIFwCvNDPPQMi6MQ9YhA58ChP/i1o4Rw6kTPqOAE/HH8EcmKH4MhmnEVPSZ1TK0kggTk2IL4jzyVm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\n+\t\t\t\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t1234567890128\n+\t\t\t\n+\t\t\t\tCRONUS International\n+\t\t\t\n+\t\t\t\n+\t\t\t\tMain Street, 14\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tGB123456789\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tCRONUS International\n+\t\t\t\t123456789\n+\t\t\t\n+\t\t\t\n+\t\t\t\tJim Olive\n+\t\t\t\tJO@contoso.com\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t\n+\t\t\t789456278\n+\t\t\t\n+\t\t\t\t8712345000004\n+\t\t\t\n+\t\t\t\n+\t\t\t\tThe Cannon Group PLC\n+\t\t\t\n+\t\t\t\n+\t\t\t\t192 Market Square\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tGB789456278\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\t\n+\t\t\t\tThe Cannon Group PLC\n+\t\t\t\t789456278\n+\t\t\t\n+\t\t\t\n+\t\t\t\tMr. Andy Teal\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t2026-01-22\n+\t\t\n+\t\t\t8712345000004\n+\t\t\t\n+\t\t\t\t192 Market Square\n+\t\t\t\tBirmingham\n+\t\t\t\tB27 4KT\n+\t\t\t\t\n+\t\t\t\t\tGB\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t31\n+\t\t\n+\t\t\tGB12CPBK08929965044991\n+\t\t\t\n+\t\t\t\tBG99999\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t1 Month/2% 8 days\n+\t\n+\t\n+\t\t1000\n+\t\t\n+\t\t\t4000\n+\t\t\t1000\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\n+\t\n+\t\t14000\n+\t\t14000\n+\t\t14140\n+\t\t0\n+\t\t0.00\n+\t\t0\n+\t\t14140\n+\t\n+\t\n+\t\t10000\n+\t\tItem\n+\t\t1\n+\t\t4000\n+\t\t\n+\t\t\tBicycle\n+\t\t\t\n+\t\t\t\t1000\n+\t\t\t\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\t\n+\t\t\t4000.00\n+\t\t\t1\n+\t\t\n+\t\n+\t\n+\t\t20000\n+\t\tItem\n+\t\t2\n+\t\t10000\n+\t\t\n+\t\t\tBicycle v2\n+\t\t\t\n+\t\t\t\t2000\n+\t\t\t\n+\t\t\t\n+\t\t\t\tS\n+\t\t\t\t25\n+\t\t\t\t\n+\t\t\t\t\tVAT\n+\t\t\t\t\n+\t\t\t\n+\t\t\n+\t\t\n+\t\t\t5000.00\n+\t\t\t2\n+\t\t\n+\t\n+\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\nindex 8a391d8117..7d3502ca5c 100644\n--- a/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\n+++ b/src/Apps/W1/EDocument/Test/src/Processing/EDocProcessTest.Codeunit.al\n@@ -21,6 +21,7 @@ using Microsoft.Inventory.Location;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.History;\n using Microsoft.Purchases.Payables;\n+using Microsoft.Purchases.Setup;\n using Microsoft.Purchases.Vendor;\n using Microsoft.Sales.Customer;\n using System.IO;\n@@ -884,6 +885,138 @@ codeunit 139883 \"E-Doc Process Test\"\n Assert.RecordCount(PurchaseLine, 2);\n end;\n \n+ [Test]\n+ procedure InvoicePostingDateDefaultsToWorkDateWhenSettingIsWorkDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Work Date\" (default), the created purchase invoice Posting Date equals WorkDate\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Work Date\" (default)\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL invoice (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-0.xml', TempEDocImportParams), 'The e-document should be processed');\n+\n+ // [THEN] Posting Date is WorkDate, not the document date\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(1, 1, 2027), PurchaseHeader.\"Posting Date\", 'Posting Date should be WorkDate when setting is Work Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure InvoicePostingDateUsesDocumentDateWhenSettingIsDocumentDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Document Date\", the created purchase invoice Posting Date equals the e-document's Document Date\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Document Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Document Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL invoice (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-no-currency.xml', TempEDocImportParams), 'The e-document should be processed');\n+\n+ // [THEN] Posting Date equals the Document Date from the PEPPOL file\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(22, 1, 2026), PurchaseHeader.\"Posting Date\", 'Posting Date should be Document Date when setting is Document Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure CreditMemoPostingDateDefaultsToWorkDateWhenSettingIsWorkDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Work Date\", the created purchase credit memo Posting Date equals WorkDate\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Work Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL credit note (IssueDate = 2026-02-15) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-creditnote-0.xml', TempEDocImportParams), 'The credit note e-document should be processed');\n+\n+ // [THEN] Posting Date is WorkDate\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(1, 1, 2027), PurchaseHeader.\"Posting Date\", 'Posting Date should be WorkDate when setting is Work Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n+ [Test]\n+ procedure CreditMemoPostingDateUsesDocumentDateWhenSettingIsDocumentDate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ TempEDocImportParams: Record \"E-Doc. Import Parameters\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ SavedWorkDate: Date;\n+ begin\n+ // [SCENARIO] When \"E-Doc. Def. Posting Date\" is \"Document Date\", the created purchase credit memo Posting Date equals the e-document's Document Date\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ // [GIVEN] Setup has \"E-Doc. Def. Posting Date\" = \"Document Date\"\n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Document Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n+ // [WHEN] A PEPPOL credit note (IssueDate = 2026-01-22) is processed with WorkDate = 2027-01-01\n+ TempEDocImportParams.\"Step to Run\" := \"Import E-Document Steps\"::\"Finish draft\";\n+ SavedWorkDate := WorkDate();\n+ WorkDate(DMY2Date(1, 1, 2027));\n+ Assert.IsTrue(LibraryEDoc.CreateInboundPEPPOLDocumentToState(EDocument, EDocumentService, 'peppol/peppol-invoice-no-currency.xml', TempEDocImportParams), 'The credit note e-document should be processed');\n+\n+ // [THEN] Posting Date equals the Document Date from the PEPPOL file\n+ EDocument.Get(EDocument.\"Entry No\");\n+ PurchaseHeader.Get(EDocument.\"Document Record ID\");\n+ Assert.AreEqual(DMY2Date(22, 1, 2026), PurchaseHeader.\"Posting Date\", 'Posting Date should be Document Date when setting is Document Date.');\n+\n+ WorkDate(SavedWorkDate);\n+ end;\n+\n local procedure Initialize(Integration: Enum \"Service Integration\")\n var\n TransformationRule: Record \"Transformation Rule\";\n@@ -893,6 +1026,7 @@ codeunit 139883 \"E-Doc Process Test\"\n EDocPurchLineFieldSetup: Record \"ED Purchase Line Field Setup\";\n PurchInvHeader: Record \"Purch. Inv. Header\";\n VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n GLSetup: Record \"General Ledger Setup\";\n Currency: Record Currency;\n LibraryERM: Codeunit \"Library - ERM\";\n@@ -902,6 +1036,10 @@ codeunit 139883 \"E-Doc Process Test\"\n Clear(EDocImplState);\n EDocPurchLineFieldSetup.DeleteAll();\n \n+ PurchasesPayablesSetup.GetRecordOnce();\n+ PurchasesPayablesSetup.\"E-Doc. Def. Posting Date\" := \"E-Doc. Purch.Def. Posting Date\"::\"Work Date\";\n+ PurchasesPayablesSetup.Modify();\n+\n PurchInvHeader.DeleteAll();\n VendorLedgerEntry.DeleteAll();\n \n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8251", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-20T13:52:50Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\EDocument\\App", "src\\Apps\\W1\\EDocument\\Test"], "patch": "diff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\nindex 556fbad792..6e67ed6537 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.PageExt.al\n@@ -26,6 +26,16 @@ pageextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n ApplicationArea = All;\n ToolTip = 'Specifies how the posting date is set on purchase invoices created from e-documents. Work Date uses the current work date. Document Date uses the document date from the e-document.';\n }\n+ field(\"Apply VAT Diff. For Purch EDoc\"; Rec.\"Apply VAT Diff. For Purch EDoc\")\n+ {\n+ ApplicationArea = All;\n+ ToolTip = 'Specifies whether VAT difference should be applied when matching incoming E-Document line with Purchase Order line';\n+ }\n+ field(\"Resolve VAT Group Purch EDoc\"; Rec.\"Resolve VAT Group Purch EDoc\")\n+ {\n+ ApplicationArea = All;\n+ ToolTip = 'Specifies whether to resolve VAT Product Group for purchase lines created from e-documents based on the VAT rate and the vendor''s VAT posting setup. If disabled, the VAT Product Group will not be identified based on the purchase e-document.';\n+ }\n }\n }\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\nindex 2dc0c9ccec..7da8eadd20 100644\n--- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n+++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchPayablesSetup.TableExt.al\n@@ -26,5 +26,17 @@ tableextension 6162 \"E-Doc. Purch. Payables Setup\" extends \"Purchases & Payables\n Caption = 'E-Document Default Posting Date';\n DataClassification = CustomerContent;\n }\n+ field(6103; \"Apply VAT Diff. For Purch EDoc\"; Boolean)\n+ {\n+ Caption = 'Apply VAT Diff. For Purch. E-Doc.';\n+ DataClassification = CustomerContent;\n+ InitValue = true;\n+ }\n+ field(6104; \"Resolve VAT Group Purch EDoc\"; Boolean)\n+ {\n+ Caption = 'Resolve VAT Product Group for Purch. E-Doc.';\n+ DataClassification = CustomerContent;\n+ InitValue = true;\n+ }\n }\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\nindex 2eceac35ed..37f6fea09e 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocCreatePurchaseInvoice.Codeunit.al\n@@ -178,6 +178,7 @@ codeunit 6117 \"E-Doc. Create Purchase Invoice\" implements IEDocumentFinishDraft,\n EDocLineByReceipt.Close();\n PurchaseHeader.Modify();\n PurchCalcDiscByType.ApplyInvDiscBasedOnAmt(EDocumentPurchaseHeader.\"Total Discount\", PurchaseHeader);\n+ EDocPurchaseDocumentHelper.ApplyVATDifferenceToLines(PurchaseHeader, EDocumentPurchaseHeader);\n exit(PurchaseHeader);\n end;\n \ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\nindex 857e73d309..cfc2d04acd 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/FinishDraft/EDocPurchDocHelper.Codeunit.al\n@@ -7,7 +7,9 @@ namespace Microsoft.eServices.EDocument.Processing.Import;\n using Microsoft.eServices.EDocument;\n using Microsoft.eServices.EDocument.Processing;\n using Microsoft.eServices.EDocument.Processing.Import.Purchase;\n+using Microsoft.Finance.Currency;\n using Microsoft.Finance.Dimension;\n+using Microsoft.Finance.VAT.Setup;\n using Microsoft.Foundation.Attachment;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.Posting;\n@@ -40,6 +42,9 @@ codeunit 6402 \"E-Doc. Purch. Doc. Helper\"\n PurchaseLine.\"Variant Code\" := EDocumentPurchaseLine.\"[BC] Variant Code\";\n PurchaseLine.Type := EDocumentPurchaseLine.\"[BC] Purchase Line Type\";\n ValidateFieldWithContext(PurchaseLine, PurchaseLine.FieldNo(\"No.\"), EDocumentPurchaseLine.\"[BC] Purchase Type No.\");\n+ if EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\" <> '' then\n+ ValidateFieldWithContext(\n+ PurchaseLine, PurchaseLine.FieldNo(\"VAT Prod. Posting Group\"), EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\");\n if (PurchaseLine.Type = PurchaseLine.Type::\"G/L Account\") and HasTotalDiscount then\n ValidateFieldWithContext(PurchaseLine, PurchaseLine.FieldNo(\"Allow Invoice Disc.\"), true);\n PurchaseLine.Description := EDocumentPurchaseLine.Description;\n@@ -154,6 +159,45 @@ codeunit 6402 \"E-Doc. Purch. Doc. Helper\"\n EDocImpSessionTelemetry.SetBool('Totals Validation', TryValidateDocumentTotals(PurchaseHeader));\n end;\n \n+ procedure ApplyVATDifferenceToLines(PurchaseHeader: Record \"Purchase Header\"; EDocumentPurchaseHeader: Record \"E-Document Purchase Header\")\n+ var\n+ PurchaseLine: Record \"Purchase Line\";\n+ Currency: Record Currency;\n+ LineAmount: Decimal;\n+ TotalLineAmount, VATDiffRemainder, VATDiffForLine : Decimal;\n+ AppliedVATAmountDiff: Decimal;\n+ begin\n+ AppliedVATAmountDiff := EDocumentPurchaseHeader.GetAppliedVATAmountDiff();\n+ if AppliedVATAmountDiff = 0 then\n+ exit;\n+\n+ if PurchaseHeader.\"Currency Code\" = '' then\n+ Currency.InitRoundingPrecision()\n+ else\n+ Currency.Get(PurchaseHeader.\"Currency Code\");\n+\n+ TotalLineAmount := ComputeTotalLineAmount(EDocumentPurchaseHeader.\"E-Document Entry No.\", Currency.\"Amount Rounding Precision\");\n+ if TotalLineAmount = 0 then\n+ exit;\n+\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseHeader.\"Document Type\");\n+ PurchaseLine.SetRange(\"Document No.\", PurchaseHeader.\"No.\");\n+ PurchaseLine.SetFilter(Type, '<>%1', PurchaseLine.Type::\" \");\n+ if not PurchaseLine.FindSet() then\n+ exit;\n+\n+ VATDiffRemainder := 0;\n+ repeat\n+ LineAmount := PurchaseLine.\"Line Amount\" - PurchaseLine.\"Inv. Discount Amount\";\n+ if LineAmount <> 0 then begin\n+ VATDiffForLine := VATDiffRemainder + AppliedVATAmountDiff * LineAmount / TotalLineAmount;\n+ PurchaseLine.Validate(\"VAT Difference\", Round(VATDiffForLine, Currency.\"Amount Rounding Precision\"));\n+ VATDiffRemainder := VATDiffForLine - PurchaseLine.\"VAT Difference\";\n+ PurchaseLine.Modify(true);\n+ end;\n+ until PurchaseLine.Next() = 0;\n+ end;\n+\n procedure RevertCreatedDocument(EDocument: Record \"E-Document\")\n var\n PurchaseHeader: Record \"Purchase Header\";\n@@ -181,4 +225,27 @@ codeunit 6402 \"E-Doc. Purch. Doc. Helper\"\n exit;\n PurchaseHeader.Validate(\"Posting Date\", EDocumentPurchaseHeader.\"Document Date\");\n end;\n+\n+ procedure SetNormalReverseChargeFilter(var VATPostingSetup: Record \"VAT Posting Setup\"; VATBusPostingGroup: Code[20])\n+ begin\n+ VATPostingSetup.SetRange(\"VAT Bus. Posting Group\", VATBusPostingGroup);\n+ VATPostingSetup.SetFilter(\"VAT Calculation Type\", '%1|%2',\n+ VATPostingSetup.\"VAT Calculation Type\"::\"Normal VAT\",\n+ VATPostingSetup.\"VAT Calculation Type\"::\"Reverse Charge VAT\");\n+ end;\n+\n+ local procedure ComputeTotalLineAmount(EDocEntryNo: Integer; AmountRoundingPrecision: Decimal): Decimal\n+ var\n+ EDocPurchLine: Record \"E-Document Purchase Line\";\n+ TotalLineAmount: Decimal;\n+ begin\n+ EDocPurchLine.SetRange(\"E-Document Entry No.\", EDocEntryNo);\n+ if EDocPurchLine.FindSet() then\n+ repeat\n+ TotalLineAmount += Round(\n+ EDocPurchLine.Quantity * EDocPurchLine.\"Unit Price\" - EDocPurchLine.\"Total Discount\",\n+ AmountRoundingPrecision);\n+ until EDocPurchLine.Next() = 0;\n+ exit(TotalLineAmount);\n+ end;\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/EDocPreparePurchDraft.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/EDocPreparePurchDraft.Codeunit.al\nindex 23612228b1..2b267d5875 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/EDocPreparePurchDraft.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/EDocPreparePurchDraft.Codeunit.al\n@@ -8,8 +8,11 @@ using Microsoft.eServices.EDocument;\n using Microsoft.eServices.EDocument.Processing.AI;\n using Microsoft.eServices.EDocument.Processing.Import.Purchase;\n using Microsoft.eServices.EDocument.Processing.Interfaces;\n+using Microsoft.Finance.GeneralLedger.Setup;\n+using Microsoft.Finance.VAT.Setup;\n using Microsoft.Foundation.UOM;\n using Microsoft.Purchases.Document;\n+using Microsoft.Purchases.Setup;\n using Microsoft.Purchases.Vendor;\n using System.Log;\n \n@@ -31,11 +34,15 @@ codeunit 6406 \"EDoc Prepare Purch. Draft\"\n Vendor: Record Vendor;\n PurchaseOrder: Record \"Purchase Header\";\n EDocVendorAssignmentHistory: Record \"E-Doc. Vendor Assign. History\";\n+\n EDocPurchaseHistMapping: Codeunit \"E-Doc. Purchase Hist. Mapping\";\n EDocActivityLogSession: Codeunit \"E-Doc. Activity Log Session\";\n IUnitOfMeasureProvider: Interface IUnitOfMeasureProvider;\n IPurchaseLineProvider: Interface IPurchaseLineProvider;\n IPurchaseOrderProvider: Interface IPurchaseOrderProvider;\n+ LineAmount: Decimal;\n+ LineVATAmount: Decimal;\n+ TotalLineVATAmount: Decimal;\n begin\n IUnitOfMeasureProvider := EDocImportParameters.\"Processing Customizations\";\n IPurchaseLineProvider := EDocImportParameters.\"Processing Customizations\";\n@@ -72,16 +79,26 @@ codeunit 6406 \"EDoc Prepare Purch. Draft\"\n EDocumentPurchaseLine.Modify();\n until EDocumentPurchaseLine.Next() = 0;\n \n+ // Resolve VAT Product Posting Groups from extracted VAT rates\n+ ResolveVATProductPostingGroups(EDocument.\"Entry No\", EDocumentPurchaseHeader);\n+\n CopilotLineMatching(EDocument.\"Entry No\");\n end;\n \n Clear(EDocumentPurchaseLine);\n EDocumentPurchaseLine.SetRange(\"E-Document Entry No.\", EDocument.\"Entry No\");\n+ TotalLineVATAmount := 0;\n if EDocumentPurchaseLine.FindSet() then\n repeat\n+ LineAmount := Round(EDocumentPurchaseLine.Quantity * EDocumentPurchaseLine.\"Unit Price\" - EDocumentPurchaseLine.\"Total Discount\");\n+ LineVATAmount := Round(LineAmount * EDocumentPurchaseLine.\"VAT Rate\" / 100);\n+ TotalLineVATAmount += LineVATAmount;\n EDocImpSessionTelemetry.SetLine(EDocumentPurchaseLine.SystemId);\n until EDocumentPurchaseLine.Next() = 0;\n \n+ ComputeAndApplyVATAmountDifference(EDocumentPurchaseHeader, TotalLineVATAmount);\n+ EDocumentPurchaseHeader.Modify();\n+\n LogAllActivitySessionChanges(EDocActivityLogSession);\n \n if EDocActivityLogSession.EndSession() then;\n@@ -138,6 +155,72 @@ codeunit 6406 \"EDoc Prepare Purch. Draft\"\n ActivityLog.Log();\n end;\n \n+ local procedure ResolveVATProductPostingGroups(EDocumentEntryNo: Integer; EDocumentPurchaseHeader: Record \"E-Document Purchase Header\")\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ Vendor: Record Vendor;\n+ VATRate: Decimal;\n+ LineBase: Decimal;\n+ LineCount: Integer;\n+ begin\n+ if not PurchasesPayablesSetup.Get() then\n+ exit;\n+ if not PurchasesPayablesSetup.\"Resolve VAT Group Purch EDoc\" then\n+ exit;\n+ Vendor := EDocumentPurchaseHeader.GetBCVendor();\n+ if Vendor.\"No.\" = '' then\n+ exit;\n+ if Vendor.\"VAT Bus. Posting Group\" = '' then\n+ exit;\n+\n+ EDocumentPurchaseLine.SetRange(\"E-Document Entry No.\", EDocumentEntryNo);\n+ LineCount := EDocumentPurchaseLine.Count();\n+ if LineCount = 0 then\n+ exit;\n+\n+ if EDocumentPurchaseLine.FindSet() then\n+ repeat\n+ VATRate := EDocumentPurchaseLine.\"VAT Rate\";\n+\n+ // Single-line fallback: compute from header Total VAT\n+ if (VATRate = 0) and (LineCount = 1) and (EDocumentPurchaseHeader.\"Total VAT\" > 0) then begin\n+ LineBase := EDocumentPurchaseLine.Quantity * EDocumentPurchaseLine.\"Unit Price\" - EDocumentPurchaseLine.\"Total Discount\";\n+ if LineBase = 0 then\n+ LineBase := EDocumentPurchaseHeader.\"Sub Total\";\n+ if LineBase > 0 then\n+ VATRate := Round((EDocumentPurchaseHeader.\"Total VAT\" / LineBase) * 100, 0.01);\n+ end;\n+\n+ if VATRate > 0 then begin\n+ EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\" :=\n+ FindVATProductPostingGroup(Vendor.\"VAT Bus. Posting Group\", VATRate);\n+ EDocumentPurchaseLine.Modify();\n+ if EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\" = '' then\n+ EDocumentPurchaseLine.LogVATRateMismatch(Vendor.\"VAT Bus. Posting Group\", VATRate)\n+ else\n+ EDocumentPurchaseLine.LogVATRateResolved(Vendor.\"VAT Bus. Posting Group\", VATRate);\n+ end;\n+ until EDocumentPurchaseLine.Next() = 0;\n+ end;\n+\n+ local procedure FindVATProductPostingGroup(VATBusPostingGroup: Code[20]; VATRate: Decimal): Code[20]\n+ var\n+ VATPostingSetup: Record \"VAT Posting Setup\";\n+ EDocPurchDocHelper: Codeunit \"E-Doc. Purch. Doc. Helper\";\n+ CustomDimensions: Dictionary of [Text, Text];\n+ VATPostingGroupNotFoundLbl: Label 'VAT Product Posting Group not found for VAT Rate %1.', Comment = '%1 = VAT rate', Locked = true;\n+ begin\n+ EDocPurchDocHelper.SetNormalReverseChargeFilter(VATPostingSetup, VATBusPostingGroup);\n+ VATPostingSetup.SetRange(\"VAT %\", VATRate);\n+ if VATPostingSetup.Count() = 1 then begin\n+ VATPostingSetup.FindFirst();\n+ exit(VATPostingSetup.\"VAT Prod. Posting Group\");\n+ end;\n+ Session.LogMessage('0000TXZ', StrSubstNo(VATPostingGroupNotFoundLbl, VATRate), Verbosity::Warning, DataClassification::SystemMetadata, TelemetryScope::All, CustomDimensions);\n+ exit('');\n+ end;\n+\n local procedure CopilotLineMatching(EDocumentEntryNo: Integer)\n var\n EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n@@ -172,4 +255,64 @@ codeunit 6406 \"EDoc Prepare Purch. Draft\"\n if Codeunit.Run(Codeunit::\"E-Doc. Deferral Matching\", EDocumentPurchaseLine) then;\n end;\n end;\n+\n+ local procedure ComputeAndApplyVATAmountDifference(EDocumentPurchaseHeader: Record \"E-Document Purchase Header\"; TotalLineVATAmount: Decimal)\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ GeneralLedgerSetup: Record \"General Ledger Setup\";\n+ ActivityLog: Codeunit \"Activity Log Builder\";\n+ VATAmountDiff: Decimal;\n+ Reasoning: Text[250];\n+ VATDiffAppliedLbl: Label 'Applied VAT amount difference of %1 to reconcile document Total VAT %2 with computed Total Line VAT Amount %3.', Comment = '%1 = VAT difference, %2 = Total VAT, %3 = Total Line VAT Amount';\n+ VATDiffSkippedSetupLbl: Label 'VAT amount difference of %1 was not applied because Apply VAT Diff. For Purch. E-Doc. is disabled in Purchases & Payables Setup.', Comment = '%1 = VAT difference';\n+ VATDiffSkippedAllowLbl: Label 'VAT amount difference of %1 was not applied because Allow VAT Difference is disabled in Purchases & Payables Setup.', Comment = '%1 = VAT difference';\n+ VATDiffSkippedMaxLbl: Label 'VAT amount difference of %1 was not applied because it exceeds the Max. VAT Difference Allowed of %2 in General Ledger Setup.', Comment = '%1 = VAT difference, %2 = Max. VAT Difference Allowed';\n+ begin\n+ if (EDocumentPurchaseHeader.\"Total VAT\" = 0) or (TotalLineVATAmount = EDocumentPurchaseHeader.\"Total VAT\") then\n+ exit;\n+\n+ VATAmountDiff := EDocumentPurchaseHeader.\"Total VAT\" - TotalLineVATAmount;\n+\n+ if not PurchasesPayablesSetup.Get() then\n+ exit;\n+\n+ if not PurchasesPayablesSetup.\"Apply VAT Diff. For Purch EDoc\" then begin\n+ Reasoning := CopyStr(StrSubstNo(VATDiffSkippedSetupLbl, VATAmountDiff), 1, MaxStrLen(Reasoning));\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Header\", EDocumentPurchaseHeader.FieldNo(\"Total VAT\"), EDocumentPurchaseHeader.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::\"AL\")\n+ .Log();\n+ exit;\n+ end;\n+\n+ if not PurchasesPayablesSetup.\"Allow VAT Difference\" then begin\n+ Reasoning := CopyStr(StrSubstNo(VATDiffSkippedAllowLbl, VATAmountDiff), 1, MaxStrLen(Reasoning));\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Header\", EDocumentPurchaseHeader.FieldNo(\"Total VAT\"), EDocumentPurchaseHeader.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::\"AL\")\n+ .Log();\n+ exit;\n+ end;\n+\n+ if not GeneralLedgerSetup.Get() then\n+ exit;\n+ if Abs(VATAmountDiff) > GeneralLedgerSetup.\"Max. VAT Difference Allowed\" then begin\n+ Reasoning := CopyStr(StrSubstNo(VATDiffSkippedMaxLbl, VATAmountDiff, GeneralLedgerSetup.\"Max. VAT Difference Allowed\"), 1, MaxStrLen(Reasoning));\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Header\", EDocumentPurchaseHeader.FieldNo(\"Total VAT\"), EDocumentPurchaseHeader.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::\"AL\")\n+ .Log();\n+ exit;\n+ end;\n+\n+ Reasoning := CopyStr(StrSubstNo(VATDiffAppliedLbl, VATAmountDiff, EDocumentPurchaseHeader.\"Total VAT\", TotalLineVATAmount), 1, MaxStrLen(Reasoning));\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Header\", EDocumentPurchaseHeader.FieldNo(\"Total VAT\"), EDocumentPurchaseHeader.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::\"AL\")\n+ .Log();\n+ end;\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al\nindex a49e0ab6aa..ee70da225f 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al\n@@ -10,6 +10,7 @@ using Microsoft.Finance.Dimension;\n using Microsoft.Inventory.Item.Catalog;\n using Microsoft.Purchases.Document;\n using Microsoft.Purchases.History;\n+using Microsoft.Purchases.Setup;\n \n page 6183 \"E-Doc. Purchase Draft Subform\"\n {\n@@ -71,6 +72,12 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n Lookup = true;\n ShowMandatory = true;\n }\n+ field(\"VAT Prod. Posting Group\"; Rec.\"[BC] VAT Prod. Posting Group\")\n+ {\n+ ApplicationArea = All;\n+ Lookup = true;\n+ Visible = VATProdPostGroupIsVisible;\n+ }\n field(\"Item Reference No.\"; Rec.\"[BC] Item Reference No.\")\n {\n ApplicationArea = All;\n@@ -333,7 +340,7 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n EDocPOMatching: Codeunit \"E-Doc. PO Matching\";\n AdditionalColumns, OrderMatchedCaption, MatchWarningsCaption, MatchWarningsStyleExpr : Text;\n LineAmount: Decimal;\n- DimVisible1, DimVisible2, HasAdditionalColumns, IsEDocumentMatchedToAnyPOLine, IsLineMatchedToOrderLine, IsLineMatchedToReceiptLine, HasEDocumentOrderMatchWarnings : Boolean;\n+ DimVisible1, DimVisible2, HasAdditionalColumns, IsEDocumentMatchedToAnyPOLine, IsLineMatchedToOrderLine, IsLineMatchedToReceiptLine, HasEDocumentOrderMatchWarnings, VATProdPostGroupIsVisible : Boolean;\n HistoryCantBeRetrievedErr: Label 'The purchase invoice that matched historically with this line can''t be opened.';\n \n trigger OnOpenPage()\n@@ -350,6 +357,7 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n trigger OnAfterGetCurrRecord()\n begin\n UpdatePOMatching();\n+ SetVATProductPostingGroupVisibility();\n end;\n \n trigger OnAfterGetRecord()\n@@ -362,6 +370,7 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n IsLineMatchedToReceiptLine := EDocPOMatching.IsEDocumentLineMatchedToAnyReceiptLine(EDocumentPurchaseLine);\n OrderMatchedCaption := IsLineMatchedToOrderLine ? GetSummaryOfMatchedOrders() : '';\n UpdateMatchWarnings();\n+ SetVATProductPostingGroupVisibility();\n end;\n \n internal procedure SetEDocumentPurchaseHeader(EDocPurchHeader: Record \"E-Document Purchase Header\")\n@@ -381,6 +390,14 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n DimVisible1, DimVisible2, DimOther, DimOther, DimOther, DimOther, DimOther, DimOther);\n end;\n \n+ local procedure SetVATProductPostingGroupVisibility()\n+ var\n+ PurchSetup: Record \"Purchases & Payables Setup\";\n+ begin\n+ PurchSetup.Get();\n+ VATProdPostGroupIsVisible := PurchSetup.\"Resolve VAT Group Purch EDoc\";\n+ end;\n+\n local procedure UpdateCalculatedAmounts(UpdateParentRecord: Boolean)\n var\n TotalEDocPurchaseLine: Record \"E-Document Purchase Line\";\n@@ -564,5 +581,4 @@ page 6183 \"E-Doc. Purchase Draft Subform\"\n if WarningDetails.Length() > 0 then\n Message(WarningDetails.ToText());\n end;\n-\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al\nindex 60c3eb6528..0dd57bc335 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseDraft.Page.al\n@@ -8,6 +8,7 @@ using Microsoft.eServices.EDocument;\n using Microsoft.eServices.EDocument.Processing.Import;\n using Microsoft.Foundation.Attachment;\n using Microsoft.Purchases.Document;\n+using Microsoft.Purchases.Setup;\n using Microsoft.Purchases.Vendor;\n using System.Feedback;\n using System.Telemetry;\n@@ -193,6 +194,16 @@ page 6181 \"E-Document Purchase Draft\"\n group(\"E-Document Details\")\n {\n ShowCaption = false;\n+ field(\"Applied VAT Amount Diff.\"; AppliedVATAmountDiff)\n+ {\n+ Caption = 'Applied VAT Amount Diff.';\n+ ToolTip = 'Specifies the VAT amount difference that was automatically applied to reconcile the document total VAT with the computed line VAT amounts.';\n+ Importance = Additional;\n+ Editable = false;\n+ Visible = ApplyVATDiffEnabled;\n+ AutoFormatType = 1;\n+ AutoFormatExpression = EDocumentPurchaseHeader.\"Currency Code\";\n+ }\n field(\"Amount Excl. VAT\"; EDocumentPurchaseHeader.\"Sub Total\")\n {\n Caption = 'Amount Excl. VAT';\n@@ -497,6 +508,7 @@ page 6181 \"E-Document Purchase Draft\"\n trigger OnOpenPage()\n var\n EDocumentDataStorage: Record \"E-Doc. Data Storage\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n EDocumentNotification: Codeunit \"E-Document Notification\";\n EDocPOMatching: Codeunit \"E-Doc. PO Matching\";\n MatchesRemovedMsg: Label 'This e-document was matched to purchase order lines, but the matches are no longer consistent with the current data. The matches have been removed';\n@@ -517,6 +529,8 @@ page 6181 \"E-Document Purchase Draft\"\n PageEditable := IsEditable();\n IsCreditMemo := Rec.\"Document Type\" = Enum::\"E-Document Type\"::\"Purchase Credit Memo\";\n EDocumentNotification.SendPurchaseDocumentDraftNotifications(Rec.\"Entry No\");\n+ if PurchasesPayablesSetup.Get() then\n+ ApplyVATDiffEnabled := PurchasesPayablesSetup.\"Apply VAT Diff. For Purch EDoc\";\n \n if Rec.\"Entry No\" <> 0 then\n Rec.SetRecFilter(); // Filter the record to only this instance to avoid navigation \n@@ -540,6 +554,8 @@ page 6181 \"E-Document Purchase Draft\"\n SetStyle();\n SetPageCaption();\n \n+ AppliedVATAmountDiff := EDocumentPurchaseHeader.GetAppliedVATAmountDiff();\n+\n Rec.CalcFields(\"Import Processing Status\");\n ShowFinalizeDraftAction := Rec.\"Import Processing Status\" in [Enum::\"Import E-Doc. Proc. Status\"::\"Ready for draft\", Enum::\"Import E-Doc. Proc. Status\"::\"Draft Ready\"];\n ShowAnalyzeDocumentAction :=\n@@ -775,4 +791,6 @@ page 6181 \"E-Document Purchase Draft\"\n ProcessingDocumentMsg: Label 'Processing document...';\n ResetDraftQst: Label 'All the changes that you may have made on the document draft will be lost. Do you want to continue?';\n PageEditable, HasPDFSource, IsCreditMemo : Boolean;\n+ ApplyVATDiffEnabled: Boolean;\n+ AppliedVATAmountDiff: Decimal;\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al\nindex 06a2997843..2abe927c57 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseHeader.Table.al\n@@ -6,7 +6,9 @@ namespace Microsoft.EServices.EDocument.Processing.Import.Purchase;\n \n using Microsoft.eServices.EDocument;\n using Microsoft.eServices.EDocument.Processing.Import;\n+using Microsoft.Finance.GeneralLedger.Setup;\n using Microsoft.Purchases.Document;\n+using Microsoft.Purchases.Setup;\n using Microsoft.Purchases.Vendor;\n using System.Telemetry;\n \n@@ -290,6 +292,45 @@ table 6100 \"E-Document Purchase Header\"\n if Vendor.Get(Rec.\"[BC] Vendor No.\") then;\n end;\n \n+ procedure GetAppliedVATAmountDiff(): Decimal\n+ var\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ GeneralLedgerSetup: Record \"General Ledger Setup\";\n+ LineAmount: Decimal;\n+ TotalLineVATAmount: Decimal;\n+ VATAmountDiff: Decimal;\n+ begin\n+ if Rec.\"Total VAT\" = 0 then\n+ exit(0);\n+\n+ if not PurchasesPayablesSetup.Get() then\n+ exit(0);\n+ if not PurchasesPayablesSetup.\"Apply VAT Diff. For Purch EDoc\" then\n+ exit(0);\n+ if not PurchasesPayablesSetup.\"Allow VAT Difference\" then\n+ exit(0);\n+ if not GeneralLedgerSetup.Get() then\n+ exit(0);\n+\n+ EDocumentPurchaseLine.SetRange(\"E-Document Entry No.\", Rec.\"E-Document Entry No.\");\n+ if EDocumentPurchaseLine.FindSet() then\n+ repeat\n+ LineAmount := Round(EDocumentPurchaseLine.Quantity * EDocumentPurchaseLine.\"Unit Price\" - EDocumentPurchaseLine.\"Total Discount\");\n+ TotalLineVATAmount += Round(LineAmount * EDocumentPurchaseLine.\"VAT Rate\" / 100);\n+ until EDocumentPurchaseLine.Next() = 0;\n+\n+ if TotalLineVATAmount = Rec.\"Total VAT\" then\n+ exit(0);\n+\n+ VATAmountDiff := Rec.\"Total VAT\" - TotalLineVATAmount;\n+\n+ if Abs(VATAmountDiff) > GeneralLedgerSetup.\"Max. VAT Difference Allowed\" then\n+ exit(0);\n+\n+ exit(VATAmountDiff);\n+ end;\n+\n internal procedure FeatureName(): Text\n begin\n exit('E-Document Matching Assistance');\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseLine.Table.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseLine.Table.al\nindex df4c126db9..7a2523070d 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseLine.Table.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocumentPurchaseLine.Table.al\n@@ -11,6 +11,7 @@ using Microsoft.Finance.AllocationAccount;\n using Microsoft.Finance.Deferral;\n using Microsoft.Finance.Dimension;\n using Microsoft.Finance.GeneralLedger.Account;\n+using Microsoft.Finance.VAT.Setup;\n using Microsoft.FixedAssets.FixedAsset;\n using Microsoft.Foundation.UOM;\n using Microsoft.Inventory.Item;\n@@ -20,6 +21,7 @@ using Microsoft.Purchases.Document;\n using Microsoft.Purchases.History;\n using Microsoft.Purchases.Vendor;\n using Microsoft.Utilities;\n+using System.Log;\n using System.Reflection;\n using System.Utilities;\n \n@@ -208,6 +210,26 @@ table 6101 \"E-Document Purchase Line\"\n DimMgt.UpdateGlobalDimFromDimSetID(\"[BC] Dimension Set ID\", \"[BC] Shortcut Dimension 1 Code\", \"[BC] Shortcut Dimension 2 Code\");\n end;\n }\n+ field(110; \"[BC] VAT Prod. Posting Group\"; Code[20])\n+ {\n+ Caption = 'VAT Prod. Posting Group';\n+ ToolTip = 'Specifies the VAT product posting group resolved from the extracted VAT rate.';\n+ TableRelation = \"VAT Product Posting Group\";\n+\n+ trigger OnLookup()\n+ var\n+ Vendor: Record Vendor;\n+ VATPostingSetup: Record \"VAT Posting Setup\";\n+ EDocPurchDocHelper: Codeunit \"E-Doc. Purch. Doc. Helper\";\n+ begin\n+ Vendor := Rec.GetBCVendor();\n+ if Vendor.\"No.\" = '' then\n+ exit;\n+ EDocPurchDocHelper.SetNormalReverseChargeFilter(VATPostingSetup, Vendor.\"VAT Bus. Posting Group\");\n+ if Page.RunModal(Page::\"VAT Posting Setup\", VATPostingSetup) = Action::LookupOK then\n+ Validate(\"[BC] VAT Prod. Posting Group\", VATPostingSetup.\"VAT Prod. Posting Group\");\n+ end;\n+ }\n #endregion Validated fields\n \n #region Metadata fields [201-300]\n@@ -374,4 +396,52 @@ table 6101 \"E-Document Purchase Line\"\n exit(GetEDocumentPurchaseHeader().GetBCVendor());\n end;\n \n+ internal procedure LogVATRateMismatch(VendVATBusPostingGroupCode: Code[20]; VATRate: Decimal)\n+ var\n+ VATPostingSetup: Record \"VAT Posting Setup\";\n+ EDocPurchDocHelper: Codeunit \"E-Doc. Purch. Doc. Helper\";\n+ ActivityLog: Codeunit \"Activity Log Builder\";\n+ VATPostingSetupRef: RecordRef;\n+ Reasoning: Text[250];\n+ VATRateMismatchReasonLbl: Label 'VAT rate %1% extracted from the document could not be matched to a VAT Posting Setup for vendor''s VAT Business Posting Group %2.', Comment = '%1 = extracted VAT rate %, %2 = VAT Bus. Posting Group code';\n+ VATRateMismatchTitleLbl: Label 'VAT Posting Setup for %1', Comment = '%1 = VAT Bus. Posting Group code';\n+ begin\n+ EDocPurchDocHelper.SetNormalReverseChargeFilter(VATPostingSetup, VendVATBusPostingGroupCode);\n+ VATPostingSetupRef.GetTable(VATPostingSetup);\n+\n+ Reasoning := CopyStr(StrSubstNo(VATRateMismatchReasonLbl, Rec.\"VAT Rate\", VendVATBusPostingGroupCode), 1, MaxStrLen(Reasoning));\n+\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Line\", Rec.FieldNo(\"[BC] VAT Prod. Posting Group\"), Rec.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::AL)\n+ .SetReferenceSource(Page::\"VAT Posting Setup\", VATPostingSetupRef)\n+ .SetReferenceTitle(StrSubstNo(VATRateMismatchTitleLbl, VendVATBusPostingGroupCode))\n+ .Log();\n+ end;\n+\n+ internal procedure LogVATRateResolved(VendVATBusPostingGroupCode: Code[20]; VATRate: Decimal)\n+ var\n+ VATPostingSetup: Record \"VAT Posting Setup\";\n+ EDocPurchDocHelper: Codeunit \"E-Doc. Purch. Doc. Helper\";\n+ ActivityLog: Codeunit \"Activity Log Builder\";\n+ VATPostingSetupRef: RecordRef;\n+ Reasoning: Text[250];\n+ VATRateResolvedReasonLbl: Label 'VAT rate %1% extracted from the document was matched to VAT Product Posting Group %2 for vendor''s VAT Business Posting Group %3.', Comment = '%1 = extracted VAT rate %, %2 = resolved VAT Prod. Posting Group code, %3 = VAT Bus. Posting Group code';\n+ VATRateResolvedTitleLbl: Label 'VAT Posting Setup for %1', Comment = '%1 = VAT Bus. Posting Group code';\n+ begin\n+ EDocPurchDocHelper.SetNormalReverseChargeFilter(VATPostingSetup, VendVATBusPostingGroupCode);\n+ VATPostingSetupRef.GetTable(VATPostingSetup);\n+\n+ Reasoning := CopyStr(StrSubstNo(VATRateResolvedReasonLbl, VATRate, Rec.\"[BC] VAT Prod. Posting Group\", VendVATBusPostingGroupCode), 1, MaxStrLen(Reasoning));\n+\n+ ActivityLog\n+ .Init(Database::\"E-Document Purchase Line\", Rec.FieldNo(\"[BC] VAT Prod. Posting Group\"), Rec.SystemId)\n+ .SetExplanation(Reasoning)\n+ .SetType(Enum::\"Activity Log Type\"::AL)\n+ .SetReferenceSource(Page::\"VAT Posting Setup\", VATPostingSetupRef)\n+ .SetReferenceTitle(StrSubstNo(VATRateResolvedTitleLbl, VendVATBusPostingGroupCode))\n+ .Log();\n+ end;\n+\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al\nindex 52ca55a954..ddc548d7f5 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/Import/StructureReceivedEDocument/EDocumentADIHandler.Codeunit.al\n@@ -182,9 +182,60 @@ codeunit 6174 \"E-Document ADI Handler\" implements IStructureReceivedEDocument, I\n EDocumentJsonHelper.SetStringValueInField('productCode', MaxStrLen(TempEDocPurchaseLine.\"Product Code\"), FieldsJsonObject, TempEDocPurchaseLine.\"Product Code\");\n EDocumentJsonHelper.SetStringValueInField('unit', MaxStrLen(TempEDocPurchaseLine.\"Unit of Measure\"), FieldsJsonObject, TempEDocPurchaseLine.\"Unit of Measure\");\n EDocumentJsonHelper.SetDateValueInField('date', FieldsJsonObject, TempEDocPurchaseLine.Date);\n- EDocumentJsonHelper.SetCurrencyValueInField('tax', FieldsJsonObject, TempEDocPurchaseLine.\"VAT Rate\", TempEDocPurchaseLine.\"Currency Code\");\n+ ResolveVATRateFromADI(FieldsJsonObject, TempEDocPurchaseLine);\n if TempEDocPurchaseLine.\"Unit Price\" <> 0 then\n TempEDocPurchaseLine.\"Total Discount\" := (TempEDocPurchaseLine.\"Unit Price\" * TempEDocPurchaseLine.Quantity) - TempEDocPurchaseLine.\"Sub Total\";\n end;\n+\n+ local procedure ResolveVATRateFromADI(FieldsJsonObject: JsonObject; var TempEDocPurchaseLine: Record \"E-Document Purchase Line\" temporary)\n+ var\n+ TaxRateText: Text;\n+ TaxAmount: Decimal;\n+ TaxValueText: Text;\n+ ParsedRate: Decimal;\n+ UnusedCurrencyCode: Code[10];\n+ begin\n+ // 1. Prefer TaxRate (string) — unambiguous percentage field from ADI\n+ EDocumentJsonHelper.SetStringValueInField('taxRate', MaxStrLen(TaxRateText), FieldsJsonObject, TaxRateText);\n+ if TaxRateText <> '' then begin\n+ ParsedRate := ParsePercentageFromText(TaxRateText);\n+ if ParsedRate >= 0 then begin\n+ TempEDocPurchaseLine.\"VAT Rate\" := ParsedRate;\n+ exit;\n+ end;\n+ end;\n+\n+ // 2. Fallback to Tax field — but it's ambiguous (can be amount, %, or Y/N)\n+ EDocumentJsonHelper.SetCurrencyValueInField('tax', FieldsJsonObject, TaxAmount, UnusedCurrencyCode);\n+ if TaxAmount = 0 then\n+ exit;\n+\n+ // Check value_text to disambiguate\n+ EDocumentJsonHelper.SetStringValueInField('tax', MaxStrLen(TaxValueText), FieldsJsonObject, TaxValueText);\n+ if TaxValueText.Contains('%') then\n+ // Tax field contains a percentage (e.g., \"20%\")\n+ TempEDocPurchaseLine.\"VAT Rate\" := TaxAmount\n+ else\n+ // Tax field contains a monetary amount (e.g., \"$6.00\") — compute percentage\n+ if TempEDocPurchaseLine.\"Sub Total\" > 0 then\n+ TempEDocPurchaseLine.\"VAT Rate\" := Round((TaxAmount / TempEDocPurchaseLine.\"Sub Total\") * 100, 0.01);\n+ end;\n+\n+ local procedure ParsePercentageFromText(TaxRateText: Text): Decimal\n+ var\n+ CleanedText: Text;\n+ ParsedValue: Decimal;\n+ begin\n+ // Strip common non-numeric prefixes/suffixes: \"VAT 20%\", \"20%\", \"20.0%\", \"20\"\n+ CleanedText := TaxRateText.Replace('%', '').Trim();\n+ // Remove common prefixes like \"VAT \", \"Tax \", etc.\n+ if CleanedText.StartsWith('VAT ') then\n+ CleanedText := CopyStr(CleanedText, 5).Trim();\n+ if CleanedText.StartsWith('Tax ') then\n+ CleanedText := CopyStr(CleanedText, 5).Trim();\n+ if Evaluate(ParsedValue, CleanedText) then\n+ exit(ParsedValue);\n+ exit(-1); // Signal parse failure\n+ end;\n #pragma warning restore AA0139\n }\ndiff --git a/src/Apps/W1/EDocument/App/src/Setup/EDocumentUpgrade.Codeunit.al b/src/Apps/W1/EDocument/App/src/Setup/EDocumentUpgrade.Codeunit.al\nindex a10d76086c..aad2d5d532 100644\n--- a/src/Apps/W1/EDocument/App/src/Setup/EDocumentUpgrade.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Setup/EDocumentUpgrade.Codeunit.al\n@@ -8,6 +8,7 @@ using Microsoft.eServices.EDocument.IO;\n #if not CLEAN29\n using Microsoft.eServices.EDocument.Processing.Import;\n #endif\n+using Microsoft.Purchases.Setup;\n using System.Upgrade;\n \n codeunit 6168 \"E-Document Upgrade\"\n@@ -24,6 +25,7 @@ codeunit 6168 \"E-Document Upgrade\"\n UpgradeProcessDraftEnum();\n #endif\n UpgradeDataExchV2Defs();\n+ UpgradeEnableVATOptionsForPurchEDoc();\n end;\n \n local procedure UpgradeLogURLMaxLength()\n@@ -63,6 +65,7 @@ codeunit 6168 \"E-Document Upgrade\"\n PerCompanyUpgradeTags.Add(GetUpgradeLogURLMaxLengthUpgradeTag());\n PerCompanyUpgradeTags.Add(GetUpgradeProcessDraftEnumTag());\n PerCompanyUpgradeTags.Add(GetUpgradeDataExchV2DefsTag());\n+ PerCompanyUpgradeTags.Add(GetEnableVATOptionsForPurchEDocTag());\n end;\n \n internal procedure GetUpgradeLogURLMaxLengthUpgradeTag(): Code[250]\n@@ -92,9 +95,30 @@ codeunit 6168 \"E-Document Upgrade\"\n exit('MS-EDoc-ProcessDraftEnum-20260407');\n end;\n \n+ local procedure UpgradeEnableVATOptionsForPurchEDoc()\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ UpgradeTag: Codeunit \"Upgrade Tag\";\n+ begin\n+ if UpgradeTag.HasUpgradeTag(GetEnableVATOptionsForPurchEDocTag()) then\n+ exit;\n+\n+ if PurchasesPayablesSetup.Get() then begin\n+ PurchasesPayablesSetup.\"Apply VAT Diff. For Purch EDoc\" := true;\n+ PurchasesPayablesSetup.\"Resolve VAT Group Purch EDoc\" := true;\n+ PurchasesPayablesSetup.Modify();\n+ end;\n+\n+ UpgradeTag.SetUpgradeTag(GetEnableVATOptionsForPurchEDocTag());\n+ end;\n internal procedure GetUpgradeDataExchV2DefsTag(): Code[250]\n begin\n exit('MS-EDoc-DataExchV2Defs-20260521');\n end;\n+ \n+ internal procedure GetEnableVATOptionsForPurchEDocTag(): Code[250]\n+ begin\n+ exit('MS-EDoc-EnableVATOptionsForPurchEDoc-20260520');\n+ end;\n \n }\n\\ No newline at end of file\n", "FAIL_TO_PASS": [{"codeunitID": 135576, "functionName": ["PreparingPurchaseDraftResolvesVATProductPostingGroupFromLineVATRate", "PreparingDraftIgnoresFullVATSetupWhenResolvingPostingGroup", "PreparingDraftIgnoresSalesTaxSetupWhenResolvingPostingGroup", "PreparingDraftResolvesReverseChargeVATPostingGroup", "PreparingPurchaseDraftSetsVATRateMismatchWhenNoMatchingVATSetup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/EDocument/Test/app.json b/src/Apps/W1/EDocument/Test/app.json\nindex dcc263b2e6..e182d37bc9 100644\n--- a/src/Apps/W1/EDocument/Test/app.json\n+++ b/src/Apps/W1/EDocument/Test/app.json\n@@ -74,7 +74,7 @@\n },\n {\n \"from\": 135575,\n- \"to\": 135575\n+ \"to\": 135576\n },\n {\n \"from\": 135647,\n@@ -94,4 +94,4 @@\n \"features\": [\n \"TranslationFile\"\n ]\n-}\n+}\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/Test/src/Processing/EDocPurchVATTests.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Processing/EDocPurchVATTests.Codeunit.al\nnew file mode 100644\nindex 0000000000..bbc1455dba\n--- /dev/null\n+++ b/src/Apps/W1/EDocument/Test/src/Processing/EDocPurchVATTests.Codeunit.al\n@@ -0,0 +1,416 @@\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+namespace Microsoft.eServices.EDocument.Test;\n+\n+using Microsoft.eServices.EDocument;\n+using Microsoft.eServices.EDocument.Integration;\n+using Microsoft.eServices.EDocument.Processing.Import;\n+using Microsoft.eServices.EDocument.Processing.Import.Purchase;\n+using Microsoft.Finance.Currency;\n+using Microsoft.Finance.GeneralLedger.Setup;\n+using Microsoft.Finance.VAT.Setup;\n+using Microsoft.Foundation.Company;\n+using Microsoft.Purchases.History;\n+using Microsoft.Purchases.Payables;\n+using Microsoft.Purchases.Setup;\n+using Microsoft.Purchases.Vendor;\n+using Microsoft.Sales.Customer;\n+using System.IO;\n+using System.TestLibraries.Utilities;\n+\n+codeunit 135576 \"E-Doc Purch. VAT Tests\"\n+{\n+ Subtype = Test;\n+ TestType = IntegrationTest;\n+\n+ var\n+ Vendor: Record Vendor;\n+ Customer: Record Customer;\n+ EDocumentService: Record \"E-Document Service\";\n+ Assert: Codeunit Assert;\n+ LibraryVariableStorage: Codeunit \"Library - Variable Storage\";\n+ LibraryEDoc: Codeunit \"Library - E-Document\";\n+ EDocImplState: Codeunit \"E-Doc. Impl. State\";\n+ LibraryLowerPermission: Codeunit \"Library - Lower Permissions\";\n+ LibrarySetupStorage: Codeunit \"Library - Setup Storage\";\n+ IsInitialized: Boolean;\n+\n+ [Test]\n+ procedure PreparingPurchaseDraftResolvesVATProductPostingGroupFromLineVATRate()\n+ var\n+ EDocument: Record \"E-Document\";\n+ EDocumentPurchaseHeader: Record \"E-Document Purchase Header\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ TempEDocImportParameters: Record \"E-Doc. Import Parameters\";\n+ Vendor2: Record Vendor;\n+ CompanyInformation: Record \"Company Information\";\n+ VATPostingSetup2: Record \"VAT Posting Setup\";\n+ VATProductPostingGroup: Record \"VAT Product Posting Group\";\n+ EDocumentProcessing: Codeunit \"E-Document Processing\";\n+ EDocImport: Codeunit \"E-Doc. Import\";\n+ LibraryERM: Codeunit \"Library - ERM\";\n+ begin\n+ // [SCENARIO] When a draft line has a VAT Rate and a matching VAT Posting Setup exists, Prepare Draft resolves the VAT Prod. Posting Group\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ SetResolveVATProductGroupInPurchSetup(true);\n+ LibraryEDoc.CreateInboundEDocument(EDocument, EDocumentService);\n+\n+ // [GIVEN] A vendor with a known VAT Bus. Posting Group\n+ CompanyInformation.GetRecordOnce();\n+ Vendor2.\"Country/Region Code\" := CompanyInformation.\"Country/Region Code\";\n+ Vendor2.\"No.\" := 'EDOC001';\n+ Vendor2.\"VAT Registration No.\" := 'XXXXXXX001';\n+ Vendor2.\"VAT Bus. Posting Group\" := Vendor.\"VAT Bus. Posting Group\";\n+ Vendor2.Insert();\n+\n+ // [GIVEN] A VAT Posting Setup with VAT % = 10 for the vendor's bus posting group\n+ LibraryERM.CreateVATProductPostingGroup(VATProductPostingGroup);\n+ VATPostingSetup2.\"VAT Bus. Posting Group\" := Vendor2.\"VAT Bus. Posting Group\";\n+ VATPostingSetup2.\"VAT Prod. Posting Group\" := VATProductPostingGroup.Code;\n+ VATPostingSetup2.\"VAT Calculation Type\" := VATPostingSetup2.\"VAT Calculation Type\"::\"Normal VAT\";\n+ VATPostingSetup2.\"VAT %\" := 10;\n+ VATPostingSetup2.\"Sales VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.\"Purchase VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.Insert();\n+\n+ // [GIVEN] E-Document purchase header and line with VAT Rate = 10\n+ EDocumentPurchaseHeader.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseHeader.\"Vendor VAT Id\" := Vendor2.\"VAT Registration No.\";\n+ EDocumentPurchaseHeader.Insert();\n+ EDocumentPurchaseLine.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseLine.Description := 'Test VAT resolution';\n+ EDocumentPurchaseLine.\"VAT Rate\" := 10;\n+ EDocumentPurchaseLine.Insert();\n+\n+ // [WHEN] Prepare Draft is run\n+ EDocumentProcessing.ModifyEDocumentProcessingStatus(EDocument, \"Import E-Doc. Proc. Status\"::\"Ready for draft\");\n+ TempEDocImportParameters.\"Step to Run\" := \"Import E-Document Steps\"::\"Prepare draft\";\n+ EDocImport.ProcessIncomingEDocument(EDocument, TempEDocImportParameters);\n+\n+ // [THEN] The VAT Prod. Posting Group is resolved from the matching setup\n+ EDocumentPurchaseLine.SetRecFilter();\n+ EDocumentPurchaseLine.FindFirst();\n+ Assert.AreEqual(VATProductPostingGroup.Code, EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\", 'The VAT Prod. Posting Group should be resolved from the matching VAT Posting Setup.');\n+\n+ // Cleanup\n+ Vendor2.SetRecFilter();\n+ Vendor2.Delete();\n+ VATPostingSetup2.SetRecFilter();\n+ VATPostingSetup2.Delete();\n+ VATProductPostingGroup.SetRecFilter();\n+ VATProductPostingGroup.Delete();\n+ end;\n+\n+ [Test]\n+ procedure PreparingPurchaseDraftSetsVATRateMismatchWhenNoMatchingVATSetup()\n+ var\n+ EDocument: Record \"E-Document\";\n+ EDocumentPurchaseHeader: Record \"E-Document Purchase Header\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ TempEDocImportParameters: Record \"E-Doc. Import Parameters\";\n+ Vendor2: Record Vendor;\n+ CompanyInformation: Record \"Company Information\";\n+ EDocumentProcessing: Codeunit \"E-Document Processing\";\n+ EDocImport: Codeunit \"E-Doc. Import\";\n+ begin\n+ // [SCENARIO] When a draft line has a VAT Rate but no matching VAT Posting Setup exists, Prepare Draft leaves the field blank and sets the mismatch flag\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ SetResolveVATProductGroupInPurchSetup(true);\n+ LibraryEDoc.CreateInboundEDocument(EDocument, EDocumentService);\n+\n+ // [GIVEN] A vendor with a known VAT Bus. Posting Group\n+ CompanyInformation.GetRecordOnce();\n+ Vendor2.\"Country/Region Code\" := CompanyInformation.\"Country/Region Code\";\n+ Vendor2.\"No.\" := 'EDOC001';\n+ Vendor2.\"VAT Registration No.\" := 'XXXXXXX001';\n+ Vendor2.\"VAT Bus. Posting Group\" := Vendor.\"VAT Bus. Posting Group\";\n+ Vendor2.Insert();\n+\n+ // [GIVEN] E-Document purchase header and line with VAT Rate = 99 (no matching setup)\n+ EDocumentPurchaseHeader.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseHeader.\"Vendor VAT Id\" := Vendor2.\"VAT Registration No.\";\n+ EDocumentPurchaseHeader.Insert();\n+ EDocumentPurchaseLine.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseLine.Description := 'Test VAT mismatch';\n+ EDocumentPurchaseLine.\"VAT Rate\" := 99;\n+ EDocumentPurchaseLine.Insert();\n+\n+ // [WHEN] Prepare Draft is run\n+ EDocumentProcessing.ModifyEDocumentProcessingStatus(EDocument, \"Import E-Doc. Proc. Status\"::\"Ready for draft\");\n+ TempEDocImportParameters.\"Step to Run\" := \"Import E-Document Steps\"::\"Prepare draft\";\n+ EDocImport.ProcessIncomingEDocument(EDocument, TempEDocImportParameters);\n+\n+ // [THEN] The VAT Prod. Posting Group is blank and mismatch flag is set\n+ EDocumentPurchaseLine.SetRecFilter();\n+ EDocumentPurchaseLine.FindFirst();\n+ Assert.AreEqual('', EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\", 'The VAT Prod. Posting Group should be blank when no matching VAT Posting Setup exists.');\n+\n+ // Cleanup\n+ Vendor2.SetRecFilter();\n+ Vendor2.Delete();\n+ end;\n+\n+ [Test]\n+ procedure PreparingDraftIgnoresFullVATSetupWhenResolvingPostingGroup()\n+ var\n+ EDocument: Record \"E-Document\";\n+ EDocumentPurchaseHeader: Record \"E-Document Purchase Header\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ TempEDocImportParameters: Record \"E-Doc. Import Parameters\";\n+ Vendor2: Record Vendor;\n+ CompanyInformation: Record \"Company Information\";\n+ VATPostingSetup2: Record \"VAT Posting Setup\";\n+ VATProductPostingGroup: Record \"VAT Product Posting Group\";\n+ EDocumentProcessing: Codeunit \"E-Document Processing\";\n+ EDocImport: Codeunit \"E-Doc. Import\";\n+ LibraryERM: Codeunit \"Library - ERM\";\n+ begin\n+ // [SCENARIO] Full VAT setups must not be matched during VAT Posting Group resolution\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ SetResolveVATProductGroupInPurchSetup(true);\n+ LibraryEDoc.CreateInboundEDocument(EDocument, EDocumentService);\n+\n+ // [GIVEN] A vendor\n+ CompanyInformation.GetRecordOnce();\n+ Vendor2.\"Country/Region Code\" := CompanyInformation.\"Country/Region Code\";\n+ Vendor2.\"No.\" := 'EDOC001';\n+ Vendor2.\"VAT Registration No.\" := 'XXXXXXX001';\n+ Vendor2.\"VAT Bus. Posting Group\" := Vendor.\"VAT Bus. Posting Group\";\n+ Vendor2.Insert();\n+\n+ // [GIVEN] A Full VAT Posting Setup with VAT % = 10\n+ LibraryERM.CreateVATProductPostingGroup(VATProductPostingGroup);\n+ VATPostingSetup2.\"VAT Bus. Posting Group\" := Vendor2.\"VAT Bus. Posting Group\";\n+ VATPostingSetup2.\"VAT Prod. Posting Group\" := VATProductPostingGroup.Code;\n+ VATPostingSetup2.\"VAT Calculation Type\" := VATPostingSetup2.\"VAT Calculation Type\"::\"Full VAT\";\n+ VATPostingSetup2.\"VAT %\" := 10;\n+ VATPostingSetup2.\"Sales VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.\"Purchase VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.Insert();\n+\n+ // [GIVEN] E-Document line with VAT Rate = 10\n+ EDocumentPurchaseHeader.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseHeader.\"Vendor VAT Id\" := Vendor2.\"VAT Registration No.\";\n+ EDocumentPurchaseHeader.Insert();\n+ EDocumentPurchaseLine.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseLine.Description := 'Test Full VAT ignored';\n+ EDocumentPurchaseLine.\"VAT Rate\" := 10;\n+ EDocumentPurchaseLine.Insert();\n+\n+ // [WHEN] Prepare Draft is run\n+ EDocumentProcessing.ModifyEDocumentProcessingStatus(EDocument, \"Import E-Doc. Proc. Status\"::\"Ready for draft\");\n+ TempEDocImportParameters.\"Step to Run\" := \"Import E-Document Steps\"::\"Prepare draft\";\n+ EDocImport.ProcessIncomingEDocument(EDocument, TempEDocImportParameters);\n+\n+ // [THEN] Full VAT setup is not matched\n+ EDocumentPurchaseLine.SetRecFilter();\n+ EDocumentPurchaseLine.FindFirst();\n+ Assert.AreEqual('', EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\", 'Full VAT setups must not be matched.');\n+\n+ // Cleanup\n+ Vendor2.SetRecFilter();\n+ Vendor2.Delete();\n+ VATPostingSetup2.SetRecFilter();\n+ VATPostingSetup2.Delete();\n+ VATProductPostingGroup.SetRecFilter();\n+ VATProductPostingGroup.Delete();\n+ end;\n+\n+ [Test]\n+ procedure PreparingDraftIgnoresSalesTaxSetupWhenResolvingPostingGroup()\n+ var\n+ EDocument: Record \"E-Document\";\n+ EDocumentPurchaseHeader: Record \"E-Document Purchase Header\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ TempEDocImportParameters: Record \"E-Doc. Import Parameters\";\n+ Vendor2: Record Vendor;\n+ CompanyInformation: Record \"Company Information\";\n+ VATPostingSetup2: Record \"VAT Posting Setup\";\n+ VATProductPostingGroup: Record \"VAT Product Posting Group\";\n+ EDocumentProcessing: Codeunit \"E-Document Processing\";\n+ EDocImport: Codeunit \"E-Doc. Import\";\n+ LibraryERM: Codeunit \"Library - ERM\";\n+ begin\n+ // [SCENARIO] Sales Tax setups must not be matched during VAT Posting Group resolution\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ SetResolveVATProductGroupInPurchSetup(true);\n+ LibraryEDoc.CreateInboundEDocument(EDocument, EDocumentService);\n+\n+ // [GIVEN] A vendor\n+ CompanyInformation.GetRecordOnce();\n+ Vendor2.\"Country/Region Code\" := CompanyInformation.\"Country/Region Code\";\n+ Vendor2.\"No.\" := 'EDOC001';\n+ Vendor2.\"VAT Registration No.\" := 'XXXXXXX001';\n+ Vendor2.\"VAT Bus. Posting Group\" := Vendor.\"VAT Bus. Posting Group\";\n+ Vendor2.Insert();\n+\n+ // [GIVEN] A Sales Tax Posting Setup with VAT % = 10\n+ LibraryERM.CreateVATProductPostingGroup(VATProductPostingGroup);\n+ VATPostingSetup2.\"VAT Bus. Posting Group\" := Vendor2.\"VAT Bus. Posting Group\";\n+ VATPostingSetup2.\"VAT Prod. Posting Group\" := VATProductPostingGroup.Code;\n+ VATPostingSetup2.\"VAT Calculation Type\" := VATPostingSetup2.\"VAT Calculation Type\"::\"Sales Tax\";\n+ VATPostingSetup2.\"VAT %\" := 10;\n+ VATPostingSetup2.\"Sales VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.\"Purchase VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.Insert();\n+\n+ // [GIVEN] E-Document line with VAT Rate = 10\n+ EDocumentPurchaseHeader.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseHeader.\"Vendor VAT Id\" := Vendor2.\"VAT Registration No.\";\n+ EDocumentPurchaseHeader.Insert();\n+ EDocumentPurchaseLine.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseLine.Description := 'Test Sales Tax ignored';\n+ EDocumentPurchaseLine.\"VAT Rate\" := 10;\n+ EDocumentPurchaseLine.Insert();\n+\n+ // [WHEN] Prepare Draft is run\n+ EDocumentProcessing.ModifyEDocumentProcessingStatus(EDocument, \"Import E-Doc. Proc. Status\"::\"Ready for draft\");\n+ TempEDocImportParameters.\"Step to Run\" := \"Import E-Document Steps\"::\"Prepare draft\";\n+ EDocImport.ProcessIncomingEDocument(EDocument, TempEDocImportParameters);\n+\n+ // [THEN] Sales Tax setup is not matched\n+ EDocumentPurchaseLine.SetRecFilter();\n+ EDocumentPurchaseLine.FindFirst();\n+ Assert.AreEqual('', EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\", 'Sales Tax setups must not be matched.');\n+\n+ // Cleanup\n+ Vendor2.SetRecFilter();\n+ Vendor2.Delete();\n+ VATPostingSetup2.SetRecFilter();\n+ VATPostingSetup2.Delete();\n+ VATProductPostingGroup.SetRecFilter();\n+ VATProductPostingGroup.Delete();\n+ end;\n+\n+ [Test]\n+ procedure PreparingDraftResolvesReverseChargeVATPostingGroup()\n+ var\n+ EDocument: Record \"E-Document\";\n+ EDocumentPurchaseHeader: Record \"E-Document Purchase Header\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ TempEDocImportParameters: Record \"E-Doc. Import Parameters\";\n+ Vendor2: Record Vendor;\n+ CompanyInformation: Record \"Company Information\";\n+ VATPostingSetup2: Record \"VAT Posting Setup\";\n+ VATProductPostingGroup: Record \"VAT Product Posting Group\";\n+ EDocumentProcessing: Codeunit \"E-Document Processing\";\n+ EDocImport: Codeunit \"E-Doc. Import\";\n+ LibraryERM: Codeunit \"Library - ERM\";\n+ begin\n+ // [SCENARIO] Reverse Charge VAT setups should be matched during VAT Posting Group resolution\n+ Initialize(Enum::\"Service Integration\"::\"Mock\");\n+ SetResolveVATProductGroupInPurchSetup(true);\n+ LibraryEDoc.CreateInboundEDocument(EDocument, EDocumentService);\n+\n+ // [GIVEN] A vendor\n+ CompanyInformation.GetRecordOnce();\n+ Vendor2.\"Country/Region Code\" := CompanyInformation.\"Country/Region Code\";\n+ Vendor2.\"No.\" := 'EDOC001';\n+ Vendor2.\"VAT Registration No.\" := 'XXXXXXX001';\n+ Vendor2.\"VAT Bus. Posting Group\" := Vendor.\"VAT Bus. Posting Group\";\n+ Vendor2.Insert();\n+\n+ // [GIVEN] A Reverse Charge VAT Posting Setup with VAT % = 20\n+ LibraryERM.CreateVATProductPostingGroup(VATProductPostingGroup);\n+ VATPostingSetup2.\"VAT Bus. Posting Group\" := Vendor2.\"VAT Bus. Posting Group\";\n+ VATPostingSetup2.\"VAT Prod. Posting Group\" := VATProductPostingGroup.Code;\n+ VATPostingSetup2.\"VAT Calculation Type\" := VATPostingSetup2.\"VAT Calculation Type\"::\"Reverse Charge VAT\";\n+ VATPostingSetup2.\"VAT %\" := 20;\n+ VATPostingSetup2.\"Sales VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.\"Purchase VAT Account\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.\"Reverse Chrg. VAT Acc.\" := LibraryERM.CreateGLAccountNo();\n+ VATPostingSetup2.Insert();\n+\n+ // [GIVEN] E-Document line with VAT Rate = 20\n+ EDocumentPurchaseHeader.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseHeader.\"Vendor VAT Id\" := Vendor2.\"VAT Registration No.\";\n+ EDocumentPurchaseHeader.Insert();\n+ EDocumentPurchaseLine.\"E-Document Entry No.\" := EDocument.\"Entry No\";\n+ EDocumentPurchaseLine.Description := 'Test Reverse Charge resolved';\n+ EDocumentPurchaseLine.\"VAT Rate\" := 20;\n+ EDocumentPurchaseLine.Insert();\n+\n+ // [WHEN] Prepare Draft is run\n+ EDocumentProcessing.ModifyEDocumentProcessingStatus(EDocument, \"Import E-Doc. Proc. Status\"::\"Ready for draft\");\n+ TempEDocImportParameters.\"Step to Run\" := \"Import E-Document Steps\"::\"Prepare draft\";\n+ EDocImport.ProcessIncomingEDocument(EDocument, TempEDocImportParameters);\n+\n+ // [THEN] Reverse Charge VAT setup is matched\n+ EDocumentPurchaseLine.SetRecFilter();\n+ EDocumentPurchaseLine.FindFirst();\n+ Assert.AreEqual(VATProductPostingGroup.Code, EDocumentPurchaseLine.\"[BC] VAT Prod. Posting Group\", 'Reverse Charge VAT setups should be matched.');\n+\n+ // Cleanup\n+ Vendor2.SetRecFilter();\n+ Vendor2.Delete();\n+ VATPostingSetup2.SetRecFilter();\n+ VATPostingSetup2.Delete();\n+ VATProductPostingGroup.SetRecFilter();\n+ VATProductPostingGroup.Delete();\n+ end;\n+\n+ local procedure Initialize(Integration: Enum \"Service Integration\")\n+ var\n+ TransformationRule: Record \"Transformation Rule\";\n+ EDocument: Record \"E-Document\";\n+ EDocDataStorage: Record \"E-Doc. Data Storage\";\n+ EDocumentServiceStatus: Record \"E-Document Service Status\";\n+ EDocPurchLineFieldSetup: Record \"ED Purchase Line Field Setup\";\n+ PurchInvHeader: Record \"Purch. Inv. Header\";\n+ VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ GLSetup: Record \"General Ledger Setup\";\n+ Currency: Record Currency;\n+ LibraryERM: Codeunit \"Library - ERM\";\n+ begin\n+ LibrarySetupStorage.Restore();\n+ LibraryLowerPermission.SetOutsideO365Scope();\n+ LibraryVariableStorage.Clear();\n+ Clear(EDocImplState);\n+ EDocPurchLineFieldSetup.DeleteAll();\n+\n+ PurchInvHeader.DeleteAll();\n+ VendorLedgerEntry.DeleteAll();\n+\n+ if IsInitialized then\n+ exit;\n+\n+ GLSetup.GetRecordOnce();\n+ GLSetup.\"VAT Reporting Date Usage\" := GLSetup.\"VAT Reporting Date Usage\"::Disabled;\n+ GLSetup.Modify();\n+\n+ // Set a currency that can be used across all localizations\n+ Currency.Init();\n+ Currency.Validate(Code, 'XYZ');\n+ if Currency.Insert(true) then\n+ LibraryERM.CreateExchangeRate(Currency.Code, WorkDate(), 1.0, 1.0);\n+\n+ EDocument.DeleteAll();\n+ EDocumentServiceStatus.DeleteAll();\n+ EDocumentService.DeleteAll();\n+ EDocDataStorage.DeleteAll();\n+\n+ LibraryEDoc.SetupStandardVAT();\n+ LibraryEDoc.SetupStandardSalesScenario(Customer, EDocumentService, Enum::\"E-Document Format\"::Mock, Integration);\n+ LibraryEDoc.SetupStandardPurchaseScenario(Vendor, EDocumentService, Enum::\"E-Document Format\"::Mock, Integration);\n+ EDocumentService.\"Import Process\" := \"E-Document Import Process\"::\"Version 2.0\";\n+ EDocumentService.\"Read into Draft Impl.\" := \"E-Doc. Read into Draft\"::PEPPOL;\n+ EDocumentService.Modify();\n+\n+ TransformationRule.DeleteAll();\n+ TransformationRule.CreateDefaultTransformations();\n+ LibrarySetupStorage.SavePurchasesSetup();\n+\n+ IsInitialized := true;\n+ end;\n+\n+ local procedure SetResolveVATProductGroupInPurchSetup(NewResolveVATProductGroup: Boolean)\n+ var\n+ PurchasesPayablesSetup: Record \"Purchases & Payables Setup\";\n+ begin\n+ PurchasesPayablesSetup.Get();\n+ PurchasesPayablesSetup.Validate(\"Resolve VAT Group Purch EDoc\", NewResolveVATProductGroup);\n+ PurchasesPayablesSetup.Modify();\n+ end;\n+}\ndiff --git a/src/Apps/W1/EDocument/Test/src/Processing/EDocStructuredValidations.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Processing/EDocStructuredValidations.Codeunit.al\nindex 98a99e284b..8245505fa7 100644\n--- a/src/Apps/W1/EDocument/Test/src/Processing/EDocStructuredValidations.Codeunit.al\n+++ b/src/Apps/W1/EDocument/Test/src/Processing/EDocStructuredValidations.Codeunit.al\n@@ -56,7 +56,7 @@ codeunit 139894 \"EDoc Structured Validations\"\n Assert.AreEqual('A123', EDocumentPurchaseLine.\"Product Code\", 'The product code in the purchase line does not allign with the mock data.');\n Assert.AreEqual('hours', EDocumentPurchaseLine.\"Unit of Measure\", 'The unit of measure in the purchase line does not allign with the mock data.');\n Assert.AreEqual(DMY2Date(4, 3, 2021), EDocumentPurchaseLine.Date, 'The date in the purchase line does not allign with the mock data.');\n- Assert.AreEqual(6, EDocumentPurchaseLine.\"VAT Rate\", 'The amount in the purchase line does not allign with the mock data.');\n+ Assert.AreEqual(10, EDocumentPurchaseLine.\"VAT Rate\", 'The VAT rate in the purchase line does not match the expected percentage.');\n \n EDocumentPurchaseLine.Next();\n Assert.AreEqual(30, EDocumentPurchaseLine.\"Sub Total\", 'The amount in the purchase line does not allign with the mock data.');\n@@ -67,7 +67,7 @@ codeunit 139894 \"EDoc Structured Validations\"\n Assert.AreEqual('B456', EDocumentPurchaseLine.\"Product Code\", 'The product code in the purchase line does not allign with the mock data.');\n Assert.AreEqual('', EDocumentPurchaseLine.\"Unit of Measure\", 'The unit of measure in the purchase line does not allign with the mock data.');\n Assert.AreEqual(DMY2Date(5, 3, 2021), EDocumentPurchaseLine.Date, 'The date in the purchase line does not allign with the mock data.');\n- Assert.AreEqual(3, EDocumentPurchaseLine.\"VAT Rate\", 'The amount in the purchase line does not allign with the mock data.');\n+ Assert.AreEqual(10, EDocumentPurchaseLine.\"VAT Rate\", 'The VAT rate in the purchase line does not match the expected percentage.');\n \n EDocumentPurchaseLine.Next();\n Assert.AreEqual(10, EDocumentPurchaseLine.\"Sub Total\", 'The amount does not allign with the mock data.');\n@@ -77,7 +77,7 @@ codeunit 139894 \"EDoc Structured Validations\"\n Assert.AreEqual('C789', EDocumentPurchaseLine.\"Product Code\", 'The product code does not allign with the mock data.');\n Assert.AreEqual('pages', EDocumentPurchaseLine.\"Unit of Measure\", 'The unit of measure does not allign with the mock data.');\n Assert.AreEqual(DMY2Date(6, 3, 2021), EDocumentPurchaseLine.Date, 'The date does not allign with the mock data.');\n- Assert.AreEqual(1, EDocumentPurchaseLine.\"VAT Rate\", 'The amount does not allign with the mock data.');\n+ Assert.AreEqual(10, EDocumentPurchaseLine.\"VAT Rate\", 'The VAT rate in the purchase line does not match the expected percentage.');\n end;\n \n internal procedure AssertMinimalCAPIDocumentParsed(EDocumentEntryNo: Integer)\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7414", "base_commit": "f2762782853b2527241f8ddd024f8153dda0a1ad", "created_at": "2026-03-26T20:40:25Z", "environment_setup_version": "28.0", "project_paths": ["src\\Apps\\W1\\Shopify\\App", "src\\Apps\\W1\\Shopify\\Test"], "patch": "diff --git a/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al b/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al\nindex 48dc876162..5cb2a5d3c1 100644\n--- a/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al\n+++ b/src/Apps/W1/Shopify/App/src/Base/Pages/ShpfyShopCard.Page.al\n@@ -170,6 +170,10 @@ page 30101 \"Shpfy Shop Card\"\n {\n ApplicationArea = All;\n }\n+ field(SyncHSCodeAndCountry; Rec.\"Sync HS Code and Country\")\n+ {\n+ ApplicationArea = All;\n+ }\n field(UOMAsVariant; Rec.\"UoM as Variant\")\n {\n ApplicationArea = All;\ndiff --git a/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al b/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al\nindex 311f89bf8e..8b29c15807 100644\n--- a/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al\n+++ b/src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al\n@@ -950,6 +950,13 @@ table 30102 \"Shpfy Shop\"\n DataClassification = SystemMetadata;\n InitValue = true;\n }\n+ field(209; \"Sync HS Code and Country\"; Boolean)\n+ {\n+ Caption = 'Sync HS Code and Country of Origin';\n+ ToolTip = 'Specifies whether the Tariff No. (as harmonized system code) and Country/Region of Origin Code are synchronized to Shopify variants. Required for AI channel distribution and customs-aware selling.';\n+ DataClassification = SystemMetadata;\n+ InitValue = true;\n+ }\n }\n \n keys\ndiff --git a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyCreateProduct.Codeunit.al b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyCreateProduct.Codeunit.al\nindex 2f9c67bf2b..8dafe40875 100644\n--- a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyCreateProduct.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyCreateProduct.Codeunit.al\n@@ -110,6 +110,10 @@ codeunit 30174 \"Shpfy Create Product\"\n TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item.\"No.\", ItemVariant.Code, Item.\"Vendor Item No.\");\n TempShopifyVariant.Taxable := true;\n TempShopifyVariant.Weight := ItemUnitofMeasure.\"Qty. per Unit of Measure\" > 0 ? Item.\"Gross Weight\" * ItemUnitofMeasure.\"Qty. per Unit of Measure\" : Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ TempShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ TempShopifyVariant.\"Country/Region of Origin Code\" := ProductExport.GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n TempShopifyVariant.\"Option 1 Name\" := 'Variant';\n TempShopifyVariant.\"Option 1 Value\" := ItemVariant.Code;\n TempShopifyVariant.\"Option 2 Name\" := Shop.\"Option Name for UoM\";\n@@ -132,6 +136,10 @@ codeunit 30174 \"Shpfy Create Product\"\n TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item.\"No.\", ItemVariant.Code, GetVendorItemNo(Item.\"No.\", ItemVariant.Code, Item.\"Sales Unit of Measure\"));\n TempShopifyVariant.Taxable := true;\n TempShopifyVariant.Weight := Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ TempShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ TempShopifyVariant.\"Country/Region of Origin Code\" := ProductExport.GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n TempShopifyVariant.\"Option 1 Name\" := 'Variant';\n TempShopifyVariant.\"Option 1 Value\" := ItemVariant.Code;\n TempShopifyVariant.\"Shop Code\" := Shop.Code;\n@@ -158,6 +166,10 @@ codeunit 30174 \"Shpfy Create Product\"\n TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item.\"No.\", '', Item.\"Vendor Item No.\");\n TempShopifyVariant.Taxable := true;\n TempShopifyVariant.Weight := ItemUnitofMeasure.\"Qty. per Unit of Measure\" > 0 ? Item.\"Gross Weight\" * ItemUnitofMeasure.\"Qty. per Unit of Measure\" : Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ TempShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ TempShopifyVariant.\"Country/Region of Origin Code\" := ProductExport.GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n TempShopifyVariant.\"Option 1 Name\" := Shop.\"Option Name for UoM\";\n TempShopifyVariant.\"Option 1 Value\" := ItemUnitofMeasure.Code;\n TempShopifyVariant.\"Shop Code\" := Shop.Code;\n@@ -239,6 +251,10 @@ codeunit 30174 \"Shpfy Create Product\"\n TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item.\"No.\", '', Item.\"Vendor Item No.\");\n TempShopifyVariant.Taxable := true;\n TempShopifyVariant.Weight := Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ TempShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ TempShopifyVariant.\"Country/Region of Origin Code\" := ProductExport.GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n TempShopifyVariant.\"Shop Code\" := Shop.Code;\n TempShopifyVariant.\"Item SystemId\" := Item.SystemId;\n TempShopifyVariant.Insert(false);\n@@ -285,4 +301,5 @@ codeunit 30174 \"Shpfy Create Product\"\n Page.Run(Page::\"Shpfy Shop Locations Mapping\", ShopLocation);\n end;\n end;\n+\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\nindex 75bd1bd20a..02a2e95b62 100644\n--- a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\n@@ -5,6 +5,7 @@\n \n namespace Microsoft.Integration.Shopify;\n \n+using Microsoft.Foundation.Address;\n using Microsoft.Foundation.ExtendedText;\n using Microsoft.Inventory.Item;\n using Microsoft.Inventory.Item.Attribute;\n@@ -368,6 +369,10 @@ codeunit 30178 \"Shpfy Product Export\"\n end;\n ShopifyVariant.Taxable := true;\n ShopifyVariant.Weight := ItemUnitofMeasure.\"Qty. per Unit of Measure\" > 0 ? Item.\"Gross Weight\" * ItemUnitofMeasure.\"Qty. per Unit of Measure\" : Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ ShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ ShopifyVariant.\"Country/Region of Origin Code\" := GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n ShopifyVariant.\"Option 1 Name\" := Shop.\"Option Name for UoM\";\n ShopifyVariant.\"Option 1 Value\" := ItemUnitofMeasure.Code;\n ShopifyVariant.\"Shop Code\" := Shop.Code;\n@@ -424,6 +429,10 @@ codeunit 30178 \"Shpfy Product Export\"\n end;\n ShopifyVariant.Taxable := true;\n ShopifyVariant.Weight := Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ ShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ ShopifyVariant.\"Country/Region of Origin Code\" := GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n if ShopifyVariant.\"Option 1 Name\" = '' then\n ShopifyVariant.\"Option 1 Name\" := 'Variant';\n if ShopifyVariant.\"Option 1 Name\" = 'Variant' then\n@@ -479,6 +488,10 @@ codeunit 30178 \"Shpfy Product Export\"\n end;\n ShopifyVariant.Taxable := true;\n ShopifyVariant.Weight := ItemUnitofMeasure.\"Qty. per Unit of Measure\" > 0 ? Item.\"Gross Weight\" * ItemUnitofMeasure.\"Qty. per Unit of Measure\" : Item.\"Gross Weight\";\n+ if Shop.\"Sync HS Code and Country\" then begin\n+ ShopifyVariant.\"Tariff No.\" := Item.\"Tariff No.\";\n+ ShopifyVariant.\"Country/Region of Origin Code\" := GetCountryISOCode(Item.\"Country/Region of Origin Code\");\n+ end;\n ShopifyVariant.\"Option 1 Name\" := 'Variant';\n ShopifyVariant.\"Option 1 Value\" := ItemVariant.Code;\n ShopifyVariant.\"Option 2 Name\" := Shop.\"Option Name for UoM\";\n@@ -1359,4 +1372,15 @@ codeunit 30178 \"Shpfy Product Export\"\n exit(true);\n end;\n #endregion\n+\n+ internal procedure GetCountryISOCode(CountryRegionCode: Code[10]): Code[10]\n+ var\n+ CountryRegion: Record \"Country/Region\";\n+ begin\n+ if CountryRegionCode = '' then\n+ exit('');\n+ if CountryRegion.Get(CountryRegionCode) then\n+ exit(CountryRegion.\"ISO Code\");\n+ exit(CountryRegionCode);\n+ end;\n }\ndiff --git a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al\nindex 2889cd32fd..99d52b1cb7 100644\n--- a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al\n@@ -189,7 +189,7 @@ codeunit 30189 \"Shpfy Variant API\"\n HasChange := true;\n GraphQuery.Append(', compareAtPrice: null');\n end;\n- if (ShopifyVariant.\"Unit Cost\" <> xShopifyVariant.\"Unit Cost\") or (ShopifyVariant.Weight <> xShopifyVariant.Weight) or (ShopifyVariant.SKU <> xShopifyVariant.SKU) then begin\n+ if (ShopifyVariant.\"Unit Cost\" <> xShopifyVariant.\"Unit Cost\") or (ShopifyVariant.Weight <> xShopifyVariant.Weight) or (ShopifyVariant.SKU <> xShopifyVariant.SKU) or (ShopifyVariant.\"Tariff No.\" <> xShopifyVariant.\"Tariff No.\") or (ShopifyVariant.\"Country/Region of Origin Code\" <> xShopifyVariant.\"Country/Region of Origin Code\") then begin\n HasChange := true;\n GraphQuery.Append(', inventoryItem: {tracked: ');\n if Shop.\"Inventory Tracked\" then\n@@ -206,6 +206,20 @@ codeunit 30189 \"Shpfy Variant API\"\n GraphQuery.Append(ShopifyVariant.SKU);\n GraphQuery.Append('\\\"');\n end;\n+ if ShopifyVariant.\"Tariff No.\" <> xShopifyVariant.\"Tariff No.\" then begin\n+ HasChange := true;\n+ GraphQuery.Append(', harmonizedSystemCode: \\\"');\n+ GraphQuery.Append(CommunicationMgt.EscapeGraphQLData(ShopifyVariant.\"Tariff No.\"));\n+ GraphQuery.Append('\\\"');\n+ end;\n+ if ShopifyVariant.\"Country/Region of Origin Code\" <> xShopifyVariant.\"Country/Region of Origin Code\" then begin\n+ HasChange := true;\n+ GraphQuery.Append(', countryCodeOfOrigin: ');\n+ if ShopifyVariant.\"Country/Region of Origin Code\" = '' then\n+ GraphQuery.Append('null')\n+ else\n+ GraphQuery.Append(ShopifyVariant.\"Country/Region of Origin Code\");\n+ end;\n if ShopifyVariant.Weight <> xShopifyVariant.Weight then begin\n GraphQuery.Append(', measurement: {weight: {value:');\n GraphQuery.Append(Format(ShopifyVariant.Weight, 0, 9));\n@@ -283,6 +297,15 @@ codeunit 30189 \"Shpfy Variant API\"\n GraphQuery.Append(CommunicationMgt.EscapeGraphQLData(ShopifyVariant.SKU));\n GraphQuery.Append('\\\"');\n end;\n+ if ShopifyVariant.\"Tariff No.\" <> '' then begin\n+ GraphQuery.Append(', harmonizedSystemCode: \\\"');\n+ GraphQuery.Append(CommunicationMgt.EscapeGraphQLData(ShopifyVariant.\"Tariff No.\"));\n+ GraphQuery.Append('\\\"');\n+ end;\n+ if ShopifyVariant.\"Country/Region of Origin Code\" <> '' then begin\n+ GraphQuery.Append(', countryCodeOfOrigin: ');\n+ GraphQuery.Append(ShopifyVariant.\"Country/Region of Origin Code\");\n+ end;\n if ShopifyVariant.Weight > 0 then begin\n GraphQuery.Append(', measurement: {weight: {value:');\n GraphQuery.Append(Format(ShopifyVariant.Weight, 0, 9));\ndiff --git a/src/Apps/W1/Shopify/App/src/Products/Tables/ShpfyVariant.Table.al b/src/Apps/W1/Shopify/App/src/Products/Tables/ShpfyVariant.Table.al\nindex 9538e494cf..d5a73a41bd 100644\n--- a/src/Apps/W1/Shopify/App/src/Products/Tables/ShpfyVariant.Table.al\n+++ b/src/Apps/W1/Shopify/App/src/Products/Tables/ShpfyVariant.Table.al\n@@ -202,6 +202,16 @@ table 30129 \"Shpfy Variant\"\n {\n DataClassification = SystemMetadata;\n }\n+ field(109; \"Tariff No.\"; Code[20])\n+ {\n+ Caption = 'Tariff No.';\n+ DataClassification = CustomerContent;\n+ }\n+ field(110; \"Country/Region of Origin Code\"; Code[10])\n+ {\n+ Caption = 'Country/Region of Origin Code';\n+ DataClassification = CustomerContent;\n+ }\n }\n keys\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139601, "functionName": ["UnitTestCreateTempProductSetsHSCodeAndCountryOfOrigin", "UnitTestCreateTempProductWithVariantsSetsHSCodeAndCountryOfOrigin", "UnitTestCreateTempProductEmptyHSCodeAndCountryOfOrigin"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Shopify/Test/Products/ShpfyCreateProductTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Products/ShpfyCreateProductTest.Codeunit.al\nindex 415db40208..70335c56fb 100644\n--- a/src/Apps/W1/Shopify/Test/Products/ShpfyCreateProductTest.Codeunit.al\n+++ b/src/Apps/W1/Shopify/Test/Products/ShpfyCreateProductTest.Codeunit.al\n@@ -2958,4 +2958,120 @@ codeunit 139601 \"Shpfy Create Product Test\"\n \n until TempShopifyVariant.Next() = 0;\n end;\n+\n+ [Test]\n+ procedure UnitTestCreateTempProductSetsHSCodeAndCountryOfOrigin()\n+ var\n+ Item: Record Item;\n+ TempShopifyProduct: Record \"Shpfy Product\" temporary;\n+ Shop: Record \"Shpfy Shop\";\n+ TempShopifyVariant: Record \"Shpfy Variant\" temporary;\n+ TempTag: Record \"Shpfy Tag\" temporary;\n+ CreateProduct: Codeunit \"Shpfy Create Product\";\n+ InitializeTest: Codeunit \"Shpfy Initialize Test\";\n+ ProductInitTest: Codeunit \"Shpfy Product Init Test\";\n+ begin\n+ // [SCENARIO] Creating a temp product from an Item with Tariff No. and Country/Region of Origin Code\n+ // should populate those fields on the Shopify variant.\n+\n+ // [GIVEN] A shop with HS/Country sync enabled\n+ Shop := InitializeTest.CreateShop();\n+ Shop.\"SKU Mapping\" := \"Shpfy SKU Mapping\"::\" \";\n+ Shop.\"Sync HS Code and Country\" := true;\n+ Shop.Modify();\n+ CreateProduct.SetShop(Shop);\n+\n+ // [GIVEN] An item with Tariff No. and Country/Region of Origin Code\n+ Item := ProductInitTest.CreateItem(Shop.\"Item Templ. Code\", Any.DecimalInRange(10, 100, 2), Any.DecimalInRange(100, 1000, 2));\n+ Item.\"Tariff No.\" := '6402.99.0000';\n+ Item.\"Country/Region of Origin Code\" := 'US';\n+ Item.Modify();\n+ Item.SetRecFilter();\n+\n+ // [WHEN] CreateTempProduct is called\n+ CreateProduct.CreateTempProduct(Item, TempShopifyProduct, TempShopifyVariant, TempTag);\n+\n+ // [THEN] The variant has Tariff No. populated\n+ LibraryAssert.AreEqual('6402.99.0000', TempShopifyVariant.\"Tariff No.\", 'TempShopifyVariant.\"Tariff No.\" should match Item.\"Tariff No.\"');\n+\n+ // [THEN] The variant has Country/Region of Origin Code populated\n+ LibraryAssert.AreEqual('US', TempShopifyVariant.\"Country/Region of Origin Code\", 'TempShopifyVariant.\"Country/Region of Origin Code\" should match Item.\"Country/Region of Origin Code\"');\n+ end;\n+\n+ [Test]\n+ procedure UnitTestCreateTempProductEmptyHSCodeAndCountryOfOrigin()\n+ var\n+ Item: Record Item;\n+ TempShopifyProduct: Record \"Shpfy Product\" temporary;\n+ Shop: Record \"Shpfy Shop\";\n+ TempShopifyVariant: Record \"Shpfy Variant\" temporary;\n+ TempTag: Record \"Shpfy Tag\" temporary;\n+ CreateProduct: Codeunit \"Shpfy Create Product\";\n+ InitializeTest: Codeunit \"Shpfy Initialize Test\";\n+ ProductInitTest: Codeunit \"Shpfy Product Init Test\";\n+ begin\n+ // [SCENARIO] Creating a temp product from an Item without Tariff No. and Country/Region of Origin Code\n+ // should leave those fields empty on the Shopify variant.\n+\n+ // [GIVEN] A shop with HS/Country sync enabled\n+ Shop := InitializeTest.CreateShop();\n+ Shop.\"SKU Mapping\" := \"Shpfy SKU Mapping\"::\" \";\n+ Shop.\"Sync HS Code and Country\" := true;\n+ Shop.Modify();\n+ CreateProduct.SetShop(Shop);\n+\n+ // [GIVEN] An item without Tariff No. and Country/Region of Origin Code\n+ Item := ProductInitTest.CreateItem(Shop.\"Item Templ. Code\", Any.DecimalInRange(10, 100, 2), Any.DecimalInRange(100, 1000, 2));\n+ Item.SetRecFilter();\n+\n+ // [WHEN] CreateTempProduct is called\n+ CreateProduct.CreateTempProduct(Item, TempShopifyProduct, TempShopifyVariant, TempTag);\n+\n+ // [THEN] The variant has empty Tariff No.\n+ LibraryAssert.AreEqual('', TempShopifyVariant.\"Tariff No.\", 'TempShopifyVariant.\"Tariff No.\" should be empty');\n+\n+ // [THEN] The variant has empty Country/Region of Origin Code\n+ LibraryAssert.AreEqual('', TempShopifyVariant.\"Country/Region of Origin Code\", 'TempShopifyVariant.\"Country/Region of Origin Code\" should be empty');\n+ end;\n+\n+ [Test]\n+ procedure UnitTestCreateTempProductWithVariantsSetsHSCodeAndCountryOfOrigin()\n+ var\n+ Item: Record Item;\n+ TempShopifyProduct: Record \"Shpfy Product\" temporary;\n+ Shop: Record \"Shpfy Shop\";\n+ TempShopifyVariant: Record \"Shpfy Variant\" temporary;\n+ TempTag: Record \"Shpfy Tag\" temporary;\n+ CreateProduct: Codeunit \"Shpfy Create Product\";\n+ InitializeTest: Codeunit \"Shpfy Initialize Test\";\n+ ProductInitTest: Codeunit \"Shpfy Product Init Test\";\n+ begin\n+ // [SCENARIO] Creating a temp product with variants from an Item with Tariff No. and Country/Region of Origin Code\n+ // should populate both fields on all variant records.\n+\n+ // [GIVEN] A shop with HS/Country sync enabled\n+ Shop := InitializeTest.CreateShop();\n+ Shop.\"SKU Mapping\" := \"Shpfy SKU Mapping\"::\" \";\n+ Shop.\"Sync HS Code and Country\" := true;\n+ Shop.Modify();\n+ CreateProduct.SetShop(Shop);\n+\n+ // [GIVEN] An item with variants and Tariff No.\n+ Item := ProductInitTest.CreateItem(Shop.\"Item Templ. Code\", Any.DecimalInRange(10, 100, 2), Any.DecimalInRange(100, 1000, 2), true);\n+ Item.\"Tariff No.\" := '8471.30.0100';\n+ Item.\"Country/Region of Origin Code\" := 'DE';\n+ Item.Modify();\n+ Item.SetRecFilter();\n+\n+ // [WHEN] CreateTempProduct is called\n+ CreateProduct.CreateTempProduct(Item, TempShopifyProduct, TempShopifyVariant, TempTag);\n+\n+ // [THEN] All variants have Tariff No. and Country of Origin populated\n+ TempShopifyVariant.Reset();\n+ if TempShopifyVariant.FindSet() then\n+ repeat\n+ LibraryAssert.AreEqual('8471.30.0100', TempShopifyVariant.\"Tariff No.\", 'Each variant should have Tariff No.');\n+ LibraryAssert.AreEqual('DE', TempShopifyVariant.\"Country/Region of Origin Code\", 'Each variant should have Country/Region of Origin Code');\n+ until TempShopifyVariant.Next() = 0;\n+ end;\n }\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "1b05b19c9b6ecee6e567858fc839d2342c6a0526", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.0", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} +{"metadata": {"area": "manufacturing", "image_count": 0}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "54df822ab4fd3bc4b2a1e0b11c4dd3bf75944e7e", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "8e12d8a72ecc80f705ea82baaa570a3bf2b234f0", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.0", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} diff --git a/dataset/problemstatement/microsoft__BCApps-7414/README.md b/dataset/problemstatement/microsoft__BCApps-7414/README.md deleted file mode 100644 index a92c723d0..000000000 --- a/dataset/problemstatement/microsoft__BCApps-7414/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# [Shopify] Sync HS Code and Country of Origin on variant export - -## Summary - -Addresses gaps identified in the Shopify Agentic Plan Product Sync Guide to ensure BC product catalogs meet the data requirements for AI channel distribution. - -- **Harmonized System Code**: Sync `Item."Tariff No."` as `harmonizedSystemCode` on variant export (both create and update paths) -- **Country of Origin**: Sync `Item."Country/Region of Origin Code"` as `countryCodeOfOrigin` on variant export -- New fields added to `Shpfy Variant` table and populated in `CreateTempProduct` (4 code paths) and `FillInProductVariantData` (3 overloads) -- New `Sync HS Code and Country of Origin` boolean on the Shop card (default on) gates the variant-field population, matching the pattern used by `Sync Item Extended Text` / `Marketing Text` / `Attributes` -- Tests added for HS code and country of origin field population - -Related docs PR for External URL extensibility example: MicrosoftDocs/dynamics365smb-devitpro#7259 - -Fixes [AB#632223](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/632223) - - - - diff --git a/dataset/problemstatement/microsoft__BCApps-7831/README.md b/dataset/problemstatement/microsoft__BCApps-7831/README.md index cba375c5a..2a39d36fa 100644 --- a/dataset/problemstatement/microsoft__BCApps-7831/README.md +++ b/dataset/problemstatement/microsoft__BCApps-7831/README.md @@ -1,20 +1,36 @@ -# Bug 620556: [Subcontracting] Align Subcontracting app with changes to the "Description 2" on various tables - -## Summary - -- **SubcPurchaseOrderCreator**: copy `Description 2` from `ProdOrderComponent` (not `Item`) to `PurchaseLine`; copy from `ProdOrderRoutingLine` (not blank) to `RequisitionLine` -- **SubcTempDataInitializer**: propagate `Description 2` from `RoutingLine` → temp `ProdOrderRoutingLine` and from `ProductionBOMLine` → temp `ProdOrderComponent` -- **SubcCreateProdOrdOpt**: include `Description 2` in `SetLoadFields`; propagate it to `PurchaseLine`, `ProductionBOMHeader`, `RoutingHeader`, `ProdOrderComponent`, and `ProdOrderRoutingLine` when committing wizard data -- **Pages**: surface `Description 2` (hidden) on `SubcProdOrderComponents`, `SubcPurchProvisionWizard`, and all four wizard list part pages - -## Root cause - -Bug 617366 added the `Description 2` field to manufacturing tables in the base app. The Subcontracting app was not updated to propagate that field through its wizard pipeline or purchase order creation flow, causing the field to be lost or blanked. - -Fixes [AB#620556](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/620556) - -🤖 Generated with [Claude Code](https://claude.com/claude-code) - - - - +# Title: [Subcontracting] Standard Task not propagated from Routing to Prod. Order Routing or Subcontracting Worksheet; prices not picked up +## Repro Steps: +![Image](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_apis/wit/attachments/10f744c3-9170-4590-8dd3-cf148b602b4a?fileName=image.png) + +## Hints: +### Repro Steps +**Summary**: The Subcontracting app needs to be aligned with changes made to the "Description 2" field on various tables. The bug description contains inline screenshots showing the field changes but minimal textual detail. + +#### Steps to Reproduce +1. Open Business Central with the Subcontracting module enabled. +2. Identify all tables in the Subcontracting app that reference or use the "Description 2" field (e.g., Item, Production Order Line, Purchase Line, or other related tables). +3. Check that the Subcontracting app properly reads, writes, and displays the "Description 2" field wherever it is used in the base BC application. +4. If "Description 2" has been modified (renamed, repositioned, or had its properties changed) in the base tables, verify that: + - All Subcontracting page extensions show the updated "Description 2" correctly. + - All Subcontracting codeunits that reference "Description 2" are aligned with the new field definition. + - All API queries or pages that expose "Description 2" reflect the changes. +5. Look for compilation errors or runtime issues caused by the misalignment. + +#### Expected Result +- The Subcontracting app should be fully aligned with any changes to the "Description 2" field in the base BC application. +- No compilation errors or data integrity issues related to this field. +- +#### Actual Result +- The Subcontracting app references are not aligned with the "Description 2" field changes, as shown in the inline screenshots. +- +#### Additional Context +- Related to +620425 [Subcontracting] "Single Instance Dictionary" is a very generic name. Rename & refactor it appropriately (SingleInstanceDictionary naming/refactoring). + +#### Self-Review +- The repro steps cover the general alignment concern but specific tables/pages affected are documented in the screenshots only. +- This is a code alignment/compatibility issue following upstream changes. + +**Score: 5/10** - The bug description is primarily screenshots with limited textual context. Steps provide a reasonable framework for verification. + +[AI-REPRO] score=5 | workItemId=620556 | generated=2026-03-25 | sources=Title,Description (inline images) diff --git a/dataset/problemstatement/microsoft__BCApps-7953/README.md b/dataset/problemstatement/microsoft__BCApps-7953/README.md deleted file mode 100644 index 8a34022b3..000000000 --- a/dataset/problemstatement/microsoft__BCApps-7953/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Bug 623926: Add configurable default posting date for e-document purchases - -## Why - -When the Payables Agent (or manual processing) creates purchase invoices and credit memos from incoming e-documents, the posting date always defaults to the current work date — ignoring the document date present in the e-document. This forces users to manually correct the posting date to match the original invoice date, which is error-prone and inconvenient. - -## Summary - -- **Added** `E-Doc. Default Posting Date` enum with "Work Date" (default) and "Document Date" options -- **Added** corresponding field to the Purchases & Payables Setup table and page extensions, allowing users to configure the behavior -- **Added** `ApplyDefaultPostingDateFromSetup` procedure in `EDocPurchDocHelper` — called during both invoice and credit memo creation to set the posting date from the e-document's document date when the setting is "Document Date" -- **Added** 4 tests covering invoice and credit memo scenarios for both posting date options, plus a new PEPPOL test resource XML - -[AB#623926](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/623926) - - - - - - diff --git a/dataset/problemstatement/microsoft__BCApps-8251/README.md b/dataset/problemstatement/microsoft__BCApps-8251/README.md deleted file mode 100644 index 98eed2f42..000000000 --- a/dataset/problemstatement/microsoft__BCApps-8251/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Add VAT rate resolution and VAT amount difference for E-Document purchases - -## Why - -When importing e-documents for purchase processing, the system did not automatically resolve VAT Product Posting Groups from extracted VAT rates. Users had to manually identify and assign the correct VAT posting group for each line, which was error-prone and time-consuming. Additionally, rounding differences between the document's total VAT and the computed line-level VAT amounts were not reconciled, leading to posting discrepancies. - -## Summary - -- **Added** VAT Product Posting Group resolution during Prepare Draft — matches the extracted VAT rate against VAT Posting Setup entries (Normal VAT and Reverse Charge VAT only) for the vendor's VAT Bus. Posting Group -- **Added** `[BC] VAT Prod. Posting Group` and `[BC] VAT Rate Mismatch` fields on E-Document Purchase Line with OnValidate/OnLookup support -- **Added** VAT amount difference computation and application to purchase lines when finalizing drafts, respecting Allow VAT Difference and Max. VAT Difference Allowed settings -- **Added** "Resolve VAT Group Purch EDoc" and "Apply VAT Diff. For Purch EDoc" toggles on Purchases & Payables Setup -- **Improved** ADI handler to prefer the unambiguous `taxRate` field and properly disambiguate the `tax` field between percentage and monetary values -- **Added** comprehensive test codeunit `E-Doc Purch. VAT Tests` covering resolution, mismatch detection, OnValidate behavior, and VAT calculation type filtering -- **Updated** existing structured validation tests to reflect corrected VAT rate expectations - -Fixes [AB#619564](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/619564) - - - - - - diff --git a/dataset/problemstatement/microsoft__BCApps-8253/README.md b/dataset/problemstatement/microsoft__BCApps-8253/README.md index 8e16f6d58..ffbd4dd13 100644 --- a/dataset/problemstatement/microsoft__BCApps-8253/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8253/README.md @@ -1,25 +1,74 @@ -# (Bug 633226): [Subcontracting] Standard Task not propagated from Routing to Prod. Order Routing or Subcontracting Worksheet; prices not picked up - -## Summary - -The Subcontracting Worksheet flow was dropping `Standard Task Code` between the Prod. Order Routing Line and the Requisition Line, the field on the worksheet was read-only, and Subcontractor Prices keyed on a Standard Task were therefore never applied. This change: - -- Propagates `Standard Task Code` from `Prod. Order Routing Line` to `Requisition Line` in both worksheet-population paths (Calculate Subcontracts… on the worksheet, and direct PO creation from a Prod. Order Routing line). -- Makes the `Standard Task Code` field editable on the Subcontracting Worksheet so users can override it. -- Causes the standard-task-bound subcontractor price to flow through to the Subcontracting Purchase Order's `Direct Unit Cost`. - -The bug enumerated four symptoms (Routing → Prod. Order Routing, Prod. Order Routing → Worksheet, field not editable, prices not picked up). Routing → Prod. Order Routing was already handled by `Prod. Order Routing Line.CopyFromRoutingLine`; no change there. The remaining three are addressed below. - -## Changes - -### `SubcCalcSubcontractsExt.Codeunit.al` -Extended the existing `OnAfterTransferProdOrderRoutingLine` subscriber on report `Subc. Calculate Subcontracts` to also `Validate("Standard Task Code", ProdOrderRoutingLine."Standard Task Code")` on the new requisition line. Using `Validate` (not direct assignment) fires the field's OnValidate trigger in `Subc. RequisitionLine`, which calls `UpdateSubcontractorPrice` → `Subc. Price Management.GetSubcPriceForReqLine`. The price lookup already filters `Subcontractor Price` by `RequisitionLine."Standard Task Code"` exactly, so the standard-task-bound price is applied immediately. - -### `SubcPurchaseOrderCreator.Codeunit.al` -Same fix in `InsertReqWkshLine`, which is the alternate worksheet-line builder used when a Subcontracting PO is created directly from a Prod. Order Routing Line (bypassing the worksheet UI). - -### `SubcSubcontractingWorksheet.Page.al` -Removed `Editable = false` from the `Standard Task Code` field and added a tooltip clarifying that editing the value re-applies the matching subcontractor price. The field's OnValidate already triggers price re-lookup, so manual edits/clears on the worksheet immediately update `Direct Unit Cost`. - -Fixes [AB#633226](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/633226) +# Title: [Subcontracting] Standard Task not propagated from Routing to Prod. Order Routing or Subcontracting Worksheet; prices not picked up +## Repro Steps: +**Issues:** +1. **Standard Task not propagated from Routing:** When a routing line has a Standard Task set, that value is not copied to the corresponding Prod. Order Routing line. +2. **Standard Task not propagated to Subcontracting Worksheet:** The Standard Task from the routing line is also not populated in the Subcontracting Worksheet when lines are pulled. +3. **Standard Task not editable in Subcontracting Worksheet:** Even if the field were present, it is not editable in the Subcontracting Worksheet, preventing manual correction. +4. **Prices not picked up:** If the user has configured prices tied to a Standard Task, those prices are not used because the Standard Task is missing from the subcontracting flow. + +**Expected:** Standard Task should be propagated from Routing to Prod. Order Routing and to the Subcontracting Worksheet. The field should be editable in the worksheet. Prices bound to Standard Task should be applied correctly. + +## Description: + + +## Hints + +### Repro Steps Clarity Score: 6/10 ++Specificity +Determinism +-Missing environment -Unverified UI references +-Missing data values (no concrete Standard Task / item / routing combo named in the bug) + +The bug enumerates 4 related symptoms but provides no concrete data combination. Steps below pick concrete demo values and a sequenced repro for each symptom. +---- +### Detailed Repro Steps +#### Environment +- Build: Master — Subcontracting feature dev build (target branch master). +- Localization: W1 (any localization should reproduce). +- Functional area: SCM / Manufacturing — Subcontracting (Standard Task propagation, Subcontracting Worksheet editing, Subcontracting price lookup). + +#### Prerequisites +- Subcontracting feature available with: a Subcontractor vendor, a Subcontracting Work Center, an item with a Production BOM and a Routing. +- A Standard Task code defined (e.g., STD-PAINT) — choose Search > Standard Tasks > + New to add one. +- A Routing that includes the Subcontracting Work Center, with at least one Routing Line whose Standard Task Code is set to STD-PAINT. +- A Subcontracting price (e.g., on the Standard Task card or on the Subcontracting Work Center / Subcontractor Vendor) that is specifically tied to Standard Task STD-PAINT (so that when STD-PAINT is present on the line, the price applies; when absent, it does not). +- A Released Production Order created from the manufacturing item with the routing above. + +#### Steps — Issue 1: Routing → Prod. Order Routing propagation +1. Choose Search > Routings, open the routing used by the manufacturing item, and confirm the Subcontracting routing line has Standard Task Code = STD-PAINT. +2. Choose Search > Released Production Orders, open the order created in prerequisites. +3. Drill into Lines > Routing to open Prod. Order Routing. +4. Observe Issue 1: the Prod. Order Routing line corresponding to the Subcontracting operation has Standard Task Code = blank (it was not copied from the source Routing). + +#### Steps — Issue 2: Routing → Subcontracting Worksheet propagation +5. Choose Search > Subcontracting Worksheet, choose the related link. +6. Choose Calculate Subcontracts…, accept defaults, run. +7. Observe Issue 2: the worksheet line for the production order's subcontracting operation has Standard Task Code = blank, even though the routing line has STD-PAINT set. + +#### Steps — Issue 3: Standard Task not editable in Subcontracting Worksheet +8. On the worksheet line from step 7, attempt to set Standard Task Code = STD-PAINT either by typing or via the lookup. +9. Observe Issue 3: the field is read-only / not editable, so the missing value cannot be corrected manually before Carry Out Action Message. + +#### Steps — Issue 4: Prices not picked up because Standard Task is missing +Without correcting the Standard Task (since you cannot, per Issue 3), choose Carry Out Action Message… to create the Subcontracting Purchase Order. +Open the resulting Subcontracting Purchase Order line. +Observe Issue 4: the Direct Unit Cost / line price is the work-center default price, not the price tied to Standard Task STD-PAINT. Because the Standard Task is missing from both the routing line and the worksheet, the price-lookup step never matches the standard-task-specific price and the wrong (or default) price is applied. + +#### Expected Result +- Routing → Prod. Order Routing → Subcontracting Worksheet → Subcontracting Purchase Order all preserve Standard Task Code end-to-end. +- The Standard Task Code field is editable in the Subcontracting Worksheet so users can correct or override. +- Subcontracting price lookup uses the Standard Task Code as a key, so prices defined per Standard Task are applied to the resulting PO line. + +#### Actual Result +- Standard Task Code is dropped at the Routing → Prod. Order Routing step, and remains missing on the Subcontracting Worksheet and the resulting Subcontracting PO. Prices tied to Standard Task are therefore never selected. + +#### Notes +- Severity 3, Priority 2. Issue type: Code Defect. Found by Manual Testing: Other Test Pass on 2026-04-30 by Chethan Thopaiah. +- Likely fix surfaces: + - Refresh production order routine (Codeunit "Prod. Order Routing Mgt." or equivalent) — copy Standard Task Code from Routing Line to Prod. Order Routing Line. + - Calculate Subcontracts (Codeunit "Subcontracting Worksheet Mgt." / similar) — copy Standard Task Code from Prod. Order Routing Line into the worksheet line. + - Page extension on Subcontracting Worksheet — set the Standard Task Code field Editable = true (subject to UX review). + - Subcontracting price lookup — extend the price-source lookup to include Standard Task Code as a key so prices tied to a Standard Task are matched. +- Sibling Subcontracting bugs that touch the routing → worksheet → PO chain: #633223, #633224, #633227, #633228, #633229. + +[AI-REPRO] score=6 | workItemId=633226 | generated=2026-04-30 | sources=repro_steps,documentation From 61e24044c76adb8ae855fbe30b20d6e634c5fb15 Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Fri, 29 May 2026 11:18:35 +0200 Subject: [PATCH 04/14] update --- dataset/bcbench.jsonl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index 438edba3f..02348a0a8 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -100,5 +100,5 @@ {"metadata": {"area": "inventory", "image_count": 7}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-176082", "base_commit": "cb30d50fe1ed2c716c6349370fdc31c6bd0ce956", "created_at": "2024-02-23", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137038, "functionName": ["GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\nindex e0b3ba5f0bf7..ffa98cfbb351 100644\n--- a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n@@ -48,6 +48,7 @@\n UndoneTransLineQtyErr: Label 'Expected Quantity to be 0 after Transfer Shipment was undone';\n DerivedTransLineErr: Label 'Expected no Derived Transfer Line i.e. line with \"Derived From Line No.\" equal to original transfer line.';\n IncorrectSNUndoneErr: Label 'The Serial No. of the item on the transfer shipment line that was undone was different from the SN on the corresponding transfer line.';\n+ ApplToItemEntryErr: Label '%1 must be %2 in %3.', Comment = '%1 is Appl-to Item Entry, %2 is Item Ledger Entry No. and %3 is Transfer Line';\n \n [Test]\n [HandlerFunctions('MessageHandler')]\n@@ -3655,6 +3656,99 @@\n ItemLedgerEntry.TestField(\"Cost Amount (Actual)\", NewCost);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('PostedPurchaseReceiptsModalPageHandler,PostedPurchRcptLinesModalPageHandler')]\n+ procedure GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines()\n+ var\n+ Item: Record Item;\n+ Vendor: Record Vendor;\n+ Location: Record Location;\n+ Location2: Record Location;\n+ Location3: Record Location;\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseHeader2: Record \"Purchase Header\";\n+ PurchaseHeader3: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ PurchaseLine2: Record \"Purchase Line\";\n+ PurchaseLine3: Record \"Purchase Line\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ TransferHeader: Record \"Transfer Header\";\n+ TransferLine: Record \"Transfer Line\";\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ ItemLedgerEntryNo: Integer;\n+ PurchaseReceiptNo: Code[20];\n+ TransferOrder: TestPage \"Transfer Order\";\n+ begin\n+ // [SCENARIO 500597] Get Receipt Lines action on Transfer Order shows list of Posted Purchase Receipts having Transfer-from Code in Location Code of Purch Rcpt Lines and after selecting it populates Appl-to Item Entry field in Transfer Lines.\n+ Initialize();\n+\n+ // [GIVEN] Create an Item and Validate Costing Method.\n+ LibraryInventory.CreateItem(Item);\n+ Item.Validate(\"Costing Method\", Item.\"Costing Method\"::FIFO);\n+ Item.Modify(true);\n+\n+ // [GIVEN] Create two Locations with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location2);\n+\n+ // [GIVEN] Create another Location with Inventory Posting Setup \n+ // And Validate Use As In-Transit.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location3);\n+ Location3.Validate(\"Use As In-Transit\", true);\n+ Location3.Modify(true);\n+\n+ // [GIVEN] Create a Vendor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+\n+ // [GIVEN] Create and Post Purchase Receipt with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader, PurchaseLine, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 2 with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader2, PurchaseLine2, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 3 with Location Code on Line.\n+ PurchaseReceiptNo := CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ PurchaseHeader3,\n+ PurchaseLine3,\n+ Vendor,\n+ Item,\n+ Location);\n+\n+ // [GIVEN] Find and save Item Ledger Entry No. in a Variable.\n+ ItemLedgerEntry.SetRange(\"Document No.\", PurchaseReceiptNo);\n+ ItemLedgerEntry.FindFirst();\n+ ItemLedgerEntryNo := ItemLedgerEntry.\"Entry No.\";\n+\n+ // [GIVEN] Find Purch. Rcpt Line.\n+ FindRandomReceiptLine(PurchaseReceiptNo, PurchRcptLine);\n+\n+ // [GIVEN] Create Transfer Header.\n+ LibraryInventory.CreateTransferHeader(TransferHeader, Location.Code, Location2.Code, Location3.Code);\n+\n+ // [GIVEN] Open Transfer Order page and run Get Receipt Line action.\n+ TransferOrder.OpenEdit();\n+ TransferOrder.GoToRecord(TransferHeader);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchRcptLine.\"No.\");\n+ TransferOrder.GetReceiptLines.Invoke();\n+\n+ // [WHEN] Find Transfer Line.\n+ TransferLine.SetRange(\"Document No.\", TransferHeader.\"No.\");\n+ TransferLine.FindFirst();\n+\n+ // [VERIFY] Appl-to Item Entry and Item Ledger Entry No. are same.\n+ Assert.AreEqual(\n+ ItemLedgerEntryNo,\n+ TransferLine.\"Appl.-to Item Entry\",\n+ StrSubstNo(\n+ ApplToItemEntryErr,\n+ TransferLine.FieldCaption(\"Appl.-to Item Entry\"),\n+ ItemLedgerEntryNo,\n+ TransferLine.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -5168,6 +5262,52 @@\n Assert.AreEqual(LineCount, TransferReceiptLine.Count(), '');\n end;\n \n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchHeader(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location)\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ PurchaseHeader.Validate(\"Location Code\", Location.Code);\n+ PurchaseHeader.Modify(true);\n+\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+ end;\n+\n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location): Code[20]\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Location Code\", Location.Code);\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ exit(LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false));\n+ end;\n+\n [MessageHandler]\n [Scope('OnPrem')]\n procedure MessageHandler(Message: Text[1024])\n@@ -5394,5 +5534,19 @@\n // 0 = Item.Type::Inventory\n Assert.AreEqual('0', ItemList.Filter.GetFilter(\"Type\"), 'Item List contains non-inventory items.');\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure PostedPurchRcptLinesModalPageHandler(var PostedPurchaseReceiptLines: Page \"Posted Purchase Receipt Lines\"; var Response: Action)\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ begin\n+ PurchRcptLine.SetRange(\"Document No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.SetRange(\"No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.FindFirst();\n+ PostedPurchaseReceiptLines.SetRecord(PurchRcptLine);\n+\n+ Response := ACTION::LookupOK;\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\nindex 5fe44b4568d1..c16ab8669925 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n@@ -1304,7 +1304,7 @@ table 5740 \"Transfer Header\"\n TempPurchRcptHeader: Record \"Purch. Rcpt. Header\" temporary;\n PostedPurchaseReceipts: Page \"Posted Purchase Receipts\";\n begin\n- PurchRcptHeader.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ FindPurchRcptHeader(PurchRcptHeader);\n PostedPurchaseReceipts.SetTableView(PurchRcptHeader);\n PostedPurchaseReceipts.LookupMode := true;\n if PostedPurchaseReceipts.RunModal() = ACTION::LookupOK then begin\n@@ -1376,6 +1376,8 @@ table 5740 \"Transfer Header\"\n PurchRcptLine.FilterPstdDocLnItemLedgEntries(ItemLedgerEntry);\n ItemTrackingDocMgt.CopyItemLedgerEntriesToTemp(TempItemLedgerEntry, ItemLedgerEntry);\n ItemTrackingMgt.CopyItemLedgEntryTrkgToTransferLine(TempItemLedgerEntry, TransferLine);\n+ TransferLine.\"Appl.-to Item Entry\" := ItemLedgerEntry.\"Entry No.\";\n+ TransferLine.Modify(true);\n \n OnAfterAddTransferLineFromReceiptLine(TransferLine, PurchRcptLine, TempItemLedgerEntry, Rec);\n end;\n@@ -1546,6 +1548,31 @@ table 5740 \"Transfer Header\"\n end;\n end;\n \n+ local procedure FindPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\")\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ DocumentNo: Code[20];\n+ begin\n+ PurchRcptLine.SetLoadFields(\"Document No.\", \"Location Code\");\n+ PurchRcptLine.SetCurrentKey(\"Document No.\");\n+ PurchRcptLine.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ if PurchRcptLine.FindSet() then\n+ repeat\n+ GetPurchRcptHeader(PurchRcptHeader, PurchRcptLine, DocumentNo);\n+ until PurchRcptLine.Next() = 0;\n+ PurchRcptHeader.MarkedOnly(true);\n+ end;\n+\n+ local procedure GetPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var DocumentNo: Code[20])\n+ begin\n+ if PurchRcptLine.\"Document No.\" = DocumentNo then\n+ exit;\n+\n+ PurchRcptHeader.Get(PurchRcptLine.\"Document No.\");\n+ PurchRcptHeader.Mark(true);\n+ DocumentNo := PurchRcptLine.\"Document No.\";\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnAddTransferLineFromReceiptLineOnBeforeTransferLineInsert(var TransferLine: Record \"Transfer Line\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var TransferHeader: Record \"Transfer Header\")\n begin\n"} {"metadata": {"area": "crm", "image_count": 8}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-174087", "base_commit": "74a0b7c175da3f9a272745bd34453a4712b73e7b", "created_at": "2024-02-02", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\Marketing"], "FAIL_TO_PASS": [{"codeunitID": 136208, "functionName": ["PopulateEvaluationFieldInInteractionLogEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\nindex 4c4c73700d2a..59fff6e2be93 100644\n--- a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n+++ b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n@@ -45,6 +45,7 @@ codeunit 136208 \"Marketing Interaction\"\n LoggedSegemntEntriesCreateMsg: Label 'Logged Segment entry was created';\n AttachmentFileShouldNotBeBlankErr: Label 'Attachment File should not be blank.';\n TxtFileExt: Label 'txt';\n+ EvaluationErr: Label '%1 must be %2 in %3', Comment = '%1 = Evaluation, %2 = Positive, %3 = Interaction Log Entry';\n \n [Test]\n [Scope('OnPrem')]\n@@ -2998,6 +2999,50 @@ codeunit 136208 \"Marketing Interaction\"\n VerifyAttachmentFileIsNotBlankOnInteractionLogEntry(Contact.\"No.\");\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('CreateInteractionFromContactPageHandler')]\n+ procedure PopulateEvaluationFieldInInteractionLogEntry()\n+ var\n+ Contact: Record Contact;\n+ InteractionTemplate: Record \"Interaction Template\";\n+ InteractionLogEntry: Record \"Interaction Log Entry\";\n+ ContactCard: TestPage \"Contact Card\";\n+ InteractionEvaluation: Enum \"Interaction Evaluation\";\n+ begin\n+ // [SCENARIO 498395] When stan creates an Interaction using Create Interaction action from Contact, Evaluation field should be populated in Interaction Log Entry.\n+ Initialize();\n+\n+ // [GIVEN] Create a Contact.\n+ LibraryMarketing.CreateCompanyContact(Contact);\n+\n+ // [GIVEN] Create an Interaction Template and Validate Information Flow.\n+ LibraryMarketing.CreateInteractionTemplate(InteractionTemplate);\n+ InteractionTemplate.Validate(\"Information Flow\", InteractionTemplate.\"Information Flow\"::Outbound);\n+ InteractionTemplate.Modify(true);\n+\n+ // [GIVEN] Open Contact Card and Create Interaction.\n+ ContactCard.OpenEdit();\n+ ContactCard.GoToRecord(Contact);\n+ LibraryVariableStorage.Enqueue(InteractionTemplate.Code);\n+ LibraryVariableStorage.Enqueue(Format(InteractionEvaluation::Positive));\n+ ContactCard.\"Create &Interaction\".Invoke();\n+\n+ // [WHEN] Find Interaction Log Entry.\n+ InteractionLogEntry.SetRange(\"Contact No.\", Contact.\"No.\");\n+ InteractionLogEntry.FindFirst();\n+\n+ // [VERIFY] Interaction Log Entry has Evaluation field populated as Positive.\n+ Assert.AreEqual(\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.Evaluation,\n+ StrSubstNo(\n+ EvaluationErr,\n+ InteractionLogEntry.FieldCaption(Evaluation),\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibrarySales: Codeunit \"Library - Sales\";\n@@ -4309,5 +4354,16 @@ CopyStr(StorageLocation, 1, MaxStrLen(MarketingSetup.\"Attachment Storage Locatio\n CreateInteraction.NextInteraction.Invoke();\n CreateInteraction.Finish.Invoke();\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure CreateInteractionFromContactPageHandler(var CreateInteraction: TestPage \"Create Interaction\")\n+ begin\n+ CreateInteraction.\"Interaction Template Code\".SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.Evaluation.SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.FinishInteraction.Invoke();\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\nindex ff43f4ff6a7b..05a21a6196bf 100644\n--- a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n+++ b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n@@ -694,6 +694,7 @@ page 5077 \"Create Interaction\"\n end;\n Step::\"Step 4\":\n begin\n+ InteractionLogEntry.CopyFromSegment(Rec);\n InteractionLogEntry.Modify();\n CurrPage.Close();\n end;\n"} {"metadata": {"area": "peppol", "image_count": 1}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8059", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-08T09:31:42Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\PEPPOL\\App", "src\\Apps\\W1\\PEPPOL\\Test"], "patch": "diff --git a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\nindex 30f5f792bd..c7981a46fa 100644\n--- a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n@@ -798,6 +798,8 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n InvoiceLineNote := DelChr(Format(SalesLine.Type), '<>');\n InvoicedQuantity := Format(SalesLine.Quantity, 0, 9);\n SalesLineLineAmount := SalesLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesLineLineAmount := Round(SalesLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n InvoiceLineExtensionAmount := Format(SalesLineLineAmount, 0, 9);\n LineExtensionAmountCurrencyID := GetSalesDocCurrencyCode(SalesHeader);\n InvoiceLineAccountingCost := '';\n@@ -869,7 +871,10 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n \n InvLnAllowanceChargeIndicator := 'false';\n InvLnAllowanceChargeReason := LineDisAmtTxt;\n- InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ InvLnAllowanceChargeAmount := Format(Round(SalesLine.\"Line Discount Amount\" / (1 + SalesLine.\"VAT %\" / 100), 0.01), 0, 9)\n+ else\n+ InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n InvLnAllowanceChargeAmtCurrID := GetSalesDocCurrencyCode(SalesHeader);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139235, "functionName": ["LineAmountsConsistentWhenPricesInclVATNoDiscount"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\nindex 36931d56ed..cd237011d5 100644\n--- a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n@@ -3349,6 +3349,68 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual('', CustTaxSchemeID, 'Tax Scheme ID should be empty for Tax Category O.');\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ procedure LineAmountsConsistentWhenPricesInclVATNoDiscount()\n+ var\n+ SalesHeader: Record \"Sales Header\";\n+ SalesLine: Record \"Sales Line\";\n+ Customer: Record Customer;\n+ Item: Record Item;\n+ SalesInvoiceHeader: Record \"Sales Invoice Header\";\n+ SalesInvoiceLine: Record \"Sales Invoice Line\";\n+ PEPPOLLineInfoProvider: Interface \"PEPPOL Line Info Provider\";\n+ InvoiceLineID: Text;\n+ InvoiceLineNote: Text;\n+ InvoicedQuantity: Text;\n+ InvoiceLineExtensionAmount: Text;\n+ LineExtensionAmountCurrencyID: Text;\n+ InvoiceLineAccountingCost: Text;\n+ InvoiceLinePriceAmount: Text;\n+ InvLinePriceAmountCurrencyID: Text;\n+ BaseQuantity: Text;\n+ UnitCode: Text;\n+ PriceAmount: Decimal;\n+ LineExtensionAmt: Decimal;\n+ SalesInvoiceNo: Code[20];\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 630795] PEPPOL LineExtensionAmount equals PriceAmount times Quantity when Prices Including VAT is used\n+ Initialize();\n+\n+ // [GIVEN] Customer \"C\" with PEPPOL identifier\n+ LibrarySales.CreateCustomer(Customer);\n+ AddCustPEPPOLIdentifier(Customer.\"No.\");\n+\n+ // [GIVEN] Sales Invoice for \"C\" with \"Prices Including VAT\" = TRUE and Quantity = 7\n+ CreateItemWithPrice(Item, 139);\n+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader.\"Document Type\"::Invoice, Customer.\"No.\");\n+ SalesHeader.Validate(\"Prices Including VAT\", true);\n+ SalesHeader.Modify(true);\n+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item.\"No.\", 7);\n+\n+ // [WHEN] Post the Sales Invoice and retrieve PEPPOL line amounts\n+ SalesInvoiceNo := LibrarySales.PostSalesDocument(SalesHeader, true, true);\n+ SalesInvoiceHeader.Get(SalesInvoiceNo);\n+ SalesHeader.TransferFields(SalesInvoiceHeader);\n+ FindSalesInvoiceLine(SalesInvoiceLine, SalesInvoiceNo);\n+ SalesLine.TransferFields(SalesInvoiceLine);\n+\n+ PEPPOLLineInfoProvider := GetFormat();\n+ PEPPOLLineInfoProvider.GetLineGeneralInfo(\n+ SalesLine, SalesHeader, InvoiceLineID, InvoiceLineNote, InvoicedQuantity,\n+ InvoiceLineExtensionAmount, LineExtensionAmountCurrencyID, InvoiceLineAccountingCost);\n+ PEPPOLLineInfoProvider.GetLinePriceInfo(\n+ SalesLine, SalesHeader, InvoiceLinePriceAmount, InvLinePriceAmountCurrencyID,\n+ BaseQuantity, UnitCode);\n+\n+ // [THEN] LineExtensionAmount equals PriceAmount times Quantity per PEPPOL BIS 3.0\n+ Evaluate(PriceAmount, InvoiceLinePriceAmount, 9);\n+ Evaluate(LineExtensionAmt, InvoiceLineExtensionAmount, 9);\n+ Assert.AreEqual(PriceAmount * SalesInvoiceLine.Quantity, LineExtensionAmt,\n+ 'LineExtensionAmount must equal PriceAmount * Quantity per PEPPOL BIS 3.0');\n+ end;\n+\n var\n local procedure Initialize()\n var\n@@ -3993,6 +4055,8 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual(UnitOfMeasure.\"International Standard Code\", unitCode, '');\n Assert.AreEqual('UNECERec20', unitCodeListID, '');\n SalesInvoiceLineLineAmount := SalesInvoiceLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesInvoiceLineLineAmount := Round(SalesInvoiceLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n Assert.AreEqual(Format(SalesInvoiceLineLineAmount, 0, 9), InvoiceLineExtensionAmount, '');\n Assert.AreEqual(SalesHeader.\"Currency Code\", LineExtensionAmountCurrencyID, '');\n Assert.AreEqual('', InvoiceLineAccountingCost, '');\n"} -{"metadata": {"area": "manufacturing", "image_count": 0}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "54df822ab4fd3bc4b2a1e0b11c4dd3bf75944e7e", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "8e12d8a72ecc80f705ea82baaa570a3bf2b234f0", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.0", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} +{"metadata": {"area": "manufacturing", "image_count": 0}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "cbbf3d36fdf3aeeaefa5bd59e13023fbc9f33c9c", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "8e12d8a72ecc80f705ea82baaa570a3bf2b234f0", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} From a123ef0c9fb2f002f105d7ca6fdb358502d06d65 Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Fri, 29 May 2026 13:41:20 +0200 Subject: [PATCH 05/14] 7831 use 84eb1813a9322dd1fe6d7a60689e5bcc1ddebf97 --- dataset/bcbench.jsonl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index 02348a0a8..9ae32329f 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -101,4 +101,4 @@ {"metadata": {"area": "crm", "image_count": 8}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-174087", "base_commit": "74a0b7c175da3f9a272745bd34453a4712b73e7b", "created_at": "2024-02-02", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\Marketing"], "FAIL_TO_PASS": [{"codeunitID": 136208, "functionName": ["PopulateEvaluationFieldInInteractionLogEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\nindex 4c4c73700d2a..59fff6e2be93 100644\n--- a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n+++ b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n@@ -45,6 +45,7 @@ codeunit 136208 \"Marketing Interaction\"\n LoggedSegemntEntriesCreateMsg: Label 'Logged Segment entry was created';\n AttachmentFileShouldNotBeBlankErr: Label 'Attachment File should not be blank.';\n TxtFileExt: Label 'txt';\n+ EvaluationErr: Label '%1 must be %2 in %3', Comment = '%1 = Evaluation, %2 = Positive, %3 = Interaction Log Entry';\n \n [Test]\n [Scope('OnPrem')]\n@@ -2998,6 +2999,50 @@ codeunit 136208 \"Marketing Interaction\"\n VerifyAttachmentFileIsNotBlankOnInteractionLogEntry(Contact.\"No.\");\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('CreateInteractionFromContactPageHandler')]\n+ procedure PopulateEvaluationFieldInInteractionLogEntry()\n+ var\n+ Contact: Record Contact;\n+ InteractionTemplate: Record \"Interaction Template\";\n+ InteractionLogEntry: Record \"Interaction Log Entry\";\n+ ContactCard: TestPage \"Contact Card\";\n+ InteractionEvaluation: Enum \"Interaction Evaluation\";\n+ begin\n+ // [SCENARIO 498395] When stan creates an Interaction using Create Interaction action from Contact, Evaluation field should be populated in Interaction Log Entry.\n+ Initialize();\n+\n+ // [GIVEN] Create a Contact.\n+ LibraryMarketing.CreateCompanyContact(Contact);\n+\n+ // [GIVEN] Create an Interaction Template and Validate Information Flow.\n+ LibraryMarketing.CreateInteractionTemplate(InteractionTemplate);\n+ InteractionTemplate.Validate(\"Information Flow\", InteractionTemplate.\"Information Flow\"::Outbound);\n+ InteractionTemplate.Modify(true);\n+\n+ // [GIVEN] Open Contact Card and Create Interaction.\n+ ContactCard.OpenEdit();\n+ ContactCard.GoToRecord(Contact);\n+ LibraryVariableStorage.Enqueue(InteractionTemplate.Code);\n+ LibraryVariableStorage.Enqueue(Format(InteractionEvaluation::Positive));\n+ ContactCard.\"Create &Interaction\".Invoke();\n+\n+ // [WHEN] Find Interaction Log Entry.\n+ InteractionLogEntry.SetRange(\"Contact No.\", Contact.\"No.\");\n+ InteractionLogEntry.FindFirst();\n+\n+ // [VERIFY] Interaction Log Entry has Evaluation field populated as Positive.\n+ Assert.AreEqual(\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.Evaluation,\n+ StrSubstNo(\n+ EvaluationErr,\n+ InteractionLogEntry.FieldCaption(Evaluation),\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibrarySales: Codeunit \"Library - Sales\";\n@@ -4309,5 +4354,16 @@ CopyStr(StorageLocation, 1, MaxStrLen(MarketingSetup.\"Attachment Storage Locatio\n CreateInteraction.NextInteraction.Invoke();\n CreateInteraction.Finish.Invoke();\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure CreateInteractionFromContactPageHandler(var CreateInteraction: TestPage \"Create Interaction\")\n+ begin\n+ CreateInteraction.\"Interaction Template Code\".SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.Evaluation.SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.FinishInteraction.Invoke();\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\nindex ff43f4ff6a7b..05a21a6196bf 100644\n--- a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n+++ b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n@@ -694,6 +694,7 @@ page 5077 \"Create Interaction\"\n end;\n Step::\"Step 4\":\n begin\n+ InteractionLogEntry.CopyFromSegment(Rec);\n InteractionLogEntry.Modify();\n CurrPage.Close();\n end;\n"} {"metadata": {"area": "peppol", "image_count": 1}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8059", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-08T09:31:42Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\PEPPOL\\App", "src\\Apps\\W1\\PEPPOL\\Test"], "patch": "diff --git a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\nindex 30f5f792bd..c7981a46fa 100644\n--- a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n@@ -798,6 +798,8 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n InvoiceLineNote := DelChr(Format(SalesLine.Type), '<>');\n InvoicedQuantity := Format(SalesLine.Quantity, 0, 9);\n SalesLineLineAmount := SalesLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesLineLineAmount := Round(SalesLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n InvoiceLineExtensionAmount := Format(SalesLineLineAmount, 0, 9);\n LineExtensionAmountCurrencyID := GetSalesDocCurrencyCode(SalesHeader);\n InvoiceLineAccountingCost := '';\n@@ -869,7 +871,10 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n \n InvLnAllowanceChargeIndicator := 'false';\n InvLnAllowanceChargeReason := LineDisAmtTxt;\n- InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ InvLnAllowanceChargeAmount := Format(Round(SalesLine.\"Line Discount Amount\" / (1 + SalesLine.\"VAT %\" / 100), 0.01), 0, 9)\n+ else\n+ InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n InvLnAllowanceChargeAmtCurrID := GetSalesDocCurrencyCode(SalesHeader);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139235, "functionName": ["LineAmountsConsistentWhenPricesInclVATNoDiscount"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\nindex 36931d56ed..cd237011d5 100644\n--- a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n@@ -3349,6 +3349,68 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual('', CustTaxSchemeID, 'Tax Scheme ID should be empty for Tax Category O.');\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ procedure LineAmountsConsistentWhenPricesInclVATNoDiscount()\n+ var\n+ SalesHeader: Record \"Sales Header\";\n+ SalesLine: Record \"Sales Line\";\n+ Customer: Record Customer;\n+ Item: Record Item;\n+ SalesInvoiceHeader: Record \"Sales Invoice Header\";\n+ SalesInvoiceLine: Record \"Sales Invoice Line\";\n+ PEPPOLLineInfoProvider: Interface \"PEPPOL Line Info Provider\";\n+ InvoiceLineID: Text;\n+ InvoiceLineNote: Text;\n+ InvoicedQuantity: Text;\n+ InvoiceLineExtensionAmount: Text;\n+ LineExtensionAmountCurrencyID: Text;\n+ InvoiceLineAccountingCost: Text;\n+ InvoiceLinePriceAmount: Text;\n+ InvLinePriceAmountCurrencyID: Text;\n+ BaseQuantity: Text;\n+ UnitCode: Text;\n+ PriceAmount: Decimal;\n+ LineExtensionAmt: Decimal;\n+ SalesInvoiceNo: Code[20];\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 630795] PEPPOL LineExtensionAmount equals PriceAmount times Quantity when Prices Including VAT is used\n+ Initialize();\n+\n+ // [GIVEN] Customer \"C\" with PEPPOL identifier\n+ LibrarySales.CreateCustomer(Customer);\n+ AddCustPEPPOLIdentifier(Customer.\"No.\");\n+\n+ // [GIVEN] Sales Invoice for \"C\" with \"Prices Including VAT\" = TRUE and Quantity = 7\n+ CreateItemWithPrice(Item, 139);\n+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader.\"Document Type\"::Invoice, Customer.\"No.\");\n+ SalesHeader.Validate(\"Prices Including VAT\", true);\n+ SalesHeader.Modify(true);\n+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item.\"No.\", 7);\n+\n+ // [WHEN] Post the Sales Invoice and retrieve PEPPOL line amounts\n+ SalesInvoiceNo := LibrarySales.PostSalesDocument(SalesHeader, true, true);\n+ SalesInvoiceHeader.Get(SalesInvoiceNo);\n+ SalesHeader.TransferFields(SalesInvoiceHeader);\n+ FindSalesInvoiceLine(SalesInvoiceLine, SalesInvoiceNo);\n+ SalesLine.TransferFields(SalesInvoiceLine);\n+\n+ PEPPOLLineInfoProvider := GetFormat();\n+ PEPPOLLineInfoProvider.GetLineGeneralInfo(\n+ SalesLine, SalesHeader, InvoiceLineID, InvoiceLineNote, InvoicedQuantity,\n+ InvoiceLineExtensionAmount, LineExtensionAmountCurrencyID, InvoiceLineAccountingCost);\n+ PEPPOLLineInfoProvider.GetLinePriceInfo(\n+ SalesLine, SalesHeader, InvoiceLinePriceAmount, InvLinePriceAmountCurrencyID,\n+ BaseQuantity, UnitCode);\n+\n+ // [THEN] LineExtensionAmount equals PriceAmount times Quantity per PEPPOL BIS 3.0\n+ Evaluate(PriceAmount, InvoiceLinePriceAmount, 9);\n+ Evaluate(LineExtensionAmt, InvoiceLineExtensionAmount, 9);\n+ Assert.AreEqual(PriceAmount * SalesInvoiceLine.Quantity, LineExtensionAmt,\n+ 'LineExtensionAmount must equal PriceAmount * Quantity per PEPPOL BIS 3.0');\n+ end;\n+\n var\n local procedure Initialize()\n var\n@@ -3993,6 +4055,8 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual(UnitOfMeasure.\"International Standard Code\", unitCode, '');\n Assert.AreEqual('UNECERec20', unitCodeListID, '');\n SalesInvoiceLineLineAmount := SalesInvoiceLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesInvoiceLineLineAmount := Round(SalesInvoiceLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n Assert.AreEqual(Format(SalesInvoiceLineLineAmount, 0, 9), InvoiceLineExtensionAmount, '');\n Assert.AreEqual(SalesHeader.\"Currency Code\", LineExtensionAmountCurrencyID, '');\n Assert.AreEqual('', InvoiceLineAccountingCost, '');\n"} {"metadata": {"area": "manufacturing", "image_count": 0}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "cbbf3d36fdf3aeeaefa5bd59e13023fbc9f33c9c", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "8e12d8a72ecc80f705ea82baaa570a3bf2b234f0", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "84eb1813a9322dd1fe6d7a60689e5bcc1ddebf97", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} From 1ee29c577a732eca9538065b54fb647a49837f7e Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Mon, 1 Jun 2026 10:20:55 +0200 Subject: [PATCH 06/14] add week 23 --- dataset/bcbench.jsonl | 7 +++-- .../microsoft__BCApps-8286/README.md | 31 +++++++++++++++++++ .../microsoft__BCApps-8287/README.md | 15 +++++++++ .../microsoft__BCApps-8293/README.md | 20 ++++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 dataset/problemstatement/microsoft__BCApps-8286/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8287/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8293/README.md diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index 9ae32329f..f81606c50 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -100,5 +100,8 @@ {"metadata": {"area": "inventory", "image_count": 7}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-176082", "base_commit": "cb30d50fe1ed2c716c6349370fdc31c6bd0ce956", "created_at": "2024-02-23", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137038, "functionName": ["GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\nindex e0b3ba5f0bf7..ffa98cfbb351 100644\n--- a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n@@ -48,6 +48,7 @@\n UndoneTransLineQtyErr: Label 'Expected Quantity to be 0 after Transfer Shipment was undone';\n DerivedTransLineErr: Label 'Expected no Derived Transfer Line i.e. line with \"Derived From Line No.\" equal to original transfer line.';\n IncorrectSNUndoneErr: Label 'The Serial No. of the item on the transfer shipment line that was undone was different from the SN on the corresponding transfer line.';\n+ ApplToItemEntryErr: Label '%1 must be %2 in %3.', Comment = '%1 is Appl-to Item Entry, %2 is Item Ledger Entry No. and %3 is Transfer Line';\n \n [Test]\n [HandlerFunctions('MessageHandler')]\n@@ -3655,6 +3656,99 @@\n ItemLedgerEntry.TestField(\"Cost Amount (Actual)\", NewCost);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('PostedPurchaseReceiptsModalPageHandler,PostedPurchRcptLinesModalPageHandler')]\n+ procedure GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines()\n+ var\n+ Item: Record Item;\n+ Vendor: Record Vendor;\n+ Location: Record Location;\n+ Location2: Record Location;\n+ Location3: Record Location;\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseHeader2: Record \"Purchase Header\";\n+ PurchaseHeader3: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ PurchaseLine2: Record \"Purchase Line\";\n+ PurchaseLine3: Record \"Purchase Line\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ TransferHeader: Record \"Transfer Header\";\n+ TransferLine: Record \"Transfer Line\";\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ ItemLedgerEntryNo: Integer;\n+ PurchaseReceiptNo: Code[20];\n+ TransferOrder: TestPage \"Transfer Order\";\n+ begin\n+ // [SCENARIO 500597] Get Receipt Lines action on Transfer Order shows list of Posted Purchase Receipts having Transfer-from Code in Location Code of Purch Rcpt Lines and after selecting it populates Appl-to Item Entry field in Transfer Lines.\n+ Initialize();\n+\n+ // [GIVEN] Create an Item and Validate Costing Method.\n+ LibraryInventory.CreateItem(Item);\n+ Item.Validate(\"Costing Method\", Item.\"Costing Method\"::FIFO);\n+ Item.Modify(true);\n+\n+ // [GIVEN] Create two Locations with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location2);\n+\n+ // [GIVEN] Create another Location with Inventory Posting Setup \n+ // And Validate Use As In-Transit.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location3);\n+ Location3.Validate(\"Use As In-Transit\", true);\n+ Location3.Modify(true);\n+\n+ // [GIVEN] Create a Vendor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+\n+ // [GIVEN] Create and Post Purchase Receipt with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader, PurchaseLine, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 2 with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader2, PurchaseLine2, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 3 with Location Code on Line.\n+ PurchaseReceiptNo := CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ PurchaseHeader3,\n+ PurchaseLine3,\n+ Vendor,\n+ Item,\n+ Location);\n+\n+ // [GIVEN] Find and save Item Ledger Entry No. in a Variable.\n+ ItemLedgerEntry.SetRange(\"Document No.\", PurchaseReceiptNo);\n+ ItemLedgerEntry.FindFirst();\n+ ItemLedgerEntryNo := ItemLedgerEntry.\"Entry No.\";\n+\n+ // [GIVEN] Find Purch. Rcpt Line.\n+ FindRandomReceiptLine(PurchaseReceiptNo, PurchRcptLine);\n+\n+ // [GIVEN] Create Transfer Header.\n+ LibraryInventory.CreateTransferHeader(TransferHeader, Location.Code, Location2.Code, Location3.Code);\n+\n+ // [GIVEN] Open Transfer Order page and run Get Receipt Line action.\n+ TransferOrder.OpenEdit();\n+ TransferOrder.GoToRecord(TransferHeader);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchRcptLine.\"No.\");\n+ TransferOrder.GetReceiptLines.Invoke();\n+\n+ // [WHEN] Find Transfer Line.\n+ TransferLine.SetRange(\"Document No.\", TransferHeader.\"No.\");\n+ TransferLine.FindFirst();\n+\n+ // [VERIFY] Appl-to Item Entry and Item Ledger Entry No. are same.\n+ Assert.AreEqual(\n+ ItemLedgerEntryNo,\n+ TransferLine.\"Appl.-to Item Entry\",\n+ StrSubstNo(\n+ ApplToItemEntryErr,\n+ TransferLine.FieldCaption(\"Appl.-to Item Entry\"),\n+ ItemLedgerEntryNo,\n+ TransferLine.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -5168,6 +5262,52 @@\n Assert.AreEqual(LineCount, TransferReceiptLine.Count(), '');\n end;\n \n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchHeader(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location)\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ PurchaseHeader.Validate(\"Location Code\", Location.Code);\n+ PurchaseHeader.Modify(true);\n+\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+ end;\n+\n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location): Code[20]\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Location Code\", Location.Code);\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ exit(LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false));\n+ end;\n+\n [MessageHandler]\n [Scope('OnPrem')]\n procedure MessageHandler(Message: Text[1024])\n@@ -5394,5 +5534,19 @@\n // 0 = Item.Type::Inventory\n Assert.AreEqual('0', ItemList.Filter.GetFilter(\"Type\"), 'Item List contains non-inventory items.');\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure PostedPurchRcptLinesModalPageHandler(var PostedPurchaseReceiptLines: Page \"Posted Purchase Receipt Lines\"; var Response: Action)\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ begin\n+ PurchRcptLine.SetRange(\"Document No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.SetRange(\"No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.FindFirst();\n+ PostedPurchaseReceiptLines.SetRecord(PurchRcptLine);\n+\n+ Response := ACTION::LookupOK;\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\nindex 5fe44b4568d1..c16ab8669925 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n@@ -1304,7 +1304,7 @@ table 5740 \"Transfer Header\"\n TempPurchRcptHeader: Record \"Purch. Rcpt. Header\" temporary;\n PostedPurchaseReceipts: Page \"Posted Purchase Receipts\";\n begin\n- PurchRcptHeader.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ FindPurchRcptHeader(PurchRcptHeader);\n PostedPurchaseReceipts.SetTableView(PurchRcptHeader);\n PostedPurchaseReceipts.LookupMode := true;\n if PostedPurchaseReceipts.RunModal() = ACTION::LookupOK then begin\n@@ -1376,6 +1376,8 @@ table 5740 \"Transfer Header\"\n PurchRcptLine.FilterPstdDocLnItemLedgEntries(ItemLedgerEntry);\n ItemTrackingDocMgt.CopyItemLedgerEntriesToTemp(TempItemLedgerEntry, ItemLedgerEntry);\n ItemTrackingMgt.CopyItemLedgEntryTrkgToTransferLine(TempItemLedgerEntry, TransferLine);\n+ TransferLine.\"Appl.-to Item Entry\" := ItemLedgerEntry.\"Entry No.\";\n+ TransferLine.Modify(true);\n \n OnAfterAddTransferLineFromReceiptLine(TransferLine, PurchRcptLine, TempItemLedgerEntry, Rec);\n end;\n@@ -1546,6 +1548,31 @@ table 5740 \"Transfer Header\"\n end;\n end;\n \n+ local procedure FindPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\")\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ DocumentNo: Code[20];\n+ begin\n+ PurchRcptLine.SetLoadFields(\"Document No.\", \"Location Code\");\n+ PurchRcptLine.SetCurrentKey(\"Document No.\");\n+ PurchRcptLine.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ if PurchRcptLine.FindSet() then\n+ repeat\n+ GetPurchRcptHeader(PurchRcptHeader, PurchRcptLine, DocumentNo);\n+ until PurchRcptLine.Next() = 0;\n+ PurchRcptHeader.MarkedOnly(true);\n+ end;\n+\n+ local procedure GetPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var DocumentNo: Code[20])\n+ begin\n+ if PurchRcptLine.\"Document No.\" = DocumentNo then\n+ exit;\n+\n+ PurchRcptHeader.Get(PurchRcptLine.\"Document No.\");\n+ PurchRcptHeader.Mark(true);\n+ DocumentNo := PurchRcptLine.\"Document No.\";\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnAddTransferLineFromReceiptLineOnBeforeTransferLineInsert(var TransferLine: Record \"Transfer Line\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var TransferHeader: Record \"Transfer Header\")\n begin\n"} {"metadata": {"area": "crm", "image_count": 8}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-174087", "base_commit": "74a0b7c175da3f9a272745bd34453a4712b73e7b", "created_at": "2024-02-02", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\Marketing"], "FAIL_TO_PASS": [{"codeunitID": 136208, "functionName": ["PopulateEvaluationFieldInInteractionLogEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\nindex 4c4c73700d2a..59fff6e2be93 100644\n--- a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n+++ b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n@@ -45,6 +45,7 @@ codeunit 136208 \"Marketing Interaction\"\n LoggedSegemntEntriesCreateMsg: Label 'Logged Segment entry was created';\n AttachmentFileShouldNotBeBlankErr: Label 'Attachment File should not be blank.';\n TxtFileExt: Label 'txt';\n+ EvaluationErr: Label '%1 must be %2 in %3', Comment = '%1 = Evaluation, %2 = Positive, %3 = Interaction Log Entry';\n \n [Test]\n [Scope('OnPrem')]\n@@ -2998,6 +2999,50 @@ codeunit 136208 \"Marketing Interaction\"\n VerifyAttachmentFileIsNotBlankOnInteractionLogEntry(Contact.\"No.\");\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('CreateInteractionFromContactPageHandler')]\n+ procedure PopulateEvaluationFieldInInteractionLogEntry()\n+ var\n+ Contact: Record Contact;\n+ InteractionTemplate: Record \"Interaction Template\";\n+ InteractionLogEntry: Record \"Interaction Log Entry\";\n+ ContactCard: TestPage \"Contact Card\";\n+ InteractionEvaluation: Enum \"Interaction Evaluation\";\n+ begin\n+ // [SCENARIO 498395] When stan creates an Interaction using Create Interaction action from Contact, Evaluation field should be populated in Interaction Log Entry.\n+ Initialize();\n+\n+ // [GIVEN] Create a Contact.\n+ LibraryMarketing.CreateCompanyContact(Contact);\n+\n+ // [GIVEN] Create an Interaction Template and Validate Information Flow.\n+ LibraryMarketing.CreateInteractionTemplate(InteractionTemplate);\n+ InteractionTemplate.Validate(\"Information Flow\", InteractionTemplate.\"Information Flow\"::Outbound);\n+ InteractionTemplate.Modify(true);\n+\n+ // [GIVEN] Open Contact Card and Create Interaction.\n+ ContactCard.OpenEdit();\n+ ContactCard.GoToRecord(Contact);\n+ LibraryVariableStorage.Enqueue(InteractionTemplate.Code);\n+ LibraryVariableStorage.Enqueue(Format(InteractionEvaluation::Positive));\n+ ContactCard.\"Create &Interaction\".Invoke();\n+\n+ // [WHEN] Find Interaction Log Entry.\n+ InteractionLogEntry.SetRange(\"Contact No.\", Contact.\"No.\");\n+ InteractionLogEntry.FindFirst();\n+\n+ // [VERIFY] Interaction Log Entry has Evaluation field populated as Positive.\n+ Assert.AreEqual(\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.Evaluation,\n+ StrSubstNo(\n+ EvaluationErr,\n+ InteractionLogEntry.FieldCaption(Evaluation),\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibrarySales: Codeunit \"Library - Sales\";\n@@ -4309,5 +4354,16 @@ CopyStr(StorageLocation, 1, MaxStrLen(MarketingSetup.\"Attachment Storage Locatio\n CreateInteraction.NextInteraction.Invoke();\n CreateInteraction.Finish.Invoke();\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure CreateInteractionFromContactPageHandler(var CreateInteraction: TestPage \"Create Interaction\")\n+ begin\n+ CreateInteraction.\"Interaction Template Code\".SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.Evaluation.SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.FinishInteraction.Invoke();\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\nindex ff43f4ff6a7b..05a21a6196bf 100644\n--- a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n+++ b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n@@ -694,6 +694,7 @@ page 5077 \"Create Interaction\"\n end;\n Step::\"Step 4\":\n begin\n+ InteractionLogEntry.CopyFromSegment(Rec);\n InteractionLogEntry.Modify();\n CurrPage.Close();\n end;\n"} {"metadata": {"area": "peppol", "image_count": 1}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8059", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-08T09:31:42Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\PEPPOL\\App", "src\\Apps\\W1\\PEPPOL\\Test"], "patch": "diff --git a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\nindex 30f5f792bd..c7981a46fa 100644\n--- a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n@@ -798,6 +798,8 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n InvoiceLineNote := DelChr(Format(SalesLine.Type), '<>');\n InvoicedQuantity := Format(SalesLine.Quantity, 0, 9);\n SalesLineLineAmount := SalesLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesLineLineAmount := Round(SalesLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n InvoiceLineExtensionAmount := Format(SalesLineLineAmount, 0, 9);\n LineExtensionAmountCurrencyID := GetSalesDocCurrencyCode(SalesHeader);\n InvoiceLineAccountingCost := '';\n@@ -869,7 +871,10 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n \n InvLnAllowanceChargeIndicator := 'false';\n InvLnAllowanceChargeReason := LineDisAmtTxt;\n- InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ InvLnAllowanceChargeAmount := Format(Round(SalesLine.\"Line Discount Amount\" / (1 + SalesLine.\"VAT %\" / 100), 0.01), 0, 9)\n+ else\n+ InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n InvLnAllowanceChargeAmtCurrID := GetSalesDocCurrencyCode(SalesHeader);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139235, "functionName": ["LineAmountsConsistentWhenPricesInclVATNoDiscount"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\nindex 36931d56ed..cd237011d5 100644\n--- a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n@@ -3349,6 +3349,68 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual('', CustTaxSchemeID, 'Tax Scheme ID should be empty for Tax Category O.');\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ procedure LineAmountsConsistentWhenPricesInclVATNoDiscount()\n+ var\n+ SalesHeader: Record \"Sales Header\";\n+ SalesLine: Record \"Sales Line\";\n+ Customer: Record Customer;\n+ Item: Record Item;\n+ SalesInvoiceHeader: Record \"Sales Invoice Header\";\n+ SalesInvoiceLine: Record \"Sales Invoice Line\";\n+ PEPPOLLineInfoProvider: Interface \"PEPPOL Line Info Provider\";\n+ InvoiceLineID: Text;\n+ InvoiceLineNote: Text;\n+ InvoicedQuantity: Text;\n+ InvoiceLineExtensionAmount: Text;\n+ LineExtensionAmountCurrencyID: Text;\n+ InvoiceLineAccountingCost: Text;\n+ InvoiceLinePriceAmount: Text;\n+ InvLinePriceAmountCurrencyID: Text;\n+ BaseQuantity: Text;\n+ UnitCode: Text;\n+ PriceAmount: Decimal;\n+ LineExtensionAmt: Decimal;\n+ SalesInvoiceNo: Code[20];\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 630795] PEPPOL LineExtensionAmount equals PriceAmount times Quantity when Prices Including VAT is used\n+ Initialize();\n+\n+ // [GIVEN] Customer \"C\" with PEPPOL identifier\n+ LibrarySales.CreateCustomer(Customer);\n+ AddCustPEPPOLIdentifier(Customer.\"No.\");\n+\n+ // [GIVEN] Sales Invoice for \"C\" with \"Prices Including VAT\" = TRUE and Quantity = 7\n+ CreateItemWithPrice(Item, 139);\n+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader.\"Document Type\"::Invoice, Customer.\"No.\");\n+ SalesHeader.Validate(\"Prices Including VAT\", true);\n+ SalesHeader.Modify(true);\n+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item.\"No.\", 7);\n+\n+ // [WHEN] Post the Sales Invoice and retrieve PEPPOL line amounts\n+ SalesInvoiceNo := LibrarySales.PostSalesDocument(SalesHeader, true, true);\n+ SalesInvoiceHeader.Get(SalesInvoiceNo);\n+ SalesHeader.TransferFields(SalesInvoiceHeader);\n+ FindSalesInvoiceLine(SalesInvoiceLine, SalesInvoiceNo);\n+ SalesLine.TransferFields(SalesInvoiceLine);\n+\n+ PEPPOLLineInfoProvider := GetFormat();\n+ PEPPOLLineInfoProvider.GetLineGeneralInfo(\n+ SalesLine, SalesHeader, InvoiceLineID, InvoiceLineNote, InvoicedQuantity,\n+ InvoiceLineExtensionAmount, LineExtensionAmountCurrencyID, InvoiceLineAccountingCost);\n+ PEPPOLLineInfoProvider.GetLinePriceInfo(\n+ SalesLine, SalesHeader, InvoiceLinePriceAmount, InvLinePriceAmountCurrencyID,\n+ BaseQuantity, UnitCode);\n+\n+ // [THEN] LineExtensionAmount equals PriceAmount times Quantity per PEPPOL BIS 3.0\n+ Evaluate(PriceAmount, InvoiceLinePriceAmount, 9);\n+ Evaluate(LineExtensionAmt, InvoiceLineExtensionAmount, 9);\n+ Assert.AreEqual(PriceAmount * SalesInvoiceLine.Quantity, LineExtensionAmt,\n+ 'LineExtensionAmount must equal PriceAmount * Quantity per PEPPOL BIS 3.0');\n+ end;\n+\n var\n local procedure Initialize()\n var\n@@ -3993,6 +4055,8 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual(UnitOfMeasure.\"International Standard Code\", unitCode, '');\n Assert.AreEqual('UNECERec20', unitCodeListID, '');\n SalesInvoiceLineLineAmount := SalesInvoiceLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesInvoiceLineLineAmount := Round(SalesInvoiceLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n Assert.AreEqual(Format(SalesInvoiceLineLineAmount, 0, 9), InvoiceLineExtensionAmount, '');\n Assert.AreEqual(SalesHeader.\"Currency Code\", LineExtensionAmountCurrencyID, '');\n Assert.AreEqual('', InvoiceLineAccountingCost, '');\n"} -{"metadata": {"area": "manufacturing", "image_count": 0}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "cbbf3d36fdf3aeeaefa5bd59e13023fbc9f33c9c", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "84eb1813a9322dd1fe6d7a60689e5bcc1ddebf97", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8293", "base_commit": "01e67dc5ff263b26101f7f2db6caa1b346f090a6", "created_at": "2026-05-25T21:31:15Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\nindex 8d5c75124c..056de67a1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n@@ -15,12 +15,13 @@ using System.Reflection;\n codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n {\n /// \n- /// Opens the Released Production Order page for the production order linked to the given variant record.\n+ /// Opens the appropriate Production Order page (Released or Finished) for the production order linked to the given variant record.\n /// \n /// A record variant of a purchase or transfer document line.\n procedure ShowProductionOrder(RecRelatedVariant: Variant)\n var\n ProductionOrder: Record \"Production Order\";\n+ FinishedProductionOrder: Page \"Finished Production Order\";\n ReleasedProductionOrder: Page \"Released Production Order\";\n OperationNo: Code[10];\n ProdOrderNo: Code[20];\n@@ -29,11 +30,26 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n begin\n if not SetProdOrderInformationByVariant(RecRelatedVariant, ProdOrderNo, ProdOrderLineNo, RoutingNo, OperationNo) then\n exit;\n- ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ProductionOrder.SetFilter(Status, '>=%1', ProductionOrder.Status::Released);\n ProductionOrder.SetRange(\"No.\", ProdOrderNo);\n- ReleasedProductionOrder.SetTableView(ProductionOrder);\n- ReleasedProductionOrder.Editable := false;\n- ReleasedProductionOrder.Run();\n+ if not ProductionOrder.FindFirst() then\n+ exit;\n+ case ProductionOrder.Status of\n+ ProductionOrder.Status::Released:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ReleasedProductionOrder.SetTableView(ProductionOrder);\n+ ReleasedProductionOrder.Editable := false;\n+ ReleasedProductionOrder.Run();\n+ end;\n+ ProductionOrder.Status::Finished:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Finished);\n+ FinishedProductionOrder.SetTableView(ProductionOrder);\n+ FinishedProductionOrder.Editable := false;\n+ FinishedProductionOrder.Run();\n+ end;\n+ end;\n end;\n \n /// \n@@ -77,9 +93,9 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n exit(ProdOrderRoutingLine.Count());\n end;\n \n-local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n+ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n begin\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -130,7 +146,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n begin\n ProdOrderRoutingLine.SetLoadFields(\"Routing Link Code\");\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -138,7 +154,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n if ProdOrderRoutingLine.FindFirst() then\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n \n- ProdOrderComponent.SetRange(Status, ProdOrderComponent.Status::Released);\n+ ProdOrderComponent.SetFilter(Status, '>=%1', ProdOrderComponent.Status::Released);\n ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", ProdOrderLineNo);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ProdOFactboxMgmtShowsDataAfterProdOrderFinished"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 68c7fff2af..c6c56da2b8 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1875,6 +1875,57 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n 'CalcNoOfProductionOrderComponents should return a positive count for an Item Ledger Entry from a subcontracting receipt.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmArchiveOrderHandler,HandlePurchaseOrderPage')]\n+ procedure ProdOFactboxMgmtShowsDataAfterProdOrderFinished()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ SubcWorkCenter: Record \"Work Center\";\n+ SubcProdOFactboxMgmt: Codeunit \"Subc. ProdO. Factbox Mgmt.\";\n+ begin\n+ // [SCENARIO 634953] Subcontracting factbox drilldowns should work after production order is finished.\n+ Initialize();\n+\n+ // [GIVEN] A released production order with a subcontracting routing operation and a subcontracting purchase order\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateItemWithSingleSubcontractingOperation(Item, SubcWorkCenter);\n+ SubcontractingMgmtLibrary.UpdateVendorWithSubcontractingLocationCode(SubcWorkCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", SubcWorkCenter.\"No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", SubcWorkCenter.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [GIVEN] The production order is changed to Finished status\n+ LibraryManufacturing.ChangeProdOrderStatus(ProductionOrder, \"Production Order Status\"::Finished, WorkDate(), true);\n+\n+ // Re-read purchase line (the order still exists because only receipt was posted)\n+ PurchaseLine.FindFirst();\n+\n+ // [WHEN] CalcNoOfProductionOrderRoutings / CalcNoOfProductionOrderComponents are called with the Purchase Line\n+ // [THEN] Both return a positive count even though the production order is now Finished\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderRoutings(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderRoutings should return a positive count after the production order is finished.');\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderComponents(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderComponents should return a positive count after the production order is finished.');\n+ end;\n+\n [Test]\n [HandlerFunctions('ConfirmHandler')]\n procedure RoutingFactboxMgmtFiltersPurchOrderQtyByRoutingReferenceNo()\n@@ -3430,6 +3481,7 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n \n SubSetupLibrary.InitSetupFields();\n LibraryERMCountryData.CreateVATData();\n+ LibraryERMCountryData.UpdateGeneralPostingSetup();\n SubSetupLibrary.InitialSetupForGenProdPostingGroup();\n \n IsInitialized := true;\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8287", "base_commit": "ad39c988e2565d1ea1a8cb538a5b9a6ec4107eb4", "created_at": "2026-05-22T17:02:35Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\nindex b8a5c1d869..c1b2942c55 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n@@ -22,6 +22,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n IsDefaultTextTok: Label '<>''''', Locked = true;\n InvalidDataTypeErr: Label 'The value \"%1\" is not allowed for %2, it is not a %3.', Comment = '%1=the value, %2=field name,%3=field type.';\n NotInAllowableValuesErr: Label 'The value \"%1\" is not allowed for %2, it must be in the range of \"%3\".', Comment = '%1=the value, %2=field name,%3=field type.';\n+ InvalidAllowableValuesFormatErr: Label 'The allowable values \"%1\" are not a valid filter expression for %2 of type %3.', Comment = '%1=the allowable values, %2=field name, %3=field type.';\n \n trigger OnRun()\n var\n@@ -324,6 +325,110 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n ValidateAllowableValuesOnText(TestNameForError, QltyTest.\"Default Value\", QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\", TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// The test whose allowable values expression should be validated.\n+ internal procedure ValidateAllowableValuesFormat(var QltyTest: Record \"Qlty. Test\")\n+ var\n+ TestNameForError: Text;\n+ begin\n+ if QltyTest.Description <> '' then\n+ TestNameForError := QltyTest.Description\n+ else\n+ TestNameForError := QltyTest.Code;\n+\n+ ValidateAllowableValuesFormat(TestNameForError, QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\");\n+ end;\n+\n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// Friendly identifier used in error messages.\n+ /// The allowable values filter expression to validate.\n+ /// The test value type that the filter expression must match.\n+ local procedure ValidateAllowableValuesFormat(NumberOrNameOfTestNameForError: Text; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\")\n+ var\n+ IsValid: Boolean;\n+ begin\n+ if AllowableValues = '' then\n+ exit;\n+\n+ if IsBlankOrEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ if IsAnythingExceptEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ // Allowable values may contain inline expressions like [Field] that are resolved at evaluation time.\n+ // Defer validation until resolution.\n+ if AllowableValues.Contains('[') then\n+ exit;\n+\n+ IsValid := true;\n+ case QltyTestValueType of\n+ QltyTestValueType::\"Value Type Decimal\":\n+ IsValid := TryApplyDecimalFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Integer\":\n+ IsValid := TryApplyIntegerFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Boolean\":\n+ IsValid := TryApplyBooleanFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Date\":\n+ IsValid := TryApplyDateFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type DateTime\":\n+ IsValid := TryApplyDateTimeFilter(AllowableValues);\n+ end;\n+\n+ if not IsValid then\n+ Error(InvalidAllowableValuesFormatErr, AllowableValues, NumberOrNameOfTestNameForError, QltyTestValueType);\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDecimalFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionLine: Record \"Qlty. Inspection Line\" temporary;\n+ begin\n+ TempQltyInspectionLine.SetFilter(\"Derived Numeric Value\", FilterExpression);\n+ if TempQltyInspectionLine.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyIntegerFilter(FilterExpression: Text)\n+ var\n+ TempInteger: Record \"Integer\" temporary;\n+ begin\n+ TempInteger.SetFilter(Number, FilterExpression);\n+ if TempInteger.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyBooleanFilter(FilterExpression: Text)\n+ var\n+ QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n+ begin\n+ // Valid boolean allowable values are: Yes, No, True, False, 1, 0, On, Off (and variations)\n+ if not QltyBooleanParsing.CanTextBeInterpretedAsBooleanIsh(FilterExpression) then\n+ Error(InvalidAllowableValuesFormatErr, FilterExpression, '', 'Boolean');\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateFilter(FilterExpression: Text)\n+ var\n+ TempDateLookupBuffer: Record \"Date Lookup Buffer\" temporary;\n+ begin\n+ TempDateLookupBuffer.SetFilter(\"Period Start\", FilterExpression);\n+ if TempDateLookupBuffer.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateTimeFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionHeader: Record \"Qlty. Inspection Header\" temporary;\n+ begin\n+ TempQltyInspectionHeader.SetFilter(\"Finished Date\", FilterExpression);\n+ if TempQltyInspectionHeader.IsEmpty() then;\n+ end;\n+\n local procedure ValidateAllowableValuesOnText(NumberOrNameOfTestNameForError: Text; var TextToValidate: Text[250]; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\"; var TempBufferQltyTestLookupValue: Record \"Qlty. Test Lookup Value\" temporary; QltyCaseSensitivity: Enum \"Qlty. Case Sensitivity\")\n var\n QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n@@ -393,9 +498,8 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n if not (IsBlankOrEmptyCondition(AllowableValues) and (TextToValidate = '')) then\n if not QltyResultEvaluation.CheckIfValueIsString(TextToValidate, ConvertStr(AllowableValues, ',', '|'), QltyCaseSensitivity) then\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n-\n QltyTestValueType::\"Value Type Option\",\n- QltyTestValueType::\"Value Type Table Lookup\":\n+ QltyTestValueType::\"Value Type Table Lookup\":\n begin\n TextToValidate := CopyStr(TextToValidate.Trim(), 1, MaxStrLen(TextToValidate));\n \n@@ -419,6 +523,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n end;\n end;\n+\n OnAfterValidateAllowableValuesOnText(NumberOrNameOfTestNameForError, TextToValidate, AllowableValues, QltyTestValueType, TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139963, "functionName": ["ValidateAllowableValuesFormat_Boolean_ValidFormats", "ValidateAllowableValuesFormat_NonValidatedTypes", "ValidateAllowableValuesFormat_Boolean_InvalidFormats", "ValidateAllowableValuesFormat_DateTime_InvalidFormats", "ValidateAllowableValuesFormat_Integer_ValidFormats", "ValidateAllowableValuesFormat_Integer_InvalidFormats", "ValidateAllowableValuesFormat_Date_InvalidFormats", "ValidateAllowableValuesFormat_Decimal_ValidFormats", "ValidateAllowableValuesFormat_Date_ValidFormats", "ValidateAllowableValuesFormat_DateTime_ValidFormats", "ValidateAllowableValuesFormat_Decimal_InvalidFormats"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\nindex 9f4cbf3006..66e4c203fc 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n@@ -54,8 +54,11 @@ table 20401 \"Qlty. Test\"\n {\n Caption = 'Allowable Values';\n ToolTip = 'Specifies an expression for the range of values you can enter or select for the Test. Depending on the Test Value Type, the expression format varies. For example if you want a measurement such as a percentage that collects between 0 and 100 you would enter 0..100. This is not the pass or acceptable condition, these are just the technically possible values that the inspector can enter. You would then enter a passing condition in your result conditions. If you had a result of Pass being 80 to 100, you would then configure 80..100 for that result.';\n+\n trigger OnValidate()\n begin\n+ Rec.ValidateAllowableValuesFormat();\n+\n if Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Option\", Rec.\"Test Value Type\"::\"Value Type Table Lookup\"] then\n Rec.\"Allowable Values\" := CopyStr(Rec.\"Allowable Values\".Replace(', ', ','), 1, MaxStrLen(Rec.\"Allowable Values\"));\n end;\n@@ -472,6 +475,16 @@ table 20401 \"Qlty. Test\"\n QltyResultEvaluation.ValidateAllowableValuesOnTest(Rec);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the test value type.\n+ /// \n+ procedure ValidateAllowableValuesFormat()\n+ var\n+ QltyResultEvaluation: Codeunit \"Qlty. Result Evaluation\";\n+ begin\n+ QltyResultEvaluation.ValidateAllowableValuesFormat(Rec);\n+ end;\n+\n /// \n /// Code = the unique code\n /// Description = raw description.\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\nindex 91159fca6e..05f7d8a17a 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n@@ -2071,6 +2071,440 @@ codeunit 139963 \"Qlty. Tests - Result Eval.\"\n LibraryAssert.ExpectedError(StrSubstNo(Expected4Err, OptionListQltyInspectionLine.\"Test Code\"));\n end;\n \n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_ValidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC';\n+ DecimalQltyTest.Description := 'Test Decimal';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ DecimalQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ DecimalQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25.5\"\n+ DecimalQltyTest.\"Allowable Values\" := '25.5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"10|20|30\"\n+ DecimalQltyTest.\"Allowable Values\" := '10|20|30';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DecimalQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to not empty condition \"<>''\"\n+ DecimalQltyTest.\"Allowable Values\" := '<>''''';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_InvalidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC2';\n+ DecimalQltyTest.Description := 'Test Decimal Invalid';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a number\"\n+ DecimalQltyTest.\"Allowable Values\" := 'not a number';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid operator \"==5\"\n+ DecimalQltyTest.\"Allowable Values\" := '==5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_ValidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT';\n+ IntegerQltyTest.Description := 'Test Integer';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ IntegerQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ IntegerQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ IntegerQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25\"\n+ IntegerQltyTest.\"Allowable Values\" := '25';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"1|2|3|4|5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1|2|3|4|5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ IntegerQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ IntegerQltyTest.\"Allowable Values\" := '1..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_InvalidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT2';\n+ IntegerQltyTest.Description := 'Test Integer Invalid';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to decimal value \"1.5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1.5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not an integer\"\n+ IntegerQltyTest.\"Allowable Values\" := 'not an integer';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_ValidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE';\n+ DateQltyTest.Description := 'Test Date';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact date \"2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to date range \"2024-01-01..2024-12-31\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01..2024-12-31';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than date \">2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '>2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateQltyTest.\"Allowable Values\" := '>[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_InvalidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE2';\n+ DateQltyTest.Description := 'Test Date Invalid';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid date \"99/99/9999\"\n+ DateQltyTest.\"Allowable Values\" := '99/99/9999';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a date\"\n+ DateQltyTest.\"Allowable Values\" := 'not a date';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_ValidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT';\n+ DateTimeQltyTest.Description := 'Test DateTime';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact datetime \"2024-01-01 10:30:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 10:30:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to datetime range \"2024-01-01 00:00:00..2024-12-31 23:59:59\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 00:00:00..2024-12-31 23:59:59';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than datetime \">2024-01-01 10:00:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '>2024-01-01 10:00:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateTimeQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateTimeQltyTest.\"Allowable Values\" := '<[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_InvalidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT2';\n+ DateTimeQltyTest.Description := 'Test DateTime Invalid';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid datetime \"99/99/9999 99:99:99\"\n+ DateTimeQltyTest.\"Allowable Values\" := '99/99/9999 99:99:99';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a datetime\"\n+ DateTimeQltyTest.\"Allowable Values\" := 'not a datetime';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_ValidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL';\n+ BooleanQltyTest.Description := 'Test Boolean';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to \"Yes\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Yes';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"No\"\n+ BooleanQltyTest.\"Allowable Values\" := 'No';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"True\"\n+ BooleanQltyTest.\"Allowable Values\" := 'True';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"False\"\n+ BooleanQltyTest.\"Allowable Values\" := 'False';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"1\"\n+ BooleanQltyTest.\"Allowable Values\" := '1';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"0\"\n+ BooleanQltyTest.\"Allowable Values\" := '0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"On\"\n+ BooleanQltyTest.\"Allowable Values\" := 'On';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"Off\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Off';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"Y\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Y';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"N\"\n+ BooleanQltyTest.\"Allowable Values\" := 'N';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ BooleanQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ BooleanQltyTest.\"Allowable Values\" := '[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_InvalidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL2';\n+ BooleanQltyTest.Description := 'Test Boolean Invalid';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"Maybe\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Maybe';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid number \"2\"\n+ BooleanQltyTest.\"Allowable Values\" := '2';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a boolean\"\n+ BooleanQltyTest.\"Allowable Values\" := 'not a boolean';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"abc\"\n+ BooleanQltyTest.\"Allowable Values\" := 'abc';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_NonValidatedTypes()\n+ var\n+ TextQltyTest: Record \"Qlty. Test\";\n+ OptionQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat does not validate non-numeric/non-date types\n+\n+ // [GIVEN] A quality test with text type is created\n+ TextQltyTest.Init();\n+ TextQltyTest.Code := 'TESTTEXT';\n+ TextQltyTest.Description := 'Test Text';\n+ TextQltyTest.\"Test Value Type\" := TextQltyTest.\"Test Value Type\"::\"Value Type Text\";\n+ TextQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to any text value \"A|B|C\"\n+ TextQltyTest.\"Allowable Values\" := 'A|B|C';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for text type)\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to any arbitrary text\n+ TextQltyTest.\"Allowable Values\" := 'any text value';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [GIVEN] A quality test with option type is created\n+ OptionQltyTest.Init();\n+ OptionQltyTest.Code := 'TESTOPT';\n+ OptionQltyTest.Description := 'Test Option';\n+ OptionQltyTest.\"Test Value Type\" := OptionQltyTest.\"Test Value Type\"::\"Value Type Option\";\n+ OptionQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to comma-separated options \"Option1,Option2,Option3\"\n+ OptionQltyTest.\"Allowable Values\" := 'Option1,Option2,Option3';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for option type)\n+ OptionQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+\n local procedure GetTemplateLineConfigFilters(var QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\"; var OutTemplateLineQltyIResultConditConf: Record \"Qlty. I. Result Condit. Conf.\")\n begin\n OutTemplateLineQltyIResultConditConf.SetRange(\"Condition Type\", OutTemplateLineQltyIResultConditConf.\"Condition Type\"::Template);\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8286", "base_commit": "9e4bca5d3428c17d51fbe6e903f0efe2bc9e410b", "created_at": "2026-05-22T13:07:41Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\nindex dfb07f0502..a005fa7b7c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n@@ -436,7 +436,7 @@ codeunit 99001508 \"Subc. Price Management\"\n \n GetPriceByUOM(SubcontractorPrice, PriceListQty, PriceListCost);\n if PriceListCost <> 0 then begin\n- ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityBase(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n+ ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityForUOM(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n ConvertPriceToCurrency(RequisitionLine.\"Currency Code\", SubcontractorPrice.\"Currency Code\", PriceListCost, DirectCost);\n end;\n RequisitionLine.\"Direct Unit Cost\" := DirectCost;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..73e138fe61 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -3401,6 +3401,77 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.AreEqual('', ToPurchaseHeader.\"Subc. Location Code\", 'Subc. Location Code should not be copied from archive by Copy Document');\n end;\n \n+ [Test]\n+ procedure WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion()\n+ var\n+ Item: Record Item;\n+ ItemUOM: Record \"Item Unit of Measure\";\n+ Vendor: Record Vendor;\n+ WorkCenter: Record \"Work Center\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ SubcPriceManagement: Codeunit \"Subc. Price Management\";\n+ QtyPerSet: Integer;\n+ PriceListUnitCost: Decimal;\n+ begin\n+ // [SCENARIO 636078] Calculate Subcontracts must compute Direct Unit Cost on the Subcontracting\n+ // Worksheet using the per-UoM conversion factor (GetQuantityForUOM()), not the total base\n+ // quantity (GetQuantityBase()) of the order.\n+\n+ // [GIVEN] Item with PCS base UoM and a SET alternative UoM (10 PCS per SET).\n+ Initialize();\n+ LibraryInventory.CreateItem(Item);\n+ QtyPerSet := 10;\n+ LibraryInventory.CreateItemUnitOfMeasureCode(ItemUOM, Item.\"No.\", QtyPerSet);\n+\n+ // [GIVEN] Vendor and Work Center with the vendor as its subcontractor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+ LibraryManufacturing.CreateWorkCenter(WorkCenter);\n+ WorkCenter.Validate(\"Subcontractor No.\", Vendor.\"No.\");\n+ WorkCenter.Modify(true);\n+\n+ // [GIVEN] A subcontractor price in PCS with Minimum Quantity 1 and Direct Unit Cost 1000.\n+ PriceListUnitCost := 1000;\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter.\"No.\", Vendor.\"No.\", Item.\"No.\", '', '', WorkDate(), Item.\"Base Unit of Measure\", 1, '');\n+ SubcontractorPrice.Validate(\"Direct Unit Cost\", PriceListUnitCost);\n+ SubcontractorPrice.Modify(true);\n+\n+ // [GIVEN] A staged Requisition Line for 3 SET (= 30 PCS in base UoM).\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := ItemUOM.Code;\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 3;\n+\n+ // [WHEN] The subcontractor price is applied to the requisition line.\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost = price-list cost * Qty-per-UoM (1000 * 10 = 10000),\n+ // not price-list cost * total base quantity (1000 * 30 = 30000 — the pre-fix behavior).\n+ Assert.AreEqual(\n+ PriceListUnitCost * QtyPerSet, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost on the Subcontracting Worksheet must be derived from Qty. per Unit of Measure, not from total base quantity.');\n+\n+ // [WHEN] The same price is applied to a Requisition Line using the base UoM (no conversion needed).\n+ Clear(RequisitionLine);\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := Item.\"Base Unit of Measure\";\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 30;\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost equals the price-list cost (the same-UoM path is unchanged by the fix).\n+ Assert.AreEqual(\n+ PriceListUnitCost, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost must equal the price-list cost when the worksheet UoM matches the price-list UoM.');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. Subcontracting Test\");\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "cbbf3d36fdf3aeeaefa5bd59e13023fbc9f33c9c", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "1b05b19c9b6ecee6e567858fc839d2342c6a0526", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} diff --git a/dataset/problemstatement/microsoft__BCApps-8286/README.md b/dataset/problemstatement/microsoft__BCApps-8286/README.md new file mode 100644 index 000000000..3ce37bb85 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8286/README.md @@ -0,0 +1,31 @@ +# (Bug 636078): [Subcontracting] Worksheet pricing passes total base qty instead of qty-per-UoM to ConvertPriceToUOM — wrong Direct Unit Cost + +## Summary + +Fixes the Subcontracting Worksheet **Direct Unit Cost** when the production order UoM differs from the subcontractor price-list UoM. + +`Subc. Price Management.GetSubcPriceForReqLine` passed `RequisitionLine.GetQuantityBase()` (total base quantity of the order) as the per-UoM conversion factor to `ConvertPriceToUOM`. Because `ConvertPriceToUOM` computes `DirectCost := PriceListCost / PriceListQtyPerUOM * ProdQtyPerUoM`, the result was multiplied by the order quantity instead of the UoM conversion factor. The Carry-Out Action Message-created Purchase Order then inherited the inflated cost. + +Comparison of the three call sites (only the worksheet path was wrong): + +| Path | 2nd param | Correct? | +|------|-----------|----------| +| Routing (`SetRoutingPriceListCost`) | `ProdQtyPerUom` | Yes | +| **Worksheet (`GetSubcPriceForReqLine`)** | **`RequisitionLine.GetQuantityBase()`** | **No (fixed here)** | +| Purchase Order (`GetSubcPriceForPurchLine`) | `PurchaseLine.GetQuantityPerUOM()` | Yes | + +### Fix + +Pass `RequisitionLine.GetQuantityForUOM()` instead, matching the routing and purchase paths. + +### Test + +Added `WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion` in `SubcSubcontractingTest`: + +- Item with PCS base UoM + SET alternative UoM (10 PCS per SET), vendor and work center with that vendor as subcontractor, subcontractor price of 1000 / PCS. +- Stages a Requisition Line for 3 SET (= 30 PCS base) and asserts `Direct Unit Cost = 10000` (price * Qty-per-UoM), not 30000 (pre-fix behavior). +- Also asserts the same-UoM (PCS) path still returns 1000 - guards against regression. + +### Work Item + +[AB#636078](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/636078) diff --git a/dataset/problemstatement/microsoft__BCApps-8287/README.md b/dataset/problemstatement/microsoft__BCApps-8287/README.md new file mode 100644 index 000000000..0ca474a55 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8287/README.md @@ -0,0 +1,15 @@ +# [Quality Management] Add missing validation of "Allowable Values" in Quality Test card + +## What & why + +image + + +## Linked work + +Fixes [AB#624240](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/624240) + + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-8293/README.md b/dataset/problemstatement/microsoft__BCApps-8293/README.md new file mode 100644 index 000000000..250f3cb6e --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8293/README.md @@ -0,0 +1,20 @@ +# Bug 634953: Fix factbox drilldowns for finished production orders + +## Summary +- **Bug**: Subcontracting factbox drilldowns in Purchase Order and Transfer Order break after the linked production order is finished. +- **Root cause**: \Subc. ProdO. Factbox Mgmt.\ (CU 99001559) hardcodes \SetRange(Status, ::Released)\ in all 5 procedures, so no data is returned once status moves to Finished. +- **Fix**: Replace \SetRange(Status, ::Released)\ with \SetFilter(Status, '>=%1', ::Released)\ across all filter procedures so that both Released and Finished production orders are found. \ShowProductionOrder\ now opens the correct page (\Released Production Order\ or \Finished Production Order\) based on the resolved status. + +## Changes +- \SubcProdOFactboxMgmt.Codeunit.al\ — Fixed all 5 affected procedures +- \SubcSubcontractingTest.Codeunit.al\ — Added \ProdOFactboxMgmtShowsDataAfterProdOrderFinished\ test ([SCENARIO 634953]) + +## Test +Added \ProdOFactboxMgmtShowsDataAfterProdOrderFinished\ in codeunit 139989 — verifies that \CalcNoOfProductionOrderRoutings\ and \CalcNoOfProductionOrderComponents\ return positive counts after the production order is finished. + +Fixes [AB#634953](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634953) + +:robot: Generated with GitHub Copilot + + + From 2559ed77d8f2a2244215585a78919b2ab46697b7 Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Mon, 1 Jun 2026 10:33:58 +0200 Subject: [PATCH 07/14] change version to 28.1 --- dataset/bcbench.jsonl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index f81606c50..d697305fa 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -100,8 +100,8 @@ {"metadata": {"area": "inventory", "image_count": 7}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-176082", "base_commit": "cb30d50fe1ed2c716c6349370fdc31c6bd0ce956", "created_at": "2024-02-23", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137038, "functionName": ["GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\nindex e0b3ba5f0bf7..ffa98cfbb351 100644\n--- a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n@@ -48,6 +48,7 @@\n UndoneTransLineQtyErr: Label 'Expected Quantity to be 0 after Transfer Shipment was undone';\n DerivedTransLineErr: Label 'Expected no Derived Transfer Line i.e. line with \"Derived From Line No.\" equal to original transfer line.';\n IncorrectSNUndoneErr: Label 'The Serial No. of the item on the transfer shipment line that was undone was different from the SN on the corresponding transfer line.';\n+ ApplToItemEntryErr: Label '%1 must be %2 in %3.', Comment = '%1 is Appl-to Item Entry, %2 is Item Ledger Entry No. and %3 is Transfer Line';\n \n [Test]\n [HandlerFunctions('MessageHandler')]\n@@ -3655,6 +3656,99 @@\n ItemLedgerEntry.TestField(\"Cost Amount (Actual)\", NewCost);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('PostedPurchaseReceiptsModalPageHandler,PostedPurchRcptLinesModalPageHandler')]\n+ procedure GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines()\n+ var\n+ Item: Record Item;\n+ Vendor: Record Vendor;\n+ Location: Record Location;\n+ Location2: Record Location;\n+ Location3: Record Location;\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseHeader2: Record \"Purchase Header\";\n+ PurchaseHeader3: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ PurchaseLine2: Record \"Purchase Line\";\n+ PurchaseLine3: Record \"Purchase Line\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ TransferHeader: Record \"Transfer Header\";\n+ TransferLine: Record \"Transfer Line\";\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ ItemLedgerEntryNo: Integer;\n+ PurchaseReceiptNo: Code[20];\n+ TransferOrder: TestPage \"Transfer Order\";\n+ begin\n+ // [SCENARIO 500597] Get Receipt Lines action on Transfer Order shows list of Posted Purchase Receipts having Transfer-from Code in Location Code of Purch Rcpt Lines and after selecting it populates Appl-to Item Entry field in Transfer Lines.\n+ Initialize();\n+\n+ // [GIVEN] Create an Item and Validate Costing Method.\n+ LibraryInventory.CreateItem(Item);\n+ Item.Validate(\"Costing Method\", Item.\"Costing Method\"::FIFO);\n+ Item.Modify(true);\n+\n+ // [GIVEN] Create two Locations with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location2);\n+\n+ // [GIVEN] Create another Location with Inventory Posting Setup \n+ // And Validate Use As In-Transit.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location3);\n+ Location3.Validate(\"Use As In-Transit\", true);\n+ Location3.Modify(true);\n+\n+ // [GIVEN] Create a Vendor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+\n+ // [GIVEN] Create and Post Purchase Receipt with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader, PurchaseLine, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 2 with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader2, PurchaseLine2, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 3 with Location Code on Line.\n+ PurchaseReceiptNo := CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ PurchaseHeader3,\n+ PurchaseLine3,\n+ Vendor,\n+ Item,\n+ Location);\n+\n+ // [GIVEN] Find and save Item Ledger Entry No. in a Variable.\n+ ItemLedgerEntry.SetRange(\"Document No.\", PurchaseReceiptNo);\n+ ItemLedgerEntry.FindFirst();\n+ ItemLedgerEntryNo := ItemLedgerEntry.\"Entry No.\";\n+\n+ // [GIVEN] Find Purch. Rcpt Line.\n+ FindRandomReceiptLine(PurchaseReceiptNo, PurchRcptLine);\n+\n+ // [GIVEN] Create Transfer Header.\n+ LibraryInventory.CreateTransferHeader(TransferHeader, Location.Code, Location2.Code, Location3.Code);\n+\n+ // [GIVEN] Open Transfer Order page and run Get Receipt Line action.\n+ TransferOrder.OpenEdit();\n+ TransferOrder.GoToRecord(TransferHeader);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchRcptLine.\"No.\");\n+ TransferOrder.GetReceiptLines.Invoke();\n+\n+ // [WHEN] Find Transfer Line.\n+ TransferLine.SetRange(\"Document No.\", TransferHeader.\"No.\");\n+ TransferLine.FindFirst();\n+\n+ // [VERIFY] Appl-to Item Entry and Item Ledger Entry No. are same.\n+ Assert.AreEqual(\n+ ItemLedgerEntryNo,\n+ TransferLine.\"Appl.-to Item Entry\",\n+ StrSubstNo(\n+ ApplToItemEntryErr,\n+ TransferLine.FieldCaption(\"Appl.-to Item Entry\"),\n+ ItemLedgerEntryNo,\n+ TransferLine.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -5168,6 +5262,52 @@\n Assert.AreEqual(LineCount, TransferReceiptLine.Count(), '');\n end;\n \n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchHeader(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location)\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ PurchaseHeader.Validate(\"Location Code\", Location.Code);\n+ PurchaseHeader.Modify(true);\n+\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+ end;\n+\n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location): Code[20]\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Location Code\", Location.Code);\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ exit(LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false));\n+ end;\n+\n [MessageHandler]\n [Scope('OnPrem')]\n procedure MessageHandler(Message: Text[1024])\n@@ -5394,5 +5534,19 @@\n // 0 = Item.Type::Inventory\n Assert.AreEqual('0', ItemList.Filter.GetFilter(\"Type\"), 'Item List contains non-inventory items.');\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure PostedPurchRcptLinesModalPageHandler(var PostedPurchaseReceiptLines: Page \"Posted Purchase Receipt Lines\"; var Response: Action)\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ begin\n+ PurchRcptLine.SetRange(\"Document No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.SetRange(\"No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.FindFirst();\n+ PostedPurchaseReceiptLines.SetRecord(PurchRcptLine);\n+\n+ Response := ACTION::LookupOK;\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\nindex 5fe44b4568d1..c16ab8669925 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n@@ -1304,7 +1304,7 @@ table 5740 \"Transfer Header\"\n TempPurchRcptHeader: Record \"Purch. Rcpt. Header\" temporary;\n PostedPurchaseReceipts: Page \"Posted Purchase Receipts\";\n begin\n- PurchRcptHeader.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ FindPurchRcptHeader(PurchRcptHeader);\n PostedPurchaseReceipts.SetTableView(PurchRcptHeader);\n PostedPurchaseReceipts.LookupMode := true;\n if PostedPurchaseReceipts.RunModal() = ACTION::LookupOK then begin\n@@ -1376,6 +1376,8 @@ table 5740 \"Transfer Header\"\n PurchRcptLine.FilterPstdDocLnItemLedgEntries(ItemLedgerEntry);\n ItemTrackingDocMgt.CopyItemLedgerEntriesToTemp(TempItemLedgerEntry, ItemLedgerEntry);\n ItemTrackingMgt.CopyItemLedgEntryTrkgToTransferLine(TempItemLedgerEntry, TransferLine);\n+ TransferLine.\"Appl.-to Item Entry\" := ItemLedgerEntry.\"Entry No.\";\n+ TransferLine.Modify(true);\n \n OnAfterAddTransferLineFromReceiptLine(TransferLine, PurchRcptLine, TempItemLedgerEntry, Rec);\n end;\n@@ -1546,6 +1548,31 @@ table 5740 \"Transfer Header\"\n end;\n end;\n \n+ local procedure FindPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\")\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ DocumentNo: Code[20];\n+ begin\n+ PurchRcptLine.SetLoadFields(\"Document No.\", \"Location Code\");\n+ PurchRcptLine.SetCurrentKey(\"Document No.\");\n+ PurchRcptLine.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ if PurchRcptLine.FindSet() then\n+ repeat\n+ GetPurchRcptHeader(PurchRcptHeader, PurchRcptLine, DocumentNo);\n+ until PurchRcptLine.Next() = 0;\n+ PurchRcptHeader.MarkedOnly(true);\n+ end;\n+\n+ local procedure GetPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var DocumentNo: Code[20])\n+ begin\n+ if PurchRcptLine.\"Document No.\" = DocumentNo then\n+ exit;\n+\n+ PurchRcptHeader.Get(PurchRcptLine.\"Document No.\");\n+ PurchRcptHeader.Mark(true);\n+ DocumentNo := PurchRcptLine.\"Document No.\";\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnAddTransferLineFromReceiptLineOnBeforeTransferLineInsert(var TransferLine: Record \"Transfer Line\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var TransferHeader: Record \"Transfer Header\")\n begin\n"} {"metadata": {"area": "crm", "image_count": 8}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-174087", "base_commit": "74a0b7c175da3f9a272745bd34453a4712b73e7b", "created_at": "2024-02-02", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\Marketing"], "FAIL_TO_PASS": [{"codeunitID": 136208, "functionName": ["PopulateEvaluationFieldInInteractionLogEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\nindex 4c4c73700d2a..59fff6e2be93 100644\n--- a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n+++ b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n@@ -45,6 +45,7 @@ codeunit 136208 \"Marketing Interaction\"\n LoggedSegemntEntriesCreateMsg: Label 'Logged Segment entry was created';\n AttachmentFileShouldNotBeBlankErr: Label 'Attachment File should not be blank.';\n TxtFileExt: Label 'txt';\n+ EvaluationErr: Label '%1 must be %2 in %3', Comment = '%1 = Evaluation, %2 = Positive, %3 = Interaction Log Entry';\n \n [Test]\n [Scope('OnPrem')]\n@@ -2998,6 +2999,50 @@ codeunit 136208 \"Marketing Interaction\"\n VerifyAttachmentFileIsNotBlankOnInteractionLogEntry(Contact.\"No.\");\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('CreateInteractionFromContactPageHandler')]\n+ procedure PopulateEvaluationFieldInInteractionLogEntry()\n+ var\n+ Contact: Record Contact;\n+ InteractionTemplate: Record \"Interaction Template\";\n+ InteractionLogEntry: Record \"Interaction Log Entry\";\n+ ContactCard: TestPage \"Contact Card\";\n+ InteractionEvaluation: Enum \"Interaction Evaluation\";\n+ begin\n+ // [SCENARIO 498395] When stan creates an Interaction using Create Interaction action from Contact, Evaluation field should be populated in Interaction Log Entry.\n+ Initialize();\n+\n+ // [GIVEN] Create a Contact.\n+ LibraryMarketing.CreateCompanyContact(Contact);\n+\n+ // [GIVEN] Create an Interaction Template and Validate Information Flow.\n+ LibraryMarketing.CreateInteractionTemplate(InteractionTemplate);\n+ InteractionTemplate.Validate(\"Information Flow\", InteractionTemplate.\"Information Flow\"::Outbound);\n+ InteractionTemplate.Modify(true);\n+\n+ // [GIVEN] Open Contact Card and Create Interaction.\n+ ContactCard.OpenEdit();\n+ ContactCard.GoToRecord(Contact);\n+ LibraryVariableStorage.Enqueue(InteractionTemplate.Code);\n+ LibraryVariableStorage.Enqueue(Format(InteractionEvaluation::Positive));\n+ ContactCard.\"Create &Interaction\".Invoke();\n+\n+ // [WHEN] Find Interaction Log Entry.\n+ InteractionLogEntry.SetRange(\"Contact No.\", Contact.\"No.\");\n+ InteractionLogEntry.FindFirst();\n+\n+ // [VERIFY] Interaction Log Entry has Evaluation field populated as Positive.\n+ Assert.AreEqual(\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.Evaluation,\n+ StrSubstNo(\n+ EvaluationErr,\n+ InteractionLogEntry.FieldCaption(Evaluation),\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibrarySales: Codeunit \"Library - Sales\";\n@@ -4309,5 +4354,16 @@ CopyStr(StorageLocation, 1, MaxStrLen(MarketingSetup.\"Attachment Storage Locatio\n CreateInteraction.NextInteraction.Invoke();\n CreateInteraction.Finish.Invoke();\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure CreateInteractionFromContactPageHandler(var CreateInteraction: TestPage \"Create Interaction\")\n+ begin\n+ CreateInteraction.\"Interaction Template Code\".SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.Evaluation.SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.FinishInteraction.Invoke();\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\nindex ff43f4ff6a7b..05a21a6196bf 100644\n--- a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n+++ b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n@@ -694,6 +694,7 @@ page 5077 \"Create Interaction\"\n end;\n Step::\"Step 4\":\n begin\n+ InteractionLogEntry.CopyFromSegment(Rec);\n InteractionLogEntry.Modify();\n CurrPage.Close();\n end;\n"} {"metadata": {"area": "peppol", "image_count": 1}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8059", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-08T09:31:42Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\PEPPOL\\App", "src\\Apps\\W1\\PEPPOL\\Test"], "patch": "diff --git a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\nindex 30f5f792bd..c7981a46fa 100644\n--- a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n@@ -798,6 +798,8 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n InvoiceLineNote := DelChr(Format(SalesLine.Type), '<>');\n InvoicedQuantity := Format(SalesLine.Quantity, 0, 9);\n SalesLineLineAmount := SalesLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesLineLineAmount := Round(SalesLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n InvoiceLineExtensionAmount := Format(SalesLineLineAmount, 0, 9);\n LineExtensionAmountCurrencyID := GetSalesDocCurrencyCode(SalesHeader);\n InvoiceLineAccountingCost := '';\n@@ -869,7 +871,10 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n \n InvLnAllowanceChargeIndicator := 'false';\n InvLnAllowanceChargeReason := LineDisAmtTxt;\n- InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ InvLnAllowanceChargeAmount := Format(Round(SalesLine.\"Line Discount Amount\" / (1 + SalesLine.\"VAT %\" / 100), 0.01), 0, 9)\n+ else\n+ InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n InvLnAllowanceChargeAmtCurrID := GetSalesDocCurrencyCode(SalesHeader);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139235, "functionName": ["LineAmountsConsistentWhenPricesInclVATNoDiscount"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\nindex 36931d56ed..cd237011d5 100644\n--- a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n@@ -3349,6 +3349,68 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual('', CustTaxSchemeID, 'Tax Scheme ID should be empty for Tax Category O.');\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ procedure LineAmountsConsistentWhenPricesInclVATNoDiscount()\n+ var\n+ SalesHeader: Record \"Sales Header\";\n+ SalesLine: Record \"Sales Line\";\n+ Customer: Record Customer;\n+ Item: Record Item;\n+ SalesInvoiceHeader: Record \"Sales Invoice Header\";\n+ SalesInvoiceLine: Record \"Sales Invoice Line\";\n+ PEPPOLLineInfoProvider: Interface \"PEPPOL Line Info Provider\";\n+ InvoiceLineID: Text;\n+ InvoiceLineNote: Text;\n+ InvoicedQuantity: Text;\n+ InvoiceLineExtensionAmount: Text;\n+ LineExtensionAmountCurrencyID: Text;\n+ InvoiceLineAccountingCost: Text;\n+ InvoiceLinePriceAmount: Text;\n+ InvLinePriceAmountCurrencyID: Text;\n+ BaseQuantity: Text;\n+ UnitCode: Text;\n+ PriceAmount: Decimal;\n+ LineExtensionAmt: Decimal;\n+ SalesInvoiceNo: Code[20];\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 630795] PEPPOL LineExtensionAmount equals PriceAmount times Quantity when Prices Including VAT is used\n+ Initialize();\n+\n+ // [GIVEN] Customer \"C\" with PEPPOL identifier\n+ LibrarySales.CreateCustomer(Customer);\n+ AddCustPEPPOLIdentifier(Customer.\"No.\");\n+\n+ // [GIVEN] Sales Invoice for \"C\" with \"Prices Including VAT\" = TRUE and Quantity = 7\n+ CreateItemWithPrice(Item, 139);\n+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader.\"Document Type\"::Invoice, Customer.\"No.\");\n+ SalesHeader.Validate(\"Prices Including VAT\", true);\n+ SalesHeader.Modify(true);\n+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item.\"No.\", 7);\n+\n+ // [WHEN] Post the Sales Invoice and retrieve PEPPOL line amounts\n+ SalesInvoiceNo := LibrarySales.PostSalesDocument(SalesHeader, true, true);\n+ SalesInvoiceHeader.Get(SalesInvoiceNo);\n+ SalesHeader.TransferFields(SalesInvoiceHeader);\n+ FindSalesInvoiceLine(SalesInvoiceLine, SalesInvoiceNo);\n+ SalesLine.TransferFields(SalesInvoiceLine);\n+\n+ PEPPOLLineInfoProvider := GetFormat();\n+ PEPPOLLineInfoProvider.GetLineGeneralInfo(\n+ SalesLine, SalesHeader, InvoiceLineID, InvoiceLineNote, InvoicedQuantity,\n+ InvoiceLineExtensionAmount, LineExtensionAmountCurrencyID, InvoiceLineAccountingCost);\n+ PEPPOLLineInfoProvider.GetLinePriceInfo(\n+ SalesLine, SalesHeader, InvoiceLinePriceAmount, InvLinePriceAmountCurrencyID,\n+ BaseQuantity, UnitCode);\n+\n+ // [THEN] LineExtensionAmount equals PriceAmount times Quantity per PEPPOL BIS 3.0\n+ Evaluate(PriceAmount, InvoiceLinePriceAmount, 9);\n+ Evaluate(LineExtensionAmt, InvoiceLineExtensionAmount, 9);\n+ Assert.AreEqual(PriceAmount * SalesInvoiceLine.Quantity, LineExtensionAmt,\n+ 'LineExtensionAmount must equal PriceAmount * Quantity per PEPPOL BIS 3.0');\n+ end;\n+\n var\n local procedure Initialize()\n var\n@@ -3993,6 +4055,8 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual(UnitOfMeasure.\"International Standard Code\", unitCode, '');\n Assert.AreEqual('UNECERec20', unitCodeListID, '');\n SalesInvoiceLineLineAmount := SalesInvoiceLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesInvoiceLineLineAmount := Round(SalesInvoiceLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n Assert.AreEqual(Format(SalesInvoiceLineLineAmount, 0, 9), InvoiceLineExtensionAmount, '');\n Assert.AreEqual(SalesHeader.\"Currency Code\", LineExtensionAmountCurrencyID, '');\n Assert.AreEqual('', InvoiceLineAccountingCost, '');\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8293", "base_commit": "01e67dc5ff263b26101f7f2db6caa1b346f090a6", "created_at": "2026-05-25T21:31:15Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\nindex 8d5c75124c..056de67a1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n@@ -15,12 +15,13 @@ using System.Reflection;\n codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n {\n /// \n- /// Opens the Released Production Order page for the production order linked to the given variant record.\n+ /// Opens the appropriate Production Order page (Released or Finished) for the production order linked to the given variant record.\n /// \n /// A record variant of a purchase or transfer document line.\n procedure ShowProductionOrder(RecRelatedVariant: Variant)\n var\n ProductionOrder: Record \"Production Order\";\n+ FinishedProductionOrder: Page \"Finished Production Order\";\n ReleasedProductionOrder: Page \"Released Production Order\";\n OperationNo: Code[10];\n ProdOrderNo: Code[20];\n@@ -29,11 +30,26 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n begin\n if not SetProdOrderInformationByVariant(RecRelatedVariant, ProdOrderNo, ProdOrderLineNo, RoutingNo, OperationNo) then\n exit;\n- ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ProductionOrder.SetFilter(Status, '>=%1', ProductionOrder.Status::Released);\n ProductionOrder.SetRange(\"No.\", ProdOrderNo);\n- ReleasedProductionOrder.SetTableView(ProductionOrder);\n- ReleasedProductionOrder.Editable := false;\n- ReleasedProductionOrder.Run();\n+ if not ProductionOrder.FindFirst() then\n+ exit;\n+ case ProductionOrder.Status of\n+ ProductionOrder.Status::Released:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ReleasedProductionOrder.SetTableView(ProductionOrder);\n+ ReleasedProductionOrder.Editable := false;\n+ ReleasedProductionOrder.Run();\n+ end;\n+ ProductionOrder.Status::Finished:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Finished);\n+ FinishedProductionOrder.SetTableView(ProductionOrder);\n+ FinishedProductionOrder.Editable := false;\n+ FinishedProductionOrder.Run();\n+ end;\n+ end;\n end;\n \n /// \n@@ -77,9 +93,9 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n exit(ProdOrderRoutingLine.Count());\n end;\n \n-local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n+ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n begin\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -130,7 +146,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n begin\n ProdOrderRoutingLine.SetLoadFields(\"Routing Link Code\");\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -138,7 +154,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n if ProdOrderRoutingLine.FindFirst() then\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n \n- ProdOrderComponent.SetRange(Status, ProdOrderComponent.Status::Released);\n+ ProdOrderComponent.SetFilter(Status, '>=%1', ProdOrderComponent.Status::Released);\n ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", ProdOrderLineNo);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ProdOFactboxMgmtShowsDataAfterProdOrderFinished"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 68c7fff2af..c6c56da2b8 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1875,6 +1875,57 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n 'CalcNoOfProductionOrderComponents should return a positive count for an Item Ledger Entry from a subcontracting receipt.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmArchiveOrderHandler,HandlePurchaseOrderPage')]\n+ procedure ProdOFactboxMgmtShowsDataAfterProdOrderFinished()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ SubcWorkCenter: Record \"Work Center\";\n+ SubcProdOFactboxMgmt: Codeunit \"Subc. ProdO. Factbox Mgmt.\";\n+ begin\n+ // [SCENARIO 634953] Subcontracting factbox drilldowns should work after production order is finished.\n+ Initialize();\n+\n+ // [GIVEN] A released production order with a subcontracting routing operation and a subcontracting purchase order\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateItemWithSingleSubcontractingOperation(Item, SubcWorkCenter);\n+ SubcontractingMgmtLibrary.UpdateVendorWithSubcontractingLocationCode(SubcWorkCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", SubcWorkCenter.\"No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", SubcWorkCenter.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [GIVEN] The production order is changed to Finished status\n+ LibraryManufacturing.ChangeProdOrderStatus(ProductionOrder, \"Production Order Status\"::Finished, WorkDate(), true);\n+\n+ // Re-read purchase line (the order still exists because only receipt was posted)\n+ PurchaseLine.FindFirst();\n+\n+ // [WHEN] CalcNoOfProductionOrderRoutings / CalcNoOfProductionOrderComponents are called with the Purchase Line\n+ // [THEN] Both return a positive count even though the production order is now Finished\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderRoutings(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderRoutings should return a positive count after the production order is finished.');\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderComponents(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderComponents should return a positive count after the production order is finished.');\n+ end;\n+\n [Test]\n [HandlerFunctions('ConfirmHandler')]\n procedure RoutingFactboxMgmtFiltersPurchOrderQtyByRoutingReferenceNo()\n@@ -3430,6 +3481,7 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n \n SubSetupLibrary.InitSetupFields();\n LibraryERMCountryData.CreateVATData();\n+ LibraryERMCountryData.UpdateGeneralPostingSetup();\n SubSetupLibrary.InitialSetupForGenProdPostingGroup();\n \n IsInitialized := true;\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8287", "base_commit": "ad39c988e2565d1ea1a8cb538a5b9a6ec4107eb4", "created_at": "2026-05-22T17:02:35Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\nindex b8a5c1d869..c1b2942c55 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n@@ -22,6 +22,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n IsDefaultTextTok: Label '<>''''', Locked = true;\n InvalidDataTypeErr: Label 'The value \"%1\" is not allowed for %2, it is not a %3.', Comment = '%1=the value, %2=field name,%3=field type.';\n NotInAllowableValuesErr: Label 'The value \"%1\" is not allowed for %2, it must be in the range of \"%3\".', Comment = '%1=the value, %2=field name,%3=field type.';\n+ InvalidAllowableValuesFormatErr: Label 'The allowable values \"%1\" are not a valid filter expression for %2 of type %3.', Comment = '%1=the allowable values, %2=field name, %3=field type.';\n \n trigger OnRun()\n var\n@@ -324,6 +325,110 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n ValidateAllowableValuesOnText(TestNameForError, QltyTest.\"Default Value\", QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\", TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// The test whose allowable values expression should be validated.\n+ internal procedure ValidateAllowableValuesFormat(var QltyTest: Record \"Qlty. Test\")\n+ var\n+ TestNameForError: Text;\n+ begin\n+ if QltyTest.Description <> '' then\n+ TestNameForError := QltyTest.Description\n+ else\n+ TestNameForError := QltyTest.Code;\n+\n+ ValidateAllowableValuesFormat(TestNameForError, QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\");\n+ end;\n+\n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// Friendly identifier used in error messages.\n+ /// The allowable values filter expression to validate.\n+ /// The test value type that the filter expression must match.\n+ local procedure ValidateAllowableValuesFormat(NumberOrNameOfTestNameForError: Text; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\")\n+ var\n+ IsValid: Boolean;\n+ begin\n+ if AllowableValues = '' then\n+ exit;\n+\n+ if IsBlankOrEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ if IsAnythingExceptEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ // Allowable values may contain inline expressions like [Field] that are resolved at evaluation time.\n+ // Defer validation until resolution.\n+ if AllowableValues.Contains('[') then\n+ exit;\n+\n+ IsValid := true;\n+ case QltyTestValueType of\n+ QltyTestValueType::\"Value Type Decimal\":\n+ IsValid := TryApplyDecimalFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Integer\":\n+ IsValid := TryApplyIntegerFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Boolean\":\n+ IsValid := TryApplyBooleanFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Date\":\n+ IsValid := TryApplyDateFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type DateTime\":\n+ IsValid := TryApplyDateTimeFilter(AllowableValues);\n+ end;\n+\n+ if not IsValid then\n+ Error(InvalidAllowableValuesFormatErr, AllowableValues, NumberOrNameOfTestNameForError, QltyTestValueType);\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDecimalFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionLine: Record \"Qlty. Inspection Line\" temporary;\n+ begin\n+ TempQltyInspectionLine.SetFilter(\"Derived Numeric Value\", FilterExpression);\n+ if TempQltyInspectionLine.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyIntegerFilter(FilterExpression: Text)\n+ var\n+ TempInteger: Record \"Integer\" temporary;\n+ begin\n+ TempInteger.SetFilter(Number, FilterExpression);\n+ if TempInteger.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyBooleanFilter(FilterExpression: Text)\n+ var\n+ QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n+ begin\n+ // Valid boolean allowable values are: Yes, No, True, False, 1, 0, On, Off (and variations)\n+ if not QltyBooleanParsing.CanTextBeInterpretedAsBooleanIsh(FilterExpression) then\n+ Error(InvalidAllowableValuesFormatErr, FilterExpression, '', 'Boolean');\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateFilter(FilterExpression: Text)\n+ var\n+ TempDateLookupBuffer: Record \"Date Lookup Buffer\" temporary;\n+ begin\n+ TempDateLookupBuffer.SetFilter(\"Period Start\", FilterExpression);\n+ if TempDateLookupBuffer.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateTimeFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionHeader: Record \"Qlty. Inspection Header\" temporary;\n+ begin\n+ TempQltyInspectionHeader.SetFilter(\"Finished Date\", FilterExpression);\n+ if TempQltyInspectionHeader.IsEmpty() then;\n+ end;\n+\n local procedure ValidateAllowableValuesOnText(NumberOrNameOfTestNameForError: Text; var TextToValidate: Text[250]; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\"; var TempBufferQltyTestLookupValue: Record \"Qlty. Test Lookup Value\" temporary; QltyCaseSensitivity: Enum \"Qlty. Case Sensitivity\")\n var\n QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n@@ -393,9 +498,8 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n if not (IsBlankOrEmptyCondition(AllowableValues) and (TextToValidate = '')) then\n if not QltyResultEvaluation.CheckIfValueIsString(TextToValidate, ConvertStr(AllowableValues, ',', '|'), QltyCaseSensitivity) then\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n-\n QltyTestValueType::\"Value Type Option\",\n- QltyTestValueType::\"Value Type Table Lookup\":\n+ QltyTestValueType::\"Value Type Table Lookup\":\n begin\n TextToValidate := CopyStr(TextToValidate.Trim(), 1, MaxStrLen(TextToValidate));\n \n@@ -419,6 +523,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n end;\n end;\n+\n OnAfterValidateAllowableValuesOnText(NumberOrNameOfTestNameForError, TextToValidate, AllowableValues, QltyTestValueType, TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139963, "functionName": ["ValidateAllowableValuesFormat_Boolean_ValidFormats", "ValidateAllowableValuesFormat_NonValidatedTypes", "ValidateAllowableValuesFormat_Boolean_InvalidFormats", "ValidateAllowableValuesFormat_DateTime_InvalidFormats", "ValidateAllowableValuesFormat_Integer_ValidFormats", "ValidateAllowableValuesFormat_Integer_InvalidFormats", "ValidateAllowableValuesFormat_Date_InvalidFormats", "ValidateAllowableValuesFormat_Decimal_ValidFormats", "ValidateAllowableValuesFormat_Date_ValidFormats", "ValidateAllowableValuesFormat_DateTime_ValidFormats", "ValidateAllowableValuesFormat_Decimal_InvalidFormats"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\nindex 9f4cbf3006..66e4c203fc 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n@@ -54,8 +54,11 @@ table 20401 \"Qlty. Test\"\n {\n Caption = 'Allowable Values';\n ToolTip = 'Specifies an expression for the range of values you can enter or select for the Test. Depending on the Test Value Type, the expression format varies. For example if you want a measurement such as a percentage that collects between 0 and 100 you would enter 0..100. This is not the pass or acceptable condition, these are just the technically possible values that the inspector can enter. You would then enter a passing condition in your result conditions. If you had a result of Pass being 80 to 100, you would then configure 80..100 for that result.';\n+\n trigger OnValidate()\n begin\n+ Rec.ValidateAllowableValuesFormat();\n+\n if Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Option\", Rec.\"Test Value Type\"::\"Value Type Table Lookup\"] then\n Rec.\"Allowable Values\" := CopyStr(Rec.\"Allowable Values\".Replace(', ', ','), 1, MaxStrLen(Rec.\"Allowable Values\"));\n end;\n@@ -472,6 +475,16 @@ table 20401 \"Qlty. Test\"\n QltyResultEvaluation.ValidateAllowableValuesOnTest(Rec);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the test value type.\n+ /// \n+ procedure ValidateAllowableValuesFormat()\n+ var\n+ QltyResultEvaluation: Codeunit \"Qlty. Result Evaluation\";\n+ begin\n+ QltyResultEvaluation.ValidateAllowableValuesFormat(Rec);\n+ end;\n+\n /// \n /// Code = the unique code\n /// Description = raw description.\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\nindex 91159fca6e..05f7d8a17a 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n@@ -2071,6 +2071,440 @@ codeunit 139963 \"Qlty. Tests - Result Eval.\"\n LibraryAssert.ExpectedError(StrSubstNo(Expected4Err, OptionListQltyInspectionLine.\"Test Code\"));\n end;\n \n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_ValidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC';\n+ DecimalQltyTest.Description := 'Test Decimal';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ DecimalQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ DecimalQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25.5\"\n+ DecimalQltyTest.\"Allowable Values\" := '25.5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"10|20|30\"\n+ DecimalQltyTest.\"Allowable Values\" := '10|20|30';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DecimalQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to not empty condition \"<>''\"\n+ DecimalQltyTest.\"Allowable Values\" := '<>''''';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_InvalidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC2';\n+ DecimalQltyTest.Description := 'Test Decimal Invalid';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a number\"\n+ DecimalQltyTest.\"Allowable Values\" := 'not a number';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid operator \"==5\"\n+ DecimalQltyTest.\"Allowable Values\" := '==5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_ValidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT';\n+ IntegerQltyTest.Description := 'Test Integer';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ IntegerQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ IntegerQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ IntegerQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25\"\n+ IntegerQltyTest.\"Allowable Values\" := '25';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"1|2|3|4|5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1|2|3|4|5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ IntegerQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ IntegerQltyTest.\"Allowable Values\" := '1..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_InvalidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT2';\n+ IntegerQltyTest.Description := 'Test Integer Invalid';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to decimal value \"1.5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1.5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not an integer\"\n+ IntegerQltyTest.\"Allowable Values\" := 'not an integer';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_ValidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE';\n+ DateQltyTest.Description := 'Test Date';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact date \"2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to date range \"2024-01-01..2024-12-31\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01..2024-12-31';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than date \">2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '>2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateQltyTest.\"Allowable Values\" := '>[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_InvalidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE2';\n+ DateQltyTest.Description := 'Test Date Invalid';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid date \"99/99/9999\"\n+ DateQltyTest.\"Allowable Values\" := '99/99/9999';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a date\"\n+ DateQltyTest.\"Allowable Values\" := 'not a date';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_ValidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT';\n+ DateTimeQltyTest.Description := 'Test DateTime';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact datetime \"2024-01-01 10:30:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 10:30:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to datetime range \"2024-01-01 00:00:00..2024-12-31 23:59:59\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 00:00:00..2024-12-31 23:59:59';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than datetime \">2024-01-01 10:00:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '>2024-01-01 10:00:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateTimeQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateTimeQltyTest.\"Allowable Values\" := '<[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_InvalidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT2';\n+ DateTimeQltyTest.Description := 'Test DateTime Invalid';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid datetime \"99/99/9999 99:99:99\"\n+ DateTimeQltyTest.\"Allowable Values\" := '99/99/9999 99:99:99';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a datetime\"\n+ DateTimeQltyTest.\"Allowable Values\" := 'not a datetime';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_ValidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL';\n+ BooleanQltyTest.Description := 'Test Boolean';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to \"Yes\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Yes';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"No\"\n+ BooleanQltyTest.\"Allowable Values\" := 'No';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"True\"\n+ BooleanQltyTest.\"Allowable Values\" := 'True';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"False\"\n+ BooleanQltyTest.\"Allowable Values\" := 'False';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"1\"\n+ BooleanQltyTest.\"Allowable Values\" := '1';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"0\"\n+ BooleanQltyTest.\"Allowable Values\" := '0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"On\"\n+ BooleanQltyTest.\"Allowable Values\" := 'On';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"Off\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Off';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"Y\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Y';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"N\"\n+ BooleanQltyTest.\"Allowable Values\" := 'N';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ BooleanQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ BooleanQltyTest.\"Allowable Values\" := '[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_InvalidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL2';\n+ BooleanQltyTest.Description := 'Test Boolean Invalid';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"Maybe\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Maybe';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid number \"2\"\n+ BooleanQltyTest.\"Allowable Values\" := '2';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a boolean\"\n+ BooleanQltyTest.\"Allowable Values\" := 'not a boolean';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"abc\"\n+ BooleanQltyTest.\"Allowable Values\" := 'abc';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_NonValidatedTypes()\n+ var\n+ TextQltyTest: Record \"Qlty. Test\";\n+ OptionQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat does not validate non-numeric/non-date types\n+\n+ // [GIVEN] A quality test with text type is created\n+ TextQltyTest.Init();\n+ TextQltyTest.Code := 'TESTTEXT';\n+ TextQltyTest.Description := 'Test Text';\n+ TextQltyTest.\"Test Value Type\" := TextQltyTest.\"Test Value Type\"::\"Value Type Text\";\n+ TextQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to any text value \"A|B|C\"\n+ TextQltyTest.\"Allowable Values\" := 'A|B|C';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for text type)\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to any arbitrary text\n+ TextQltyTest.\"Allowable Values\" := 'any text value';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [GIVEN] A quality test with option type is created\n+ OptionQltyTest.Init();\n+ OptionQltyTest.Code := 'TESTOPT';\n+ OptionQltyTest.Description := 'Test Option';\n+ OptionQltyTest.\"Test Value Type\" := OptionQltyTest.\"Test Value Type\"::\"Value Type Option\";\n+ OptionQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to comma-separated options \"Option1,Option2,Option3\"\n+ OptionQltyTest.\"Allowable Values\" := 'Option1,Option2,Option3';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for option type)\n+ OptionQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+\n local procedure GetTemplateLineConfigFilters(var QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\"; var OutTemplateLineQltyIResultConditConf: Record \"Qlty. I. Result Condit. Conf.\")\n begin\n OutTemplateLineQltyIResultConditConf.SetRange(\"Condition Type\", OutTemplateLineQltyIResultConditConf.\"Condition Type\"::Template);\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8286", "base_commit": "9e4bca5d3428c17d51fbe6e903f0efe2bc9e410b", "created_at": "2026-05-22T13:07:41Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\nindex dfb07f0502..a005fa7b7c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n@@ -436,7 +436,7 @@ codeunit 99001508 \"Subc. Price Management\"\n \n GetPriceByUOM(SubcontractorPrice, PriceListQty, PriceListCost);\n if PriceListCost <> 0 then begin\n- ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityBase(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n+ ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityForUOM(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n ConvertPriceToCurrency(RequisitionLine.\"Currency Code\", SubcontractorPrice.\"Currency Code\", PriceListCost, DirectCost);\n end;\n RequisitionLine.\"Direct Unit Cost\" := DirectCost;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..73e138fe61 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -3401,6 +3401,77 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.AreEqual('', ToPurchaseHeader.\"Subc. Location Code\", 'Subc. Location Code should not be copied from archive by Copy Document');\n end;\n \n+ [Test]\n+ procedure WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion()\n+ var\n+ Item: Record Item;\n+ ItemUOM: Record \"Item Unit of Measure\";\n+ Vendor: Record Vendor;\n+ WorkCenter: Record \"Work Center\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ SubcPriceManagement: Codeunit \"Subc. Price Management\";\n+ QtyPerSet: Integer;\n+ PriceListUnitCost: Decimal;\n+ begin\n+ // [SCENARIO 636078] Calculate Subcontracts must compute Direct Unit Cost on the Subcontracting\n+ // Worksheet using the per-UoM conversion factor (GetQuantityForUOM()), not the total base\n+ // quantity (GetQuantityBase()) of the order.\n+\n+ // [GIVEN] Item with PCS base UoM and a SET alternative UoM (10 PCS per SET).\n+ Initialize();\n+ LibraryInventory.CreateItem(Item);\n+ QtyPerSet := 10;\n+ LibraryInventory.CreateItemUnitOfMeasureCode(ItemUOM, Item.\"No.\", QtyPerSet);\n+\n+ // [GIVEN] Vendor and Work Center with the vendor as its subcontractor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+ LibraryManufacturing.CreateWorkCenter(WorkCenter);\n+ WorkCenter.Validate(\"Subcontractor No.\", Vendor.\"No.\");\n+ WorkCenter.Modify(true);\n+\n+ // [GIVEN] A subcontractor price in PCS with Minimum Quantity 1 and Direct Unit Cost 1000.\n+ PriceListUnitCost := 1000;\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter.\"No.\", Vendor.\"No.\", Item.\"No.\", '', '', WorkDate(), Item.\"Base Unit of Measure\", 1, '');\n+ SubcontractorPrice.Validate(\"Direct Unit Cost\", PriceListUnitCost);\n+ SubcontractorPrice.Modify(true);\n+\n+ // [GIVEN] A staged Requisition Line for 3 SET (= 30 PCS in base UoM).\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := ItemUOM.Code;\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 3;\n+\n+ // [WHEN] The subcontractor price is applied to the requisition line.\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost = price-list cost * Qty-per-UoM (1000 * 10 = 10000),\n+ // not price-list cost * total base quantity (1000 * 30 = 30000 — the pre-fix behavior).\n+ Assert.AreEqual(\n+ PriceListUnitCost * QtyPerSet, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost on the Subcontracting Worksheet must be derived from Qty. per Unit of Measure, not from total base quantity.');\n+\n+ // [WHEN] The same price is applied to a Requisition Line using the base UoM (no conversion needed).\n+ Clear(RequisitionLine);\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := Item.\"Base Unit of Measure\";\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 30;\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost equals the price-list cost (the same-UoM path is unchanged by the fix).\n+ Assert.AreEqual(\n+ PriceListUnitCost, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost must equal the price-list cost when the worksheet UoM matches the price-list UoM.');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. Subcontracting Test\");\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8293", "base_commit": "01e67dc5ff263b26101f7f2db6caa1b346f090a6", "created_at": "2026-05-25T21:31:15Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\nindex 8d5c75124c..056de67a1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n@@ -15,12 +15,13 @@ using System.Reflection;\n codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n {\n /// \n- /// Opens the Released Production Order page for the production order linked to the given variant record.\n+ /// Opens the appropriate Production Order page (Released or Finished) for the production order linked to the given variant record.\n /// \n /// A record variant of a purchase or transfer document line.\n procedure ShowProductionOrder(RecRelatedVariant: Variant)\n var\n ProductionOrder: Record \"Production Order\";\n+ FinishedProductionOrder: Page \"Finished Production Order\";\n ReleasedProductionOrder: Page \"Released Production Order\";\n OperationNo: Code[10];\n ProdOrderNo: Code[20];\n@@ -29,11 +30,26 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n begin\n if not SetProdOrderInformationByVariant(RecRelatedVariant, ProdOrderNo, ProdOrderLineNo, RoutingNo, OperationNo) then\n exit;\n- ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ProductionOrder.SetFilter(Status, '>=%1', ProductionOrder.Status::Released);\n ProductionOrder.SetRange(\"No.\", ProdOrderNo);\n- ReleasedProductionOrder.SetTableView(ProductionOrder);\n- ReleasedProductionOrder.Editable := false;\n- ReleasedProductionOrder.Run();\n+ if not ProductionOrder.FindFirst() then\n+ exit;\n+ case ProductionOrder.Status of\n+ ProductionOrder.Status::Released:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ReleasedProductionOrder.SetTableView(ProductionOrder);\n+ ReleasedProductionOrder.Editable := false;\n+ ReleasedProductionOrder.Run();\n+ end;\n+ ProductionOrder.Status::Finished:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Finished);\n+ FinishedProductionOrder.SetTableView(ProductionOrder);\n+ FinishedProductionOrder.Editable := false;\n+ FinishedProductionOrder.Run();\n+ end;\n+ end;\n end;\n \n /// \n@@ -77,9 +93,9 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n exit(ProdOrderRoutingLine.Count());\n end;\n \n-local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n+ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n begin\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -130,7 +146,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n begin\n ProdOrderRoutingLine.SetLoadFields(\"Routing Link Code\");\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -138,7 +154,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n if ProdOrderRoutingLine.FindFirst() then\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n \n- ProdOrderComponent.SetRange(Status, ProdOrderComponent.Status::Released);\n+ ProdOrderComponent.SetFilter(Status, '>=%1', ProdOrderComponent.Status::Released);\n ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", ProdOrderLineNo);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ProdOFactboxMgmtShowsDataAfterProdOrderFinished"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 68c7fff2af..c6c56da2b8 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1875,6 +1875,57 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n 'CalcNoOfProductionOrderComponents should return a positive count for an Item Ledger Entry from a subcontracting receipt.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmArchiveOrderHandler,HandlePurchaseOrderPage')]\n+ procedure ProdOFactboxMgmtShowsDataAfterProdOrderFinished()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ SubcWorkCenter: Record \"Work Center\";\n+ SubcProdOFactboxMgmt: Codeunit \"Subc. ProdO. Factbox Mgmt.\";\n+ begin\n+ // [SCENARIO 634953] Subcontracting factbox drilldowns should work after production order is finished.\n+ Initialize();\n+\n+ // [GIVEN] A released production order with a subcontracting routing operation and a subcontracting purchase order\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateItemWithSingleSubcontractingOperation(Item, SubcWorkCenter);\n+ SubcontractingMgmtLibrary.UpdateVendorWithSubcontractingLocationCode(SubcWorkCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", SubcWorkCenter.\"No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", SubcWorkCenter.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [GIVEN] The production order is changed to Finished status\n+ LibraryManufacturing.ChangeProdOrderStatus(ProductionOrder, \"Production Order Status\"::Finished, WorkDate(), true);\n+\n+ // Re-read purchase line (the order still exists because only receipt was posted)\n+ PurchaseLine.FindFirst();\n+\n+ // [WHEN] CalcNoOfProductionOrderRoutings / CalcNoOfProductionOrderComponents are called with the Purchase Line\n+ // [THEN] Both return a positive count even though the production order is now Finished\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderRoutings(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderRoutings should return a positive count after the production order is finished.');\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderComponents(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderComponents should return a positive count after the production order is finished.');\n+ end;\n+\n [Test]\n [HandlerFunctions('ConfirmHandler')]\n procedure RoutingFactboxMgmtFiltersPurchOrderQtyByRoutingReferenceNo()\n@@ -3430,6 +3481,7 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n \n SubSetupLibrary.InitSetupFields();\n LibraryERMCountryData.CreateVATData();\n+ LibraryERMCountryData.UpdateGeneralPostingSetup();\n SubSetupLibrary.InitialSetupForGenProdPostingGroup();\n \n IsInitialized := true;\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8287", "base_commit": "ad39c988e2565d1ea1a8cb538a5b9a6ec4107eb4", "created_at": "2026-05-22T17:02:35Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\nindex b8a5c1d869..c1b2942c55 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n@@ -22,6 +22,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n IsDefaultTextTok: Label '<>''''', Locked = true;\n InvalidDataTypeErr: Label 'The value \"%1\" is not allowed for %2, it is not a %3.', Comment = '%1=the value, %2=field name,%3=field type.';\n NotInAllowableValuesErr: Label 'The value \"%1\" is not allowed for %2, it must be in the range of \"%3\".', Comment = '%1=the value, %2=field name,%3=field type.';\n+ InvalidAllowableValuesFormatErr: Label 'The allowable values \"%1\" are not a valid filter expression for %2 of type %3.', Comment = '%1=the allowable values, %2=field name, %3=field type.';\n \n trigger OnRun()\n var\n@@ -324,6 +325,110 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n ValidateAllowableValuesOnText(TestNameForError, QltyTest.\"Default Value\", QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\", TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// The test whose allowable values expression should be validated.\n+ internal procedure ValidateAllowableValuesFormat(var QltyTest: Record \"Qlty. Test\")\n+ var\n+ TestNameForError: Text;\n+ begin\n+ if QltyTest.Description <> '' then\n+ TestNameForError := QltyTest.Description\n+ else\n+ TestNameForError := QltyTest.Code;\n+\n+ ValidateAllowableValuesFormat(TestNameForError, QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\");\n+ end;\n+\n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// Friendly identifier used in error messages.\n+ /// The allowable values filter expression to validate.\n+ /// The test value type that the filter expression must match.\n+ local procedure ValidateAllowableValuesFormat(NumberOrNameOfTestNameForError: Text; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\")\n+ var\n+ IsValid: Boolean;\n+ begin\n+ if AllowableValues = '' then\n+ exit;\n+\n+ if IsBlankOrEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ if IsAnythingExceptEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ // Allowable values may contain inline expressions like [Field] that are resolved at evaluation time.\n+ // Defer validation until resolution.\n+ if AllowableValues.Contains('[') then\n+ exit;\n+\n+ IsValid := true;\n+ case QltyTestValueType of\n+ QltyTestValueType::\"Value Type Decimal\":\n+ IsValid := TryApplyDecimalFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Integer\":\n+ IsValid := TryApplyIntegerFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Boolean\":\n+ IsValid := TryApplyBooleanFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Date\":\n+ IsValid := TryApplyDateFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type DateTime\":\n+ IsValid := TryApplyDateTimeFilter(AllowableValues);\n+ end;\n+\n+ if not IsValid then\n+ Error(InvalidAllowableValuesFormatErr, AllowableValues, NumberOrNameOfTestNameForError, QltyTestValueType);\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDecimalFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionLine: Record \"Qlty. Inspection Line\" temporary;\n+ begin\n+ TempQltyInspectionLine.SetFilter(\"Derived Numeric Value\", FilterExpression);\n+ if TempQltyInspectionLine.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyIntegerFilter(FilterExpression: Text)\n+ var\n+ TempInteger: Record \"Integer\" temporary;\n+ begin\n+ TempInteger.SetFilter(Number, FilterExpression);\n+ if TempInteger.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyBooleanFilter(FilterExpression: Text)\n+ var\n+ QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n+ begin\n+ // Valid boolean allowable values are: Yes, No, True, False, 1, 0, On, Off (and variations)\n+ if not QltyBooleanParsing.CanTextBeInterpretedAsBooleanIsh(FilterExpression) then\n+ Error(InvalidAllowableValuesFormatErr, FilterExpression, '', 'Boolean');\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateFilter(FilterExpression: Text)\n+ var\n+ TempDateLookupBuffer: Record \"Date Lookup Buffer\" temporary;\n+ begin\n+ TempDateLookupBuffer.SetFilter(\"Period Start\", FilterExpression);\n+ if TempDateLookupBuffer.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateTimeFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionHeader: Record \"Qlty. Inspection Header\" temporary;\n+ begin\n+ TempQltyInspectionHeader.SetFilter(\"Finished Date\", FilterExpression);\n+ if TempQltyInspectionHeader.IsEmpty() then;\n+ end;\n+\n local procedure ValidateAllowableValuesOnText(NumberOrNameOfTestNameForError: Text; var TextToValidate: Text[250]; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\"; var TempBufferQltyTestLookupValue: Record \"Qlty. Test Lookup Value\" temporary; QltyCaseSensitivity: Enum \"Qlty. Case Sensitivity\")\n var\n QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n@@ -393,9 +498,8 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n if not (IsBlankOrEmptyCondition(AllowableValues) and (TextToValidate = '')) then\n if not QltyResultEvaluation.CheckIfValueIsString(TextToValidate, ConvertStr(AllowableValues, ',', '|'), QltyCaseSensitivity) then\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n-\n QltyTestValueType::\"Value Type Option\",\n- QltyTestValueType::\"Value Type Table Lookup\":\n+ QltyTestValueType::\"Value Type Table Lookup\":\n begin\n TextToValidate := CopyStr(TextToValidate.Trim(), 1, MaxStrLen(TextToValidate));\n \n@@ -419,6 +523,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n end;\n end;\n+\n OnAfterValidateAllowableValuesOnText(NumberOrNameOfTestNameForError, TextToValidate, AllowableValues, QltyTestValueType, TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139963, "functionName": ["ValidateAllowableValuesFormat_Boolean_ValidFormats", "ValidateAllowableValuesFormat_NonValidatedTypes", "ValidateAllowableValuesFormat_Boolean_InvalidFormats", "ValidateAllowableValuesFormat_DateTime_InvalidFormats", "ValidateAllowableValuesFormat_Integer_ValidFormats", "ValidateAllowableValuesFormat_Integer_InvalidFormats", "ValidateAllowableValuesFormat_Date_InvalidFormats", "ValidateAllowableValuesFormat_Decimal_ValidFormats", "ValidateAllowableValuesFormat_Date_ValidFormats", "ValidateAllowableValuesFormat_DateTime_ValidFormats", "ValidateAllowableValuesFormat_Decimal_InvalidFormats"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\nindex 9f4cbf3006..66e4c203fc 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n@@ -54,8 +54,11 @@ table 20401 \"Qlty. Test\"\n {\n Caption = 'Allowable Values';\n ToolTip = 'Specifies an expression for the range of values you can enter or select for the Test. Depending on the Test Value Type, the expression format varies. For example if you want a measurement such as a percentage that collects between 0 and 100 you would enter 0..100. This is not the pass or acceptable condition, these are just the technically possible values that the inspector can enter. You would then enter a passing condition in your result conditions. If you had a result of Pass being 80 to 100, you would then configure 80..100 for that result.';\n+\n trigger OnValidate()\n begin\n+ Rec.ValidateAllowableValuesFormat();\n+\n if Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Option\", Rec.\"Test Value Type\"::\"Value Type Table Lookup\"] then\n Rec.\"Allowable Values\" := CopyStr(Rec.\"Allowable Values\".Replace(', ', ','), 1, MaxStrLen(Rec.\"Allowable Values\"));\n end;\n@@ -472,6 +475,16 @@ table 20401 \"Qlty. Test\"\n QltyResultEvaluation.ValidateAllowableValuesOnTest(Rec);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the test value type.\n+ /// \n+ procedure ValidateAllowableValuesFormat()\n+ var\n+ QltyResultEvaluation: Codeunit \"Qlty. Result Evaluation\";\n+ begin\n+ QltyResultEvaluation.ValidateAllowableValuesFormat(Rec);\n+ end;\n+\n /// \n /// Code = the unique code\n /// Description = raw description.\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\nindex 91159fca6e..05f7d8a17a 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n@@ -2071,6 +2071,440 @@ codeunit 139963 \"Qlty. Tests - Result Eval.\"\n LibraryAssert.ExpectedError(StrSubstNo(Expected4Err, OptionListQltyInspectionLine.\"Test Code\"));\n end;\n \n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_ValidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC';\n+ DecimalQltyTest.Description := 'Test Decimal';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ DecimalQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ DecimalQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25.5\"\n+ DecimalQltyTest.\"Allowable Values\" := '25.5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"10|20|30\"\n+ DecimalQltyTest.\"Allowable Values\" := '10|20|30';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DecimalQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to not empty condition \"<>''\"\n+ DecimalQltyTest.\"Allowable Values\" := '<>''''';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_InvalidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC2';\n+ DecimalQltyTest.Description := 'Test Decimal Invalid';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a number\"\n+ DecimalQltyTest.\"Allowable Values\" := 'not a number';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid operator \"==5\"\n+ DecimalQltyTest.\"Allowable Values\" := '==5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_ValidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT';\n+ IntegerQltyTest.Description := 'Test Integer';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ IntegerQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ IntegerQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ IntegerQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25\"\n+ IntegerQltyTest.\"Allowable Values\" := '25';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"1|2|3|4|5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1|2|3|4|5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ IntegerQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ IntegerQltyTest.\"Allowable Values\" := '1..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_InvalidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT2';\n+ IntegerQltyTest.Description := 'Test Integer Invalid';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to decimal value \"1.5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1.5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not an integer\"\n+ IntegerQltyTest.\"Allowable Values\" := 'not an integer';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_ValidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE';\n+ DateQltyTest.Description := 'Test Date';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact date \"2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to date range \"2024-01-01..2024-12-31\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01..2024-12-31';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than date \">2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '>2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateQltyTest.\"Allowable Values\" := '>[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_InvalidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE2';\n+ DateQltyTest.Description := 'Test Date Invalid';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid date \"99/99/9999\"\n+ DateQltyTest.\"Allowable Values\" := '99/99/9999';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a date\"\n+ DateQltyTest.\"Allowable Values\" := 'not a date';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_ValidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT';\n+ DateTimeQltyTest.Description := 'Test DateTime';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact datetime \"2024-01-01 10:30:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 10:30:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to datetime range \"2024-01-01 00:00:00..2024-12-31 23:59:59\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 00:00:00..2024-12-31 23:59:59';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than datetime \">2024-01-01 10:00:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '>2024-01-01 10:00:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateTimeQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateTimeQltyTest.\"Allowable Values\" := '<[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_InvalidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT2';\n+ DateTimeQltyTest.Description := 'Test DateTime Invalid';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid datetime \"99/99/9999 99:99:99\"\n+ DateTimeQltyTest.\"Allowable Values\" := '99/99/9999 99:99:99';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a datetime\"\n+ DateTimeQltyTest.\"Allowable Values\" := 'not a datetime';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_ValidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL';\n+ BooleanQltyTest.Description := 'Test Boolean';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to \"Yes\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Yes';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"No\"\n+ BooleanQltyTest.\"Allowable Values\" := 'No';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"True\"\n+ BooleanQltyTest.\"Allowable Values\" := 'True';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"False\"\n+ BooleanQltyTest.\"Allowable Values\" := 'False';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"1\"\n+ BooleanQltyTest.\"Allowable Values\" := '1';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"0\"\n+ BooleanQltyTest.\"Allowable Values\" := '0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"On\"\n+ BooleanQltyTest.\"Allowable Values\" := 'On';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"Off\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Off';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"Y\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Y';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"N\"\n+ BooleanQltyTest.\"Allowable Values\" := 'N';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ BooleanQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ BooleanQltyTest.\"Allowable Values\" := '[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_InvalidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL2';\n+ BooleanQltyTest.Description := 'Test Boolean Invalid';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"Maybe\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Maybe';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid number \"2\"\n+ BooleanQltyTest.\"Allowable Values\" := '2';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a boolean\"\n+ BooleanQltyTest.\"Allowable Values\" := 'not a boolean';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"abc\"\n+ BooleanQltyTest.\"Allowable Values\" := 'abc';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_NonValidatedTypes()\n+ var\n+ TextQltyTest: Record \"Qlty. Test\";\n+ OptionQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat does not validate non-numeric/non-date types\n+\n+ // [GIVEN] A quality test with text type is created\n+ TextQltyTest.Init();\n+ TextQltyTest.Code := 'TESTTEXT';\n+ TextQltyTest.Description := 'Test Text';\n+ TextQltyTest.\"Test Value Type\" := TextQltyTest.\"Test Value Type\"::\"Value Type Text\";\n+ TextQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to any text value \"A|B|C\"\n+ TextQltyTest.\"Allowable Values\" := 'A|B|C';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for text type)\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to any arbitrary text\n+ TextQltyTest.\"Allowable Values\" := 'any text value';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [GIVEN] A quality test with option type is created\n+ OptionQltyTest.Init();\n+ OptionQltyTest.Code := 'TESTOPT';\n+ OptionQltyTest.Description := 'Test Option';\n+ OptionQltyTest.\"Test Value Type\" := OptionQltyTest.\"Test Value Type\"::\"Value Type Option\";\n+ OptionQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to comma-separated options \"Option1,Option2,Option3\"\n+ OptionQltyTest.\"Allowable Values\" := 'Option1,Option2,Option3';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for option type)\n+ OptionQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+\n local procedure GetTemplateLineConfigFilters(var QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\"; var OutTemplateLineQltyIResultConditConf: Record \"Qlty. I. Result Condit. Conf.\")\n begin\n OutTemplateLineQltyIResultConditConf.SetRange(\"Condition Type\", OutTemplateLineQltyIResultConditConf.\"Condition Type\"::Template);\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8286", "base_commit": "9e4bca5d3428c17d51fbe6e903f0efe2bc9e410b", "created_at": "2026-05-22T13:07:41Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\nindex dfb07f0502..a005fa7b7c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n@@ -436,7 +436,7 @@ codeunit 99001508 \"Subc. Price Management\"\n \n GetPriceByUOM(SubcontractorPrice, PriceListQty, PriceListCost);\n if PriceListCost <> 0 then begin\n- ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityBase(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n+ ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityForUOM(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n ConvertPriceToCurrency(RequisitionLine.\"Currency Code\", SubcontractorPrice.\"Currency Code\", PriceListCost, DirectCost);\n end;\n RequisitionLine.\"Direct Unit Cost\" := DirectCost;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..73e138fe61 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -3401,6 +3401,77 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.AreEqual('', ToPurchaseHeader.\"Subc. Location Code\", 'Subc. Location Code should not be copied from archive by Copy Document');\n end;\n \n+ [Test]\n+ procedure WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion()\n+ var\n+ Item: Record Item;\n+ ItemUOM: Record \"Item Unit of Measure\";\n+ Vendor: Record Vendor;\n+ WorkCenter: Record \"Work Center\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ SubcPriceManagement: Codeunit \"Subc. Price Management\";\n+ QtyPerSet: Integer;\n+ PriceListUnitCost: Decimal;\n+ begin\n+ // [SCENARIO 636078] Calculate Subcontracts must compute Direct Unit Cost on the Subcontracting\n+ // Worksheet using the per-UoM conversion factor (GetQuantityForUOM()), not the total base\n+ // quantity (GetQuantityBase()) of the order.\n+\n+ // [GIVEN] Item with PCS base UoM and a SET alternative UoM (10 PCS per SET).\n+ Initialize();\n+ LibraryInventory.CreateItem(Item);\n+ QtyPerSet := 10;\n+ LibraryInventory.CreateItemUnitOfMeasureCode(ItemUOM, Item.\"No.\", QtyPerSet);\n+\n+ // [GIVEN] Vendor and Work Center with the vendor as its subcontractor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+ LibraryManufacturing.CreateWorkCenter(WorkCenter);\n+ WorkCenter.Validate(\"Subcontractor No.\", Vendor.\"No.\");\n+ WorkCenter.Modify(true);\n+\n+ // [GIVEN] A subcontractor price in PCS with Minimum Quantity 1 and Direct Unit Cost 1000.\n+ PriceListUnitCost := 1000;\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter.\"No.\", Vendor.\"No.\", Item.\"No.\", '', '', WorkDate(), Item.\"Base Unit of Measure\", 1, '');\n+ SubcontractorPrice.Validate(\"Direct Unit Cost\", PriceListUnitCost);\n+ SubcontractorPrice.Modify(true);\n+\n+ // [GIVEN] A staged Requisition Line for 3 SET (= 30 PCS in base UoM).\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := ItemUOM.Code;\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 3;\n+\n+ // [WHEN] The subcontractor price is applied to the requisition line.\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost = price-list cost * Qty-per-UoM (1000 * 10 = 10000),\n+ // not price-list cost * total base quantity (1000 * 30 = 30000 — the pre-fix behavior).\n+ Assert.AreEqual(\n+ PriceListUnitCost * QtyPerSet, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost on the Subcontracting Worksheet must be derived from Qty. per Unit of Measure, not from total base quantity.');\n+\n+ // [WHEN] The same price is applied to a Requisition Line using the base UoM (no conversion needed).\n+ Clear(RequisitionLine);\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := Item.\"Base Unit of Measure\";\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 30;\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost equals the price-list cost (the same-UoM path is unchanged by the fix).\n+ Assert.AreEqual(\n+ PriceListUnitCost, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost must equal the price-list cost when the worksheet UoM matches the price-list UoM.');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. Subcontracting Test\");\n"} {"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "cbbf3d36fdf3aeeaefa5bd59e13023fbc9f33c9c", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} {"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "1b05b19c9b6ecee6e567858fc839d2342c6a0526", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} From fe90b688cd76dbd78134cbfb19844ed43c3ad9bd Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Mon, 1 Jun 2026 12:43:30 +0200 Subject: [PATCH 08/14] ues 8059 basec ommit --- dataset/bcbench.jsonl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index d697305fa..02bdb105a 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -100,8 +100,8 @@ {"metadata": {"area": "inventory", "image_count": 7}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-176082", "base_commit": "cb30d50fe1ed2c716c6349370fdc31c6bd0ce956", "created_at": "2024-02-23", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137038, "functionName": ["GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\nindex e0b3ba5f0bf7..ffa98cfbb351 100644\n--- a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n@@ -48,6 +48,7 @@\n UndoneTransLineQtyErr: Label 'Expected Quantity to be 0 after Transfer Shipment was undone';\n DerivedTransLineErr: Label 'Expected no Derived Transfer Line i.e. line with \"Derived From Line No.\" equal to original transfer line.';\n IncorrectSNUndoneErr: Label 'The Serial No. of the item on the transfer shipment line that was undone was different from the SN on the corresponding transfer line.';\n+ ApplToItemEntryErr: Label '%1 must be %2 in %3.', Comment = '%1 is Appl-to Item Entry, %2 is Item Ledger Entry No. and %3 is Transfer Line';\n \n [Test]\n [HandlerFunctions('MessageHandler')]\n@@ -3655,6 +3656,99 @@\n ItemLedgerEntry.TestField(\"Cost Amount (Actual)\", NewCost);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('PostedPurchaseReceiptsModalPageHandler,PostedPurchRcptLinesModalPageHandler')]\n+ procedure GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines()\n+ var\n+ Item: Record Item;\n+ Vendor: Record Vendor;\n+ Location: Record Location;\n+ Location2: Record Location;\n+ Location3: Record Location;\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseHeader2: Record \"Purchase Header\";\n+ PurchaseHeader3: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ PurchaseLine2: Record \"Purchase Line\";\n+ PurchaseLine3: Record \"Purchase Line\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ TransferHeader: Record \"Transfer Header\";\n+ TransferLine: Record \"Transfer Line\";\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ ItemLedgerEntryNo: Integer;\n+ PurchaseReceiptNo: Code[20];\n+ TransferOrder: TestPage \"Transfer Order\";\n+ begin\n+ // [SCENARIO 500597] Get Receipt Lines action on Transfer Order shows list of Posted Purchase Receipts having Transfer-from Code in Location Code of Purch Rcpt Lines and after selecting it populates Appl-to Item Entry field in Transfer Lines.\n+ Initialize();\n+\n+ // [GIVEN] Create an Item and Validate Costing Method.\n+ LibraryInventory.CreateItem(Item);\n+ Item.Validate(\"Costing Method\", Item.\"Costing Method\"::FIFO);\n+ Item.Modify(true);\n+\n+ // [GIVEN] Create two Locations with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location2);\n+\n+ // [GIVEN] Create another Location with Inventory Posting Setup \n+ // And Validate Use As In-Transit.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location3);\n+ Location3.Validate(\"Use As In-Transit\", true);\n+ Location3.Modify(true);\n+\n+ // [GIVEN] Create a Vendor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+\n+ // [GIVEN] Create and Post Purchase Receipt with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader, PurchaseLine, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 2 with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader2, PurchaseLine2, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 3 with Location Code on Line.\n+ PurchaseReceiptNo := CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ PurchaseHeader3,\n+ PurchaseLine3,\n+ Vendor,\n+ Item,\n+ Location);\n+\n+ // [GIVEN] Find and save Item Ledger Entry No. in a Variable.\n+ ItemLedgerEntry.SetRange(\"Document No.\", PurchaseReceiptNo);\n+ ItemLedgerEntry.FindFirst();\n+ ItemLedgerEntryNo := ItemLedgerEntry.\"Entry No.\";\n+\n+ // [GIVEN] Find Purch. Rcpt Line.\n+ FindRandomReceiptLine(PurchaseReceiptNo, PurchRcptLine);\n+\n+ // [GIVEN] Create Transfer Header.\n+ LibraryInventory.CreateTransferHeader(TransferHeader, Location.Code, Location2.Code, Location3.Code);\n+\n+ // [GIVEN] Open Transfer Order page and run Get Receipt Line action.\n+ TransferOrder.OpenEdit();\n+ TransferOrder.GoToRecord(TransferHeader);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchRcptLine.\"No.\");\n+ TransferOrder.GetReceiptLines.Invoke();\n+\n+ // [WHEN] Find Transfer Line.\n+ TransferLine.SetRange(\"Document No.\", TransferHeader.\"No.\");\n+ TransferLine.FindFirst();\n+\n+ // [VERIFY] Appl-to Item Entry and Item Ledger Entry No. are same.\n+ Assert.AreEqual(\n+ ItemLedgerEntryNo,\n+ TransferLine.\"Appl.-to Item Entry\",\n+ StrSubstNo(\n+ ApplToItemEntryErr,\n+ TransferLine.FieldCaption(\"Appl.-to Item Entry\"),\n+ ItemLedgerEntryNo,\n+ TransferLine.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -5168,6 +5262,52 @@\n Assert.AreEqual(LineCount, TransferReceiptLine.Count(), '');\n end;\n \n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchHeader(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location)\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ PurchaseHeader.Validate(\"Location Code\", Location.Code);\n+ PurchaseHeader.Modify(true);\n+\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+ end;\n+\n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location): Code[20]\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Location Code\", Location.Code);\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ exit(LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false));\n+ end;\n+\n [MessageHandler]\n [Scope('OnPrem')]\n procedure MessageHandler(Message: Text[1024])\n@@ -5394,5 +5534,19 @@\n // 0 = Item.Type::Inventory\n Assert.AreEqual('0', ItemList.Filter.GetFilter(\"Type\"), 'Item List contains non-inventory items.');\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure PostedPurchRcptLinesModalPageHandler(var PostedPurchaseReceiptLines: Page \"Posted Purchase Receipt Lines\"; var Response: Action)\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ begin\n+ PurchRcptLine.SetRange(\"Document No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.SetRange(\"No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.FindFirst();\n+ PostedPurchaseReceiptLines.SetRecord(PurchRcptLine);\n+\n+ Response := ACTION::LookupOK;\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\nindex 5fe44b4568d1..c16ab8669925 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n@@ -1304,7 +1304,7 @@ table 5740 \"Transfer Header\"\n TempPurchRcptHeader: Record \"Purch. Rcpt. Header\" temporary;\n PostedPurchaseReceipts: Page \"Posted Purchase Receipts\";\n begin\n- PurchRcptHeader.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ FindPurchRcptHeader(PurchRcptHeader);\n PostedPurchaseReceipts.SetTableView(PurchRcptHeader);\n PostedPurchaseReceipts.LookupMode := true;\n if PostedPurchaseReceipts.RunModal() = ACTION::LookupOK then begin\n@@ -1376,6 +1376,8 @@ table 5740 \"Transfer Header\"\n PurchRcptLine.FilterPstdDocLnItemLedgEntries(ItemLedgerEntry);\n ItemTrackingDocMgt.CopyItemLedgerEntriesToTemp(TempItemLedgerEntry, ItemLedgerEntry);\n ItemTrackingMgt.CopyItemLedgEntryTrkgToTransferLine(TempItemLedgerEntry, TransferLine);\n+ TransferLine.\"Appl.-to Item Entry\" := ItemLedgerEntry.\"Entry No.\";\n+ TransferLine.Modify(true);\n \n OnAfterAddTransferLineFromReceiptLine(TransferLine, PurchRcptLine, TempItemLedgerEntry, Rec);\n end;\n@@ -1546,6 +1548,31 @@ table 5740 \"Transfer Header\"\n end;\n end;\n \n+ local procedure FindPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\")\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ DocumentNo: Code[20];\n+ begin\n+ PurchRcptLine.SetLoadFields(\"Document No.\", \"Location Code\");\n+ PurchRcptLine.SetCurrentKey(\"Document No.\");\n+ PurchRcptLine.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ if PurchRcptLine.FindSet() then\n+ repeat\n+ GetPurchRcptHeader(PurchRcptHeader, PurchRcptLine, DocumentNo);\n+ until PurchRcptLine.Next() = 0;\n+ PurchRcptHeader.MarkedOnly(true);\n+ end;\n+\n+ local procedure GetPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var DocumentNo: Code[20])\n+ begin\n+ if PurchRcptLine.\"Document No.\" = DocumentNo then\n+ exit;\n+\n+ PurchRcptHeader.Get(PurchRcptLine.\"Document No.\");\n+ PurchRcptHeader.Mark(true);\n+ DocumentNo := PurchRcptLine.\"Document No.\";\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnAddTransferLineFromReceiptLineOnBeforeTransferLineInsert(var TransferLine: Record \"Transfer Line\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var TransferHeader: Record \"Transfer Header\")\n begin\n"} {"metadata": {"area": "crm", "image_count": 8}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-174087", "base_commit": "74a0b7c175da3f9a272745bd34453a4712b73e7b", "created_at": "2024-02-02", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\Marketing"], "FAIL_TO_PASS": [{"codeunitID": 136208, "functionName": ["PopulateEvaluationFieldInInteractionLogEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\nindex 4c4c73700d2a..59fff6e2be93 100644\n--- a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n+++ b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n@@ -45,6 +45,7 @@ codeunit 136208 \"Marketing Interaction\"\n LoggedSegemntEntriesCreateMsg: Label 'Logged Segment entry was created';\n AttachmentFileShouldNotBeBlankErr: Label 'Attachment File should not be blank.';\n TxtFileExt: Label 'txt';\n+ EvaluationErr: Label '%1 must be %2 in %3', Comment = '%1 = Evaluation, %2 = Positive, %3 = Interaction Log Entry';\n \n [Test]\n [Scope('OnPrem')]\n@@ -2998,6 +2999,50 @@ codeunit 136208 \"Marketing Interaction\"\n VerifyAttachmentFileIsNotBlankOnInteractionLogEntry(Contact.\"No.\");\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('CreateInteractionFromContactPageHandler')]\n+ procedure PopulateEvaluationFieldInInteractionLogEntry()\n+ var\n+ Contact: Record Contact;\n+ InteractionTemplate: Record \"Interaction Template\";\n+ InteractionLogEntry: Record \"Interaction Log Entry\";\n+ ContactCard: TestPage \"Contact Card\";\n+ InteractionEvaluation: Enum \"Interaction Evaluation\";\n+ begin\n+ // [SCENARIO 498395] When stan creates an Interaction using Create Interaction action from Contact, Evaluation field should be populated in Interaction Log Entry.\n+ Initialize();\n+\n+ // [GIVEN] Create a Contact.\n+ LibraryMarketing.CreateCompanyContact(Contact);\n+\n+ // [GIVEN] Create an Interaction Template and Validate Information Flow.\n+ LibraryMarketing.CreateInteractionTemplate(InteractionTemplate);\n+ InteractionTemplate.Validate(\"Information Flow\", InteractionTemplate.\"Information Flow\"::Outbound);\n+ InteractionTemplate.Modify(true);\n+\n+ // [GIVEN] Open Contact Card and Create Interaction.\n+ ContactCard.OpenEdit();\n+ ContactCard.GoToRecord(Contact);\n+ LibraryVariableStorage.Enqueue(InteractionTemplate.Code);\n+ LibraryVariableStorage.Enqueue(Format(InteractionEvaluation::Positive));\n+ ContactCard.\"Create &Interaction\".Invoke();\n+\n+ // [WHEN] Find Interaction Log Entry.\n+ InteractionLogEntry.SetRange(\"Contact No.\", Contact.\"No.\");\n+ InteractionLogEntry.FindFirst();\n+\n+ // [VERIFY] Interaction Log Entry has Evaluation field populated as Positive.\n+ Assert.AreEqual(\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.Evaluation,\n+ StrSubstNo(\n+ EvaluationErr,\n+ InteractionLogEntry.FieldCaption(Evaluation),\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibrarySales: Codeunit \"Library - Sales\";\n@@ -4309,5 +4354,16 @@ CopyStr(StorageLocation, 1, MaxStrLen(MarketingSetup.\"Attachment Storage Locatio\n CreateInteraction.NextInteraction.Invoke();\n CreateInteraction.Finish.Invoke();\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure CreateInteractionFromContactPageHandler(var CreateInteraction: TestPage \"Create Interaction\")\n+ begin\n+ CreateInteraction.\"Interaction Template Code\".SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.Evaluation.SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.FinishInteraction.Invoke();\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\nindex ff43f4ff6a7b..05a21a6196bf 100644\n--- a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n+++ b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n@@ -694,6 +694,7 @@ page 5077 \"Create Interaction\"\n end;\n Step::\"Step 4\":\n begin\n+ InteractionLogEntry.CopyFromSegment(Rec);\n InteractionLogEntry.Modify();\n CurrPage.Close();\n end;\n"} {"metadata": {"area": "peppol", "image_count": 1}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8059", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-08T09:31:42Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\PEPPOL\\App", "src\\Apps\\W1\\PEPPOL\\Test"], "patch": "diff --git a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\nindex 30f5f792bd..c7981a46fa 100644\n--- a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n@@ -798,6 +798,8 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n InvoiceLineNote := DelChr(Format(SalesLine.Type), '<>');\n InvoicedQuantity := Format(SalesLine.Quantity, 0, 9);\n SalesLineLineAmount := SalesLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesLineLineAmount := Round(SalesLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n InvoiceLineExtensionAmount := Format(SalesLineLineAmount, 0, 9);\n LineExtensionAmountCurrencyID := GetSalesDocCurrencyCode(SalesHeader);\n InvoiceLineAccountingCost := '';\n@@ -869,7 +871,10 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n \n InvLnAllowanceChargeIndicator := 'false';\n InvLnAllowanceChargeReason := LineDisAmtTxt;\n- InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ InvLnAllowanceChargeAmount := Format(Round(SalesLine.\"Line Discount Amount\" / (1 + SalesLine.\"VAT %\" / 100), 0.01), 0, 9)\n+ else\n+ InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n InvLnAllowanceChargeAmtCurrID := GetSalesDocCurrencyCode(SalesHeader);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139235, "functionName": ["LineAmountsConsistentWhenPricesInclVATNoDiscount"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\nindex 36931d56ed..cd237011d5 100644\n--- a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n@@ -3349,6 +3349,68 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual('', CustTaxSchemeID, 'Tax Scheme ID should be empty for Tax Category O.');\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ procedure LineAmountsConsistentWhenPricesInclVATNoDiscount()\n+ var\n+ SalesHeader: Record \"Sales Header\";\n+ SalesLine: Record \"Sales Line\";\n+ Customer: Record Customer;\n+ Item: Record Item;\n+ SalesInvoiceHeader: Record \"Sales Invoice Header\";\n+ SalesInvoiceLine: Record \"Sales Invoice Line\";\n+ PEPPOLLineInfoProvider: Interface \"PEPPOL Line Info Provider\";\n+ InvoiceLineID: Text;\n+ InvoiceLineNote: Text;\n+ InvoicedQuantity: Text;\n+ InvoiceLineExtensionAmount: Text;\n+ LineExtensionAmountCurrencyID: Text;\n+ InvoiceLineAccountingCost: Text;\n+ InvoiceLinePriceAmount: Text;\n+ InvLinePriceAmountCurrencyID: Text;\n+ BaseQuantity: Text;\n+ UnitCode: Text;\n+ PriceAmount: Decimal;\n+ LineExtensionAmt: Decimal;\n+ SalesInvoiceNo: Code[20];\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 630795] PEPPOL LineExtensionAmount equals PriceAmount times Quantity when Prices Including VAT is used\n+ Initialize();\n+\n+ // [GIVEN] Customer \"C\" with PEPPOL identifier\n+ LibrarySales.CreateCustomer(Customer);\n+ AddCustPEPPOLIdentifier(Customer.\"No.\");\n+\n+ // [GIVEN] Sales Invoice for \"C\" with \"Prices Including VAT\" = TRUE and Quantity = 7\n+ CreateItemWithPrice(Item, 139);\n+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader.\"Document Type\"::Invoice, Customer.\"No.\");\n+ SalesHeader.Validate(\"Prices Including VAT\", true);\n+ SalesHeader.Modify(true);\n+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item.\"No.\", 7);\n+\n+ // [WHEN] Post the Sales Invoice and retrieve PEPPOL line amounts\n+ SalesInvoiceNo := LibrarySales.PostSalesDocument(SalesHeader, true, true);\n+ SalesInvoiceHeader.Get(SalesInvoiceNo);\n+ SalesHeader.TransferFields(SalesInvoiceHeader);\n+ FindSalesInvoiceLine(SalesInvoiceLine, SalesInvoiceNo);\n+ SalesLine.TransferFields(SalesInvoiceLine);\n+\n+ PEPPOLLineInfoProvider := GetFormat();\n+ PEPPOLLineInfoProvider.GetLineGeneralInfo(\n+ SalesLine, SalesHeader, InvoiceLineID, InvoiceLineNote, InvoicedQuantity,\n+ InvoiceLineExtensionAmount, LineExtensionAmountCurrencyID, InvoiceLineAccountingCost);\n+ PEPPOLLineInfoProvider.GetLinePriceInfo(\n+ SalesLine, SalesHeader, InvoiceLinePriceAmount, InvLinePriceAmountCurrencyID,\n+ BaseQuantity, UnitCode);\n+\n+ // [THEN] LineExtensionAmount equals PriceAmount times Quantity per PEPPOL BIS 3.0\n+ Evaluate(PriceAmount, InvoiceLinePriceAmount, 9);\n+ Evaluate(LineExtensionAmt, InvoiceLineExtensionAmount, 9);\n+ Assert.AreEqual(PriceAmount * SalesInvoiceLine.Quantity, LineExtensionAmt,\n+ 'LineExtensionAmount must equal PriceAmount * Quantity per PEPPOL BIS 3.0');\n+ end;\n+\n var\n local procedure Initialize()\n var\n@@ -3993,6 +4055,8 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual(UnitOfMeasure.\"International Standard Code\", unitCode, '');\n Assert.AreEqual('UNECERec20', unitCodeListID, '');\n SalesInvoiceLineLineAmount := SalesInvoiceLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesInvoiceLineLineAmount := Round(SalesInvoiceLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n Assert.AreEqual(Format(SalesInvoiceLineLineAmount, 0, 9), InvoiceLineExtensionAmount, '');\n Assert.AreEqual(SalesHeader.\"Currency Code\", LineExtensionAmountCurrencyID, '');\n Assert.AreEqual('', InvoiceLineAccountingCost, '');\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8293", "base_commit": "01e67dc5ff263b26101f7f2db6caa1b346f090a6", "created_at": "2026-05-25T21:31:15Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\nindex 8d5c75124c..056de67a1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n@@ -15,12 +15,13 @@ using System.Reflection;\n codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n {\n /// \n- /// Opens the Released Production Order page for the production order linked to the given variant record.\n+ /// Opens the appropriate Production Order page (Released or Finished) for the production order linked to the given variant record.\n /// \n /// A record variant of a purchase or transfer document line.\n procedure ShowProductionOrder(RecRelatedVariant: Variant)\n var\n ProductionOrder: Record \"Production Order\";\n+ FinishedProductionOrder: Page \"Finished Production Order\";\n ReleasedProductionOrder: Page \"Released Production Order\";\n OperationNo: Code[10];\n ProdOrderNo: Code[20];\n@@ -29,11 +30,26 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n begin\n if not SetProdOrderInformationByVariant(RecRelatedVariant, ProdOrderNo, ProdOrderLineNo, RoutingNo, OperationNo) then\n exit;\n- ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ProductionOrder.SetFilter(Status, '>=%1', ProductionOrder.Status::Released);\n ProductionOrder.SetRange(\"No.\", ProdOrderNo);\n- ReleasedProductionOrder.SetTableView(ProductionOrder);\n- ReleasedProductionOrder.Editable := false;\n- ReleasedProductionOrder.Run();\n+ if not ProductionOrder.FindFirst() then\n+ exit;\n+ case ProductionOrder.Status of\n+ ProductionOrder.Status::Released:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ReleasedProductionOrder.SetTableView(ProductionOrder);\n+ ReleasedProductionOrder.Editable := false;\n+ ReleasedProductionOrder.Run();\n+ end;\n+ ProductionOrder.Status::Finished:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Finished);\n+ FinishedProductionOrder.SetTableView(ProductionOrder);\n+ FinishedProductionOrder.Editable := false;\n+ FinishedProductionOrder.Run();\n+ end;\n+ end;\n end;\n \n /// \n@@ -77,9 +93,9 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n exit(ProdOrderRoutingLine.Count());\n end;\n \n-local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n+ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n begin\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -130,7 +146,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n begin\n ProdOrderRoutingLine.SetLoadFields(\"Routing Link Code\");\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -138,7 +154,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n if ProdOrderRoutingLine.FindFirst() then\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n \n- ProdOrderComponent.SetRange(Status, ProdOrderComponent.Status::Released);\n+ ProdOrderComponent.SetFilter(Status, '>=%1', ProdOrderComponent.Status::Released);\n ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", ProdOrderLineNo);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ProdOFactboxMgmtShowsDataAfterProdOrderFinished"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 68c7fff2af..c6c56da2b8 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1875,6 +1875,57 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n 'CalcNoOfProductionOrderComponents should return a positive count for an Item Ledger Entry from a subcontracting receipt.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmArchiveOrderHandler,HandlePurchaseOrderPage')]\n+ procedure ProdOFactboxMgmtShowsDataAfterProdOrderFinished()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ SubcWorkCenter: Record \"Work Center\";\n+ SubcProdOFactboxMgmt: Codeunit \"Subc. ProdO. Factbox Mgmt.\";\n+ begin\n+ // [SCENARIO 634953] Subcontracting factbox drilldowns should work after production order is finished.\n+ Initialize();\n+\n+ // [GIVEN] A released production order with a subcontracting routing operation and a subcontracting purchase order\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateItemWithSingleSubcontractingOperation(Item, SubcWorkCenter);\n+ SubcontractingMgmtLibrary.UpdateVendorWithSubcontractingLocationCode(SubcWorkCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", SubcWorkCenter.\"No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", SubcWorkCenter.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [GIVEN] The production order is changed to Finished status\n+ LibraryManufacturing.ChangeProdOrderStatus(ProductionOrder, \"Production Order Status\"::Finished, WorkDate(), true);\n+\n+ // Re-read purchase line (the order still exists because only receipt was posted)\n+ PurchaseLine.FindFirst();\n+\n+ // [WHEN] CalcNoOfProductionOrderRoutings / CalcNoOfProductionOrderComponents are called with the Purchase Line\n+ // [THEN] Both return a positive count even though the production order is now Finished\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderRoutings(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderRoutings should return a positive count after the production order is finished.');\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderComponents(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderComponents should return a positive count after the production order is finished.');\n+ end;\n+\n [Test]\n [HandlerFunctions('ConfirmHandler')]\n procedure RoutingFactboxMgmtFiltersPurchOrderQtyByRoutingReferenceNo()\n@@ -3430,6 +3481,7 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n \n SubSetupLibrary.InitSetupFields();\n LibraryERMCountryData.CreateVATData();\n+ LibraryERMCountryData.UpdateGeneralPostingSetup();\n SubSetupLibrary.InitialSetupForGenProdPostingGroup();\n \n IsInitialized := true;\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8287", "base_commit": "ad39c988e2565d1ea1a8cb538a5b9a6ec4107eb4", "created_at": "2026-05-22T17:02:35Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\nindex b8a5c1d869..c1b2942c55 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n@@ -22,6 +22,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n IsDefaultTextTok: Label '<>''''', Locked = true;\n InvalidDataTypeErr: Label 'The value \"%1\" is not allowed for %2, it is not a %3.', Comment = '%1=the value, %2=field name,%3=field type.';\n NotInAllowableValuesErr: Label 'The value \"%1\" is not allowed for %2, it must be in the range of \"%3\".', Comment = '%1=the value, %2=field name,%3=field type.';\n+ InvalidAllowableValuesFormatErr: Label 'The allowable values \"%1\" are not a valid filter expression for %2 of type %3.', Comment = '%1=the allowable values, %2=field name, %3=field type.';\n \n trigger OnRun()\n var\n@@ -324,6 +325,110 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n ValidateAllowableValuesOnText(TestNameForError, QltyTest.\"Default Value\", QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\", TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// The test whose allowable values expression should be validated.\n+ internal procedure ValidateAllowableValuesFormat(var QltyTest: Record \"Qlty. Test\")\n+ var\n+ TestNameForError: Text;\n+ begin\n+ if QltyTest.Description <> '' then\n+ TestNameForError := QltyTest.Description\n+ else\n+ TestNameForError := QltyTest.Code;\n+\n+ ValidateAllowableValuesFormat(TestNameForError, QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\");\n+ end;\n+\n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// Friendly identifier used in error messages.\n+ /// The allowable values filter expression to validate.\n+ /// The test value type that the filter expression must match.\n+ local procedure ValidateAllowableValuesFormat(NumberOrNameOfTestNameForError: Text; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\")\n+ var\n+ IsValid: Boolean;\n+ begin\n+ if AllowableValues = '' then\n+ exit;\n+\n+ if IsBlankOrEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ if IsAnythingExceptEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ // Allowable values may contain inline expressions like [Field] that are resolved at evaluation time.\n+ // Defer validation until resolution.\n+ if AllowableValues.Contains('[') then\n+ exit;\n+\n+ IsValid := true;\n+ case QltyTestValueType of\n+ QltyTestValueType::\"Value Type Decimal\":\n+ IsValid := TryApplyDecimalFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Integer\":\n+ IsValid := TryApplyIntegerFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Boolean\":\n+ IsValid := TryApplyBooleanFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Date\":\n+ IsValid := TryApplyDateFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type DateTime\":\n+ IsValid := TryApplyDateTimeFilter(AllowableValues);\n+ end;\n+\n+ if not IsValid then\n+ Error(InvalidAllowableValuesFormatErr, AllowableValues, NumberOrNameOfTestNameForError, QltyTestValueType);\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDecimalFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionLine: Record \"Qlty. Inspection Line\" temporary;\n+ begin\n+ TempQltyInspectionLine.SetFilter(\"Derived Numeric Value\", FilterExpression);\n+ if TempQltyInspectionLine.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyIntegerFilter(FilterExpression: Text)\n+ var\n+ TempInteger: Record \"Integer\" temporary;\n+ begin\n+ TempInteger.SetFilter(Number, FilterExpression);\n+ if TempInteger.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyBooleanFilter(FilterExpression: Text)\n+ var\n+ QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n+ begin\n+ // Valid boolean allowable values are: Yes, No, True, False, 1, 0, On, Off (and variations)\n+ if not QltyBooleanParsing.CanTextBeInterpretedAsBooleanIsh(FilterExpression) then\n+ Error(InvalidAllowableValuesFormatErr, FilterExpression, '', 'Boolean');\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateFilter(FilterExpression: Text)\n+ var\n+ TempDateLookupBuffer: Record \"Date Lookup Buffer\" temporary;\n+ begin\n+ TempDateLookupBuffer.SetFilter(\"Period Start\", FilterExpression);\n+ if TempDateLookupBuffer.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateTimeFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionHeader: Record \"Qlty. Inspection Header\" temporary;\n+ begin\n+ TempQltyInspectionHeader.SetFilter(\"Finished Date\", FilterExpression);\n+ if TempQltyInspectionHeader.IsEmpty() then;\n+ end;\n+\n local procedure ValidateAllowableValuesOnText(NumberOrNameOfTestNameForError: Text; var TextToValidate: Text[250]; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\"; var TempBufferQltyTestLookupValue: Record \"Qlty. Test Lookup Value\" temporary; QltyCaseSensitivity: Enum \"Qlty. Case Sensitivity\")\n var\n QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n@@ -393,9 +498,8 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n if not (IsBlankOrEmptyCondition(AllowableValues) and (TextToValidate = '')) then\n if not QltyResultEvaluation.CheckIfValueIsString(TextToValidate, ConvertStr(AllowableValues, ',', '|'), QltyCaseSensitivity) then\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n-\n QltyTestValueType::\"Value Type Option\",\n- QltyTestValueType::\"Value Type Table Lookup\":\n+ QltyTestValueType::\"Value Type Table Lookup\":\n begin\n TextToValidate := CopyStr(TextToValidate.Trim(), 1, MaxStrLen(TextToValidate));\n \n@@ -419,6 +523,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n end;\n end;\n+\n OnAfterValidateAllowableValuesOnText(NumberOrNameOfTestNameForError, TextToValidate, AllowableValues, QltyTestValueType, TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139963, "functionName": ["ValidateAllowableValuesFormat_Boolean_ValidFormats", "ValidateAllowableValuesFormat_NonValidatedTypes", "ValidateAllowableValuesFormat_Boolean_InvalidFormats", "ValidateAllowableValuesFormat_DateTime_InvalidFormats", "ValidateAllowableValuesFormat_Integer_ValidFormats", "ValidateAllowableValuesFormat_Integer_InvalidFormats", "ValidateAllowableValuesFormat_Date_InvalidFormats", "ValidateAllowableValuesFormat_Decimal_ValidFormats", "ValidateAllowableValuesFormat_Date_ValidFormats", "ValidateAllowableValuesFormat_DateTime_ValidFormats", "ValidateAllowableValuesFormat_Decimal_InvalidFormats"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\nindex 9f4cbf3006..66e4c203fc 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n@@ -54,8 +54,11 @@ table 20401 \"Qlty. Test\"\n {\n Caption = 'Allowable Values';\n ToolTip = 'Specifies an expression for the range of values you can enter or select for the Test. Depending on the Test Value Type, the expression format varies. For example if you want a measurement such as a percentage that collects between 0 and 100 you would enter 0..100. This is not the pass or acceptable condition, these are just the technically possible values that the inspector can enter. You would then enter a passing condition in your result conditions. If you had a result of Pass being 80 to 100, you would then configure 80..100 for that result.';\n+\n trigger OnValidate()\n begin\n+ Rec.ValidateAllowableValuesFormat();\n+\n if Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Option\", Rec.\"Test Value Type\"::\"Value Type Table Lookup\"] then\n Rec.\"Allowable Values\" := CopyStr(Rec.\"Allowable Values\".Replace(', ', ','), 1, MaxStrLen(Rec.\"Allowable Values\"));\n end;\n@@ -472,6 +475,16 @@ table 20401 \"Qlty. Test\"\n QltyResultEvaluation.ValidateAllowableValuesOnTest(Rec);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the test value type.\n+ /// \n+ procedure ValidateAllowableValuesFormat()\n+ var\n+ QltyResultEvaluation: Codeunit \"Qlty. Result Evaluation\";\n+ begin\n+ QltyResultEvaluation.ValidateAllowableValuesFormat(Rec);\n+ end;\n+\n /// \n /// Code = the unique code\n /// Description = raw description.\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\nindex 91159fca6e..05f7d8a17a 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n@@ -2071,6 +2071,440 @@ codeunit 139963 \"Qlty. Tests - Result Eval.\"\n LibraryAssert.ExpectedError(StrSubstNo(Expected4Err, OptionListQltyInspectionLine.\"Test Code\"));\n end;\n \n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_ValidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC';\n+ DecimalQltyTest.Description := 'Test Decimal';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ DecimalQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ DecimalQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25.5\"\n+ DecimalQltyTest.\"Allowable Values\" := '25.5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"10|20|30\"\n+ DecimalQltyTest.\"Allowable Values\" := '10|20|30';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DecimalQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to not empty condition \"<>''\"\n+ DecimalQltyTest.\"Allowable Values\" := '<>''''';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_InvalidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC2';\n+ DecimalQltyTest.Description := 'Test Decimal Invalid';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a number\"\n+ DecimalQltyTest.\"Allowable Values\" := 'not a number';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid operator \"==5\"\n+ DecimalQltyTest.\"Allowable Values\" := '==5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_ValidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT';\n+ IntegerQltyTest.Description := 'Test Integer';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ IntegerQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ IntegerQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ IntegerQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25\"\n+ IntegerQltyTest.\"Allowable Values\" := '25';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"1|2|3|4|5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1|2|3|4|5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ IntegerQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ IntegerQltyTest.\"Allowable Values\" := '1..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_InvalidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT2';\n+ IntegerQltyTest.Description := 'Test Integer Invalid';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to decimal value \"1.5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1.5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not an integer\"\n+ IntegerQltyTest.\"Allowable Values\" := 'not an integer';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_ValidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE';\n+ DateQltyTest.Description := 'Test Date';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact date \"2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to date range \"2024-01-01..2024-12-31\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01..2024-12-31';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than date \">2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '>2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateQltyTest.\"Allowable Values\" := '>[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_InvalidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE2';\n+ DateQltyTest.Description := 'Test Date Invalid';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid date \"99/99/9999\"\n+ DateQltyTest.\"Allowable Values\" := '99/99/9999';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a date\"\n+ DateQltyTest.\"Allowable Values\" := 'not a date';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_ValidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT';\n+ DateTimeQltyTest.Description := 'Test DateTime';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact datetime \"2024-01-01 10:30:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 10:30:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to datetime range \"2024-01-01 00:00:00..2024-12-31 23:59:59\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 00:00:00..2024-12-31 23:59:59';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than datetime \">2024-01-01 10:00:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '>2024-01-01 10:00:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateTimeQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateTimeQltyTest.\"Allowable Values\" := '<[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_InvalidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT2';\n+ DateTimeQltyTest.Description := 'Test DateTime Invalid';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid datetime \"99/99/9999 99:99:99\"\n+ DateTimeQltyTest.\"Allowable Values\" := '99/99/9999 99:99:99';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a datetime\"\n+ DateTimeQltyTest.\"Allowable Values\" := 'not a datetime';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_ValidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL';\n+ BooleanQltyTest.Description := 'Test Boolean';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to \"Yes\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Yes';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"No\"\n+ BooleanQltyTest.\"Allowable Values\" := 'No';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"True\"\n+ BooleanQltyTest.\"Allowable Values\" := 'True';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"False\"\n+ BooleanQltyTest.\"Allowable Values\" := 'False';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"1\"\n+ BooleanQltyTest.\"Allowable Values\" := '1';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"0\"\n+ BooleanQltyTest.\"Allowable Values\" := '0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"On\"\n+ BooleanQltyTest.\"Allowable Values\" := 'On';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"Off\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Off';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"Y\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Y';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"N\"\n+ BooleanQltyTest.\"Allowable Values\" := 'N';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ BooleanQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ BooleanQltyTest.\"Allowable Values\" := '[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_InvalidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL2';\n+ BooleanQltyTest.Description := 'Test Boolean Invalid';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"Maybe\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Maybe';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid number \"2\"\n+ BooleanQltyTest.\"Allowable Values\" := '2';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a boolean\"\n+ BooleanQltyTest.\"Allowable Values\" := 'not a boolean';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"abc\"\n+ BooleanQltyTest.\"Allowable Values\" := 'abc';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_NonValidatedTypes()\n+ var\n+ TextQltyTest: Record \"Qlty. Test\";\n+ OptionQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat does not validate non-numeric/non-date types\n+\n+ // [GIVEN] A quality test with text type is created\n+ TextQltyTest.Init();\n+ TextQltyTest.Code := 'TESTTEXT';\n+ TextQltyTest.Description := 'Test Text';\n+ TextQltyTest.\"Test Value Type\" := TextQltyTest.\"Test Value Type\"::\"Value Type Text\";\n+ TextQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to any text value \"A|B|C\"\n+ TextQltyTest.\"Allowable Values\" := 'A|B|C';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for text type)\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to any arbitrary text\n+ TextQltyTest.\"Allowable Values\" := 'any text value';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [GIVEN] A quality test with option type is created\n+ OptionQltyTest.Init();\n+ OptionQltyTest.Code := 'TESTOPT';\n+ OptionQltyTest.Description := 'Test Option';\n+ OptionQltyTest.\"Test Value Type\" := OptionQltyTest.\"Test Value Type\"::\"Value Type Option\";\n+ OptionQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to comma-separated options \"Option1,Option2,Option3\"\n+ OptionQltyTest.\"Allowable Values\" := 'Option1,Option2,Option3';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for option type)\n+ OptionQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+\n local procedure GetTemplateLineConfigFilters(var QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\"; var OutTemplateLineQltyIResultConditConf: Record \"Qlty. I. Result Condit. Conf.\")\n begin\n OutTemplateLineQltyIResultConditConf.SetRange(\"Condition Type\", OutTemplateLineQltyIResultConditConf.\"Condition Type\"::Template);\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8286", "base_commit": "9e4bca5d3428c17d51fbe6e903f0efe2bc9e410b", "created_at": "2026-05-22T13:07:41Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\nindex dfb07f0502..a005fa7b7c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n@@ -436,7 +436,7 @@ codeunit 99001508 \"Subc. Price Management\"\n \n GetPriceByUOM(SubcontractorPrice, PriceListQty, PriceListCost);\n if PriceListCost <> 0 then begin\n- ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityBase(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n+ ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityForUOM(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n ConvertPriceToCurrency(RequisitionLine.\"Currency Code\", SubcontractorPrice.\"Currency Code\", PriceListCost, DirectCost);\n end;\n RequisitionLine.\"Direct Unit Cost\" := DirectCost;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..73e138fe61 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -3401,6 +3401,77 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.AreEqual('', ToPurchaseHeader.\"Subc. Location Code\", 'Subc. Location Code should not be copied from archive by Copy Document');\n end;\n \n+ [Test]\n+ procedure WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion()\n+ var\n+ Item: Record Item;\n+ ItemUOM: Record \"Item Unit of Measure\";\n+ Vendor: Record Vendor;\n+ WorkCenter: Record \"Work Center\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ SubcPriceManagement: Codeunit \"Subc. Price Management\";\n+ QtyPerSet: Integer;\n+ PriceListUnitCost: Decimal;\n+ begin\n+ // [SCENARIO 636078] Calculate Subcontracts must compute Direct Unit Cost on the Subcontracting\n+ // Worksheet using the per-UoM conversion factor (GetQuantityForUOM()), not the total base\n+ // quantity (GetQuantityBase()) of the order.\n+\n+ // [GIVEN] Item with PCS base UoM and a SET alternative UoM (10 PCS per SET).\n+ Initialize();\n+ LibraryInventory.CreateItem(Item);\n+ QtyPerSet := 10;\n+ LibraryInventory.CreateItemUnitOfMeasureCode(ItemUOM, Item.\"No.\", QtyPerSet);\n+\n+ // [GIVEN] Vendor and Work Center with the vendor as its subcontractor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+ LibraryManufacturing.CreateWorkCenter(WorkCenter);\n+ WorkCenter.Validate(\"Subcontractor No.\", Vendor.\"No.\");\n+ WorkCenter.Modify(true);\n+\n+ // [GIVEN] A subcontractor price in PCS with Minimum Quantity 1 and Direct Unit Cost 1000.\n+ PriceListUnitCost := 1000;\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter.\"No.\", Vendor.\"No.\", Item.\"No.\", '', '', WorkDate(), Item.\"Base Unit of Measure\", 1, '');\n+ SubcontractorPrice.Validate(\"Direct Unit Cost\", PriceListUnitCost);\n+ SubcontractorPrice.Modify(true);\n+\n+ // [GIVEN] A staged Requisition Line for 3 SET (= 30 PCS in base UoM).\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := ItemUOM.Code;\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 3;\n+\n+ // [WHEN] The subcontractor price is applied to the requisition line.\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost = price-list cost * Qty-per-UoM (1000 * 10 = 10000),\n+ // not price-list cost * total base quantity (1000 * 30 = 30000 — the pre-fix behavior).\n+ Assert.AreEqual(\n+ PriceListUnitCost * QtyPerSet, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost on the Subcontracting Worksheet must be derived from Qty. per Unit of Measure, not from total base quantity.');\n+\n+ // [WHEN] The same price is applied to a Requisition Line using the base UoM (no conversion needed).\n+ Clear(RequisitionLine);\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := Item.\"Base Unit of Measure\";\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 30;\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost equals the price-list cost (the same-UoM path is unchanged by the fix).\n+ Assert.AreEqual(\n+ PriceListUnitCost, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost must equal the price-list cost when the worksheet UoM matches the price-list UoM.');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. Subcontracting Test\");\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8293", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-25T21:31:15Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\nindex 8d5c75124c..056de67a1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n@@ -15,12 +15,13 @@ using System.Reflection;\n codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n {\n /// \n- /// Opens the Released Production Order page for the production order linked to the given variant record.\n+ /// Opens the appropriate Production Order page (Released or Finished) for the production order linked to the given variant record.\n /// \n /// A record variant of a purchase or transfer document line.\n procedure ShowProductionOrder(RecRelatedVariant: Variant)\n var\n ProductionOrder: Record \"Production Order\";\n+ FinishedProductionOrder: Page \"Finished Production Order\";\n ReleasedProductionOrder: Page \"Released Production Order\";\n OperationNo: Code[10];\n ProdOrderNo: Code[20];\n@@ -29,11 +30,26 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n begin\n if not SetProdOrderInformationByVariant(RecRelatedVariant, ProdOrderNo, ProdOrderLineNo, RoutingNo, OperationNo) then\n exit;\n- ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ProductionOrder.SetFilter(Status, '>=%1', ProductionOrder.Status::Released);\n ProductionOrder.SetRange(\"No.\", ProdOrderNo);\n- ReleasedProductionOrder.SetTableView(ProductionOrder);\n- ReleasedProductionOrder.Editable := false;\n- ReleasedProductionOrder.Run();\n+ if not ProductionOrder.FindFirst() then\n+ exit;\n+ case ProductionOrder.Status of\n+ ProductionOrder.Status::Released:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ReleasedProductionOrder.SetTableView(ProductionOrder);\n+ ReleasedProductionOrder.Editable := false;\n+ ReleasedProductionOrder.Run();\n+ end;\n+ ProductionOrder.Status::Finished:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Finished);\n+ FinishedProductionOrder.SetTableView(ProductionOrder);\n+ FinishedProductionOrder.Editable := false;\n+ FinishedProductionOrder.Run();\n+ end;\n+ end;\n end;\n \n /// \n@@ -77,9 +93,9 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n exit(ProdOrderRoutingLine.Count());\n end;\n \n-local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n+ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n begin\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -130,7 +146,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n begin\n ProdOrderRoutingLine.SetLoadFields(\"Routing Link Code\");\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -138,7 +154,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n if ProdOrderRoutingLine.FindFirst() then\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n \n- ProdOrderComponent.SetRange(Status, ProdOrderComponent.Status::Released);\n+ ProdOrderComponent.SetFilter(Status, '>=%1', ProdOrderComponent.Status::Released);\n ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", ProdOrderLineNo);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ProdOFactboxMgmtShowsDataAfterProdOrderFinished"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 68c7fff2af..c6c56da2b8 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1875,6 +1875,57 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n 'CalcNoOfProductionOrderComponents should return a positive count for an Item Ledger Entry from a subcontracting receipt.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmArchiveOrderHandler,HandlePurchaseOrderPage')]\n+ procedure ProdOFactboxMgmtShowsDataAfterProdOrderFinished()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ SubcWorkCenter: Record \"Work Center\";\n+ SubcProdOFactboxMgmt: Codeunit \"Subc. ProdO. Factbox Mgmt.\";\n+ begin\n+ // [SCENARIO 634953] Subcontracting factbox drilldowns should work after production order is finished.\n+ Initialize();\n+\n+ // [GIVEN] A released production order with a subcontracting routing operation and a subcontracting purchase order\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateItemWithSingleSubcontractingOperation(Item, SubcWorkCenter);\n+ SubcontractingMgmtLibrary.UpdateVendorWithSubcontractingLocationCode(SubcWorkCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", SubcWorkCenter.\"No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", SubcWorkCenter.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [GIVEN] The production order is changed to Finished status\n+ LibraryManufacturing.ChangeProdOrderStatus(ProductionOrder, \"Production Order Status\"::Finished, WorkDate(), true);\n+\n+ // Re-read purchase line (the order still exists because only receipt was posted)\n+ PurchaseLine.FindFirst();\n+\n+ // [WHEN] CalcNoOfProductionOrderRoutings / CalcNoOfProductionOrderComponents are called with the Purchase Line\n+ // [THEN] Both return a positive count even though the production order is now Finished\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderRoutings(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderRoutings should return a positive count after the production order is finished.');\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderComponents(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderComponents should return a positive count after the production order is finished.');\n+ end;\n+\n [Test]\n [HandlerFunctions('ConfirmHandler')]\n procedure RoutingFactboxMgmtFiltersPurchOrderQtyByRoutingReferenceNo()\n@@ -3430,6 +3481,7 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n \n SubSetupLibrary.InitSetupFields();\n LibraryERMCountryData.CreateVATData();\n+ LibraryERMCountryData.UpdateGeneralPostingSetup();\n SubSetupLibrary.InitialSetupForGenProdPostingGroup();\n \n IsInitialized := true;\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8287", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-22T17:02:35Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\nindex b8a5c1d869..c1b2942c55 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n@@ -22,6 +22,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n IsDefaultTextTok: Label '<>''''', Locked = true;\n InvalidDataTypeErr: Label 'The value \"%1\" is not allowed for %2, it is not a %3.', Comment = '%1=the value, %2=field name,%3=field type.';\n NotInAllowableValuesErr: Label 'The value \"%1\" is not allowed for %2, it must be in the range of \"%3\".', Comment = '%1=the value, %2=field name,%3=field type.';\n+ InvalidAllowableValuesFormatErr: Label 'The allowable values \"%1\" are not a valid filter expression for %2 of type %3.', Comment = '%1=the allowable values, %2=field name, %3=field type.';\n \n trigger OnRun()\n var\n@@ -324,6 +325,110 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n ValidateAllowableValuesOnText(TestNameForError, QltyTest.\"Default Value\", QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\", TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// The test whose allowable values expression should be validated.\n+ internal procedure ValidateAllowableValuesFormat(var QltyTest: Record \"Qlty. Test\")\n+ var\n+ TestNameForError: Text;\n+ begin\n+ if QltyTest.Description <> '' then\n+ TestNameForError := QltyTest.Description\n+ else\n+ TestNameForError := QltyTest.Code;\n+\n+ ValidateAllowableValuesFormat(TestNameForError, QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\");\n+ end;\n+\n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// Friendly identifier used in error messages.\n+ /// The allowable values filter expression to validate.\n+ /// The test value type that the filter expression must match.\n+ local procedure ValidateAllowableValuesFormat(NumberOrNameOfTestNameForError: Text; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\")\n+ var\n+ IsValid: Boolean;\n+ begin\n+ if AllowableValues = '' then\n+ exit;\n+\n+ if IsBlankOrEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ if IsAnythingExceptEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ // Allowable values may contain inline expressions like [Field] that are resolved at evaluation time.\n+ // Defer validation until resolution.\n+ if AllowableValues.Contains('[') then\n+ exit;\n+\n+ IsValid := true;\n+ case QltyTestValueType of\n+ QltyTestValueType::\"Value Type Decimal\":\n+ IsValid := TryApplyDecimalFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Integer\":\n+ IsValid := TryApplyIntegerFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Boolean\":\n+ IsValid := TryApplyBooleanFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Date\":\n+ IsValid := TryApplyDateFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type DateTime\":\n+ IsValid := TryApplyDateTimeFilter(AllowableValues);\n+ end;\n+\n+ if not IsValid then\n+ Error(InvalidAllowableValuesFormatErr, AllowableValues, NumberOrNameOfTestNameForError, QltyTestValueType);\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDecimalFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionLine: Record \"Qlty. Inspection Line\" temporary;\n+ begin\n+ TempQltyInspectionLine.SetFilter(\"Derived Numeric Value\", FilterExpression);\n+ if TempQltyInspectionLine.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyIntegerFilter(FilterExpression: Text)\n+ var\n+ TempInteger: Record \"Integer\" temporary;\n+ begin\n+ TempInteger.SetFilter(Number, FilterExpression);\n+ if TempInteger.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyBooleanFilter(FilterExpression: Text)\n+ var\n+ QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n+ begin\n+ // Valid boolean allowable values are: Yes, No, True, False, 1, 0, On, Off (and variations)\n+ if not QltyBooleanParsing.CanTextBeInterpretedAsBooleanIsh(FilterExpression) then\n+ Error(InvalidAllowableValuesFormatErr, FilterExpression, '', 'Boolean');\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateFilter(FilterExpression: Text)\n+ var\n+ TempDateLookupBuffer: Record \"Date Lookup Buffer\" temporary;\n+ begin\n+ TempDateLookupBuffer.SetFilter(\"Period Start\", FilterExpression);\n+ if TempDateLookupBuffer.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateTimeFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionHeader: Record \"Qlty. Inspection Header\" temporary;\n+ begin\n+ TempQltyInspectionHeader.SetFilter(\"Finished Date\", FilterExpression);\n+ if TempQltyInspectionHeader.IsEmpty() then;\n+ end;\n+\n local procedure ValidateAllowableValuesOnText(NumberOrNameOfTestNameForError: Text; var TextToValidate: Text[250]; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\"; var TempBufferQltyTestLookupValue: Record \"Qlty. Test Lookup Value\" temporary; QltyCaseSensitivity: Enum \"Qlty. Case Sensitivity\")\n var\n QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n@@ -393,9 +498,8 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n if not (IsBlankOrEmptyCondition(AllowableValues) and (TextToValidate = '')) then\n if not QltyResultEvaluation.CheckIfValueIsString(TextToValidate, ConvertStr(AllowableValues, ',', '|'), QltyCaseSensitivity) then\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n-\n QltyTestValueType::\"Value Type Option\",\n- QltyTestValueType::\"Value Type Table Lookup\":\n+ QltyTestValueType::\"Value Type Table Lookup\":\n begin\n TextToValidate := CopyStr(TextToValidate.Trim(), 1, MaxStrLen(TextToValidate));\n \n@@ -419,6 +523,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n end;\n end;\n+\n OnAfterValidateAllowableValuesOnText(NumberOrNameOfTestNameForError, TextToValidate, AllowableValues, QltyTestValueType, TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139963, "functionName": ["ValidateAllowableValuesFormat_Boolean_ValidFormats", "ValidateAllowableValuesFormat_NonValidatedTypes", "ValidateAllowableValuesFormat_Boolean_InvalidFormats", "ValidateAllowableValuesFormat_DateTime_InvalidFormats", "ValidateAllowableValuesFormat_Integer_ValidFormats", "ValidateAllowableValuesFormat_Integer_InvalidFormats", "ValidateAllowableValuesFormat_Date_InvalidFormats", "ValidateAllowableValuesFormat_Decimal_ValidFormats", "ValidateAllowableValuesFormat_Date_ValidFormats", "ValidateAllowableValuesFormat_DateTime_ValidFormats", "ValidateAllowableValuesFormat_Decimal_InvalidFormats"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\nindex 9f4cbf3006..66e4c203fc 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n@@ -54,8 +54,11 @@ table 20401 \"Qlty. Test\"\n {\n Caption = 'Allowable Values';\n ToolTip = 'Specifies an expression for the range of values you can enter or select for the Test. Depending on the Test Value Type, the expression format varies. For example if you want a measurement such as a percentage that collects between 0 and 100 you would enter 0..100. This is not the pass or acceptable condition, these are just the technically possible values that the inspector can enter. You would then enter a passing condition in your result conditions. If you had a result of Pass being 80 to 100, you would then configure 80..100 for that result.';\n+\n trigger OnValidate()\n begin\n+ Rec.ValidateAllowableValuesFormat();\n+\n if Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Option\", Rec.\"Test Value Type\"::\"Value Type Table Lookup\"] then\n Rec.\"Allowable Values\" := CopyStr(Rec.\"Allowable Values\".Replace(', ', ','), 1, MaxStrLen(Rec.\"Allowable Values\"));\n end;\n@@ -472,6 +475,16 @@ table 20401 \"Qlty. Test\"\n QltyResultEvaluation.ValidateAllowableValuesOnTest(Rec);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the test value type.\n+ /// \n+ procedure ValidateAllowableValuesFormat()\n+ var\n+ QltyResultEvaluation: Codeunit \"Qlty. Result Evaluation\";\n+ begin\n+ QltyResultEvaluation.ValidateAllowableValuesFormat(Rec);\n+ end;\n+\n /// \n /// Code = the unique code\n /// Description = raw description.\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\nindex 91159fca6e..05f7d8a17a 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n@@ -2071,6 +2071,440 @@ codeunit 139963 \"Qlty. Tests - Result Eval.\"\n LibraryAssert.ExpectedError(StrSubstNo(Expected4Err, OptionListQltyInspectionLine.\"Test Code\"));\n end;\n \n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_ValidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC';\n+ DecimalQltyTest.Description := 'Test Decimal';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ DecimalQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ DecimalQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25.5\"\n+ DecimalQltyTest.\"Allowable Values\" := '25.5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"10|20|30\"\n+ DecimalQltyTest.\"Allowable Values\" := '10|20|30';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DecimalQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to not empty condition \"<>''\"\n+ DecimalQltyTest.\"Allowable Values\" := '<>''''';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_InvalidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC2';\n+ DecimalQltyTest.Description := 'Test Decimal Invalid';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a number\"\n+ DecimalQltyTest.\"Allowable Values\" := 'not a number';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid operator \"==5\"\n+ DecimalQltyTest.\"Allowable Values\" := '==5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_ValidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT';\n+ IntegerQltyTest.Description := 'Test Integer';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ IntegerQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ IntegerQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ IntegerQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25\"\n+ IntegerQltyTest.\"Allowable Values\" := '25';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"1|2|3|4|5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1|2|3|4|5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ IntegerQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ IntegerQltyTest.\"Allowable Values\" := '1..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_InvalidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT2';\n+ IntegerQltyTest.Description := 'Test Integer Invalid';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to decimal value \"1.5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1.5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not an integer\"\n+ IntegerQltyTest.\"Allowable Values\" := 'not an integer';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_ValidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE';\n+ DateQltyTest.Description := 'Test Date';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact date \"2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to date range \"2024-01-01..2024-12-31\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01..2024-12-31';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than date \">2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '>2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateQltyTest.\"Allowable Values\" := '>[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_InvalidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE2';\n+ DateQltyTest.Description := 'Test Date Invalid';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid date \"99/99/9999\"\n+ DateQltyTest.\"Allowable Values\" := '99/99/9999';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a date\"\n+ DateQltyTest.\"Allowable Values\" := 'not a date';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_ValidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT';\n+ DateTimeQltyTest.Description := 'Test DateTime';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact datetime \"2024-01-01 10:30:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 10:30:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to datetime range \"2024-01-01 00:00:00..2024-12-31 23:59:59\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 00:00:00..2024-12-31 23:59:59';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than datetime \">2024-01-01 10:00:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '>2024-01-01 10:00:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateTimeQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateTimeQltyTest.\"Allowable Values\" := '<[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_InvalidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT2';\n+ DateTimeQltyTest.Description := 'Test DateTime Invalid';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid datetime \"99/99/9999 99:99:99\"\n+ DateTimeQltyTest.\"Allowable Values\" := '99/99/9999 99:99:99';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a datetime\"\n+ DateTimeQltyTest.\"Allowable Values\" := 'not a datetime';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_ValidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL';\n+ BooleanQltyTest.Description := 'Test Boolean';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to \"Yes\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Yes';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"No\"\n+ BooleanQltyTest.\"Allowable Values\" := 'No';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"True\"\n+ BooleanQltyTest.\"Allowable Values\" := 'True';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"False\"\n+ BooleanQltyTest.\"Allowable Values\" := 'False';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"1\"\n+ BooleanQltyTest.\"Allowable Values\" := '1';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"0\"\n+ BooleanQltyTest.\"Allowable Values\" := '0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"On\"\n+ BooleanQltyTest.\"Allowable Values\" := 'On';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"Off\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Off';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"Y\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Y';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"N\"\n+ BooleanQltyTest.\"Allowable Values\" := 'N';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ BooleanQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ BooleanQltyTest.\"Allowable Values\" := '[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_InvalidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL2';\n+ BooleanQltyTest.Description := 'Test Boolean Invalid';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"Maybe\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Maybe';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid number \"2\"\n+ BooleanQltyTest.\"Allowable Values\" := '2';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a boolean\"\n+ BooleanQltyTest.\"Allowable Values\" := 'not a boolean';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"abc\"\n+ BooleanQltyTest.\"Allowable Values\" := 'abc';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_NonValidatedTypes()\n+ var\n+ TextQltyTest: Record \"Qlty. Test\";\n+ OptionQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat does not validate non-numeric/non-date types\n+\n+ // [GIVEN] A quality test with text type is created\n+ TextQltyTest.Init();\n+ TextQltyTest.Code := 'TESTTEXT';\n+ TextQltyTest.Description := 'Test Text';\n+ TextQltyTest.\"Test Value Type\" := TextQltyTest.\"Test Value Type\"::\"Value Type Text\";\n+ TextQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to any text value \"A|B|C\"\n+ TextQltyTest.\"Allowable Values\" := 'A|B|C';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for text type)\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to any arbitrary text\n+ TextQltyTest.\"Allowable Values\" := 'any text value';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [GIVEN] A quality test with option type is created\n+ OptionQltyTest.Init();\n+ OptionQltyTest.Code := 'TESTOPT';\n+ OptionQltyTest.Description := 'Test Option';\n+ OptionQltyTest.\"Test Value Type\" := OptionQltyTest.\"Test Value Type\"::\"Value Type Option\";\n+ OptionQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to comma-separated options \"Option1,Option2,Option3\"\n+ OptionQltyTest.\"Allowable Values\" := 'Option1,Option2,Option3';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for option type)\n+ OptionQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+\n local procedure GetTemplateLineConfigFilters(var QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\"; var OutTemplateLineQltyIResultConditConf: Record \"Qlty. I. Result Condit. Conf.\")\n begin\n OutTemplateLineQltyIResultConditConf.SetRange(\"Condition Type\", OutTemplateLineQltyIResultConditConf.\"Condition Type\"::Template);\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8286", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-22T13:07:41Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\nindex dfb07f0502..a005fa7b7c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n@@ -436,7 +436,7 @@ codeunit 99001508 \"Subc. Price Management\"\n \n GetPriceByUOM(SubcontractorPrice, PriceListQty, PriceListCost);\n if PriceListCost <> 0 then begin\n- ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityBase(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n+ ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityForUOM(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n ConvertPriceToCurrency(RequisitionLine.\"Currency Code\", SubcontractorPrice.\"Currency Code\", PriceListCost, DirectCost);\n end;\n RequisitionLine.\"Direct Unit Cost\" := DirectCost;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..73e138fe61 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -3401,6 +3401,77 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.AreEqual('', ToPurchaseHeader.\"Subc. Location Code\", 'Subc. Location Code should not be copied from archive by Copy Document');\n end;\n \n+ [Test]\n+ procedure WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion()\n+ var\n+ Item: Record Item;\n+ ItemUOM: Record \"Item Unit of Measure\";\n+ Vendor: Record Vendor;\n+ WorkCenter: Record \"Work Center\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ SubcPriceManagement: Codeunit \"Subc. Price Management\";\n+ QtyPerSet: Integer;\n+ PriceListUnitCost: Decimal;\n+ begin\n+ // [SCENARIO 636078] Calculate Subcontracts must compute Direct Unit Cost on the Subcontracting\n+ // Worksheet using the per-UoM conversion factor (GetQuantityForUOM()), not the total base\n+ // quantity (GetQuantityBase()) of the order.\n+\n+ // [GIVEN] Item with PCS base UoM and a SET alternative UoM (10 PCS per SET).\n+ Initialize();\n+ LibraryInventory.CreateItem(Item);\n+ QtyPerSet := 10;\n+ LibraryInventory.CreateItemUnitOfMeasureCode(ItemUOM, Item.\"No.\", QtyPerSet);\n+\n+ // [GIVEN] Vendor and Work Center with the vendor as its subcontractor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+ LibraryManufacturing.CreateWorkCenter(WorkCenter);\n+ WorkCenter.Validate(\"Subcontractor No.\", Vendor.\"No.\");\n+ WorkCenter.Modify(true);\n+\n+ // [GIVEN] A subcontractor price in PCS with Minimum Quantity 1 and Direct Unit Cost 1000.\n+ PriceListUnitCost := 1000;\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter.\"No.\", Vendor.\"No.\", Item.\"No.\", '', '', WorkDate(), Item.\"Base Unit of Measure\", 1, '');\n+ SubcontractorPrice.Validate(\"Direct Unit Cost\", PriceListUnitCost);\n+ SubcontractorPrice.Modify(true);\n+\n+ // [GIVEN] A staged Requisition Line for 3 SET (= 30 PCS in base UoM).\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := ItemUOM.Code;\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 3;\n+\n+ // [WHEN] The subcontractor price is applied to the requisition line.\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost = price-list cost * Qty-per-UoM (1000 * 10 = 10000),\n+ // not price-list cost * total base quantity (1000 * 30 = 30000 — the pre-fix behavior).\n+ Assert.AreEqual(\n+ PriceListUnitCost * QtyPerSet, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost on the Subcontracting Worksheet must be derived from Qty. per Unit of Measure, not from total base quantity.');\n+\n+ // [WHEN] The same price is applied to a Requisition Line using the base UoM (no conversion needed).\n+ Clear(RequisitionLine);\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := Item.\"Base Unit of Measure\";\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 30;\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost equals the price-list cost (the same-UoM path is unchanged by the fix).\n+ Assert.AreEqual(\n+ PriceListUnitCost, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost must equal the price-list cost when the worksheet UoM matches the price-list UoM.');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. Subcontracting Test\");\n"} {"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "cbbf3d36fdf3aeeaefa5bd59e13023fbc9f33c9c", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} {"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "1b05b19c9b6ecee6e567858fc839d2342c6a0526", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} From b774cd87740904d3b87c4b3cb7382c806dc5dca0 Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Thu, 4 Jun 2026 13:24:08 +0200 Subject: [PATCH 09/14] change base commits --- dataset/bcbench.jsonl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index 02bdb105a..660b7f7f6 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -100,8 +100,6 @@ {"metadata": {"area": "inventory", "image_count": 7}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-176082", "base_commit": "cb30d50fe1ed2c716c6349370fdc31c6bd0ce956", "created_at": "2024-02-23", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137038, "functionName": ["GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\nindex e0b3ba5f0bf7..ffa98cfbb351 100644\n--- a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n@@ -48,6 +48,7 @@\n UndoneTransLineQtyErr: Label 'Expected Quantity to be 0 after Transfer Shipment was undone';\n DerivedTransLineErr: Label 'Expected no Derived Transfer Line i.e. line with \"Derived From Line No.\" equal to original transfer line.';\n IncorrectSNUndoneErr: Label 'The Serial No. of the item on the transfer shipment line that was undone was different from the SN on the corresponding transfer line.';\n+ ApplToItemEntryErr: Label '%1 must be %2 in %3.', Comment = '%1 is Appl-to Item Entry, %2 is Item Ledger Entry No. and %3 is Transfer Line';\n \n [Test]\n [HandlerFunctions('MessageHandler')]\n@@ -3655,6 +3656,99 @@\n ItemLedgerEntry.TestField(\"Cost Amount (Actual)\", NewCost);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('PostedPurchaseReceiptsModalPageHandler,PostedPurchRcptLinesModalPageHandler')]\n+ procedure GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines()\n+ var\n+ Item: Record Item;\n+ Vendor: Record Vendor;\n+ Location: Record Location;\n+ Location2: Record Location;\n+ Location3: Record Location;\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseHeader2: Record \"Purchase Header\";\n+ PurchaseHeader3: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ PurchaseLine2: Record \"Purchase Line\";\n+ PurchaseLine3: Record \"Purchase Line\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ TransferHeader: Record \"Transfer Header\";\n+ TransferLine: Record \"Transfer Line\";\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ ItemLedgerEntryNo: Integer;\n+ PurchaseReceiptNo: Code[20];\n+ TransferOrder: TestPage \"Transfer Order\";\n+ begin\n+ // [SCENARIO 500597] Get Receipt Lines action on Transfer Order shows list of Posted Purchase Receipts having Transfer-from Code in Location Code of Purch Rcpt Lines and after selecting it populates Appl-to Item Entry field in Transfer Lines.\n+ Initialize();\n+\n+ // [GIVEN] Create an Item and Validate Costing Method.\n+ LibraryInventory.CreateItem(Item);\n+ Item.Validate(\"Costing Method\", Item.\"Costing Method\"::FIFO);\n+ Item.Modify(true);\n+\n+ // [GIVEN] Create two Locations with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location2);\n+\n+ // [GIVEN] Create another Location with Inventory Posting Setup \n+ // And Validate Use As In-Transit.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location3);\n+ Location3.Validate(\"Use As In-Transit\", true);\n+ Location3.Modify(true);\n+\n+ // [GIVEN] Create a Vendor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+\n+ // [GIVEN] Create and Post Purchase Receipt with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader, PurchaseLine, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 2 with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader2, PurchaseLine2, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 3 with Location Code on Line.\n+ PurchaseReceiptNo := CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ PurchaseHeader3,\n+ PurchaseLine3,\n+ Vendor,\n+ Item,\n+ Location);\n+\n+ // [GIVEN] Find and save Item Ledger Entry No. in a Variable.\n+ ItemLedgerEntry.SetRange(\"Document No.\", PurchaseReceiptNo);\n+ ItemLedgerEntry.FindFirst();\n+ ItemLedgerEntryNo := ItemLedgerEntry.\"Entry No.\";\n+\n+ // [GIVEN] Find Purch. Rcpt Line.\n+ FindRandomReceiptLine(PurchaseReceiptNo, PurchRcptLine);\n+\n+ // [GIVEN] Create Transfer Header.\n+ LibraryInventory.CreateTransferHeader(TransferHeader, Location.Code, Location2.Code, Location3.Code);\n+\n+ // [GIVEN] Open Transfer Order page and run Get Receipt Line action.\n+ TransferOrder.OpenEdit();\n+ TransferOrder.GoToRecord(TransferHeader);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchRcptLine.\"No.\");\n+ TransferOrder.GetReceiptLines.Invoke();\n+\n+ // [WHEN] Find Transfer Line.\n+ TransferLine.SetRange(\"Document No.\", TransferHeader.\"No.\");\n+ TransferLine.FindFirst();\n+\n+ // [VERIFY] Appl-to Item Entry and Item Ledger Entry No. are same.\n+ Assert.AreEqual(\n+ ItemLedgerEntryNo,\n+ TransferLine.\"Appl.-to Item Entry\",\n+ StrSubstNo(\n+ ApplToItemEntryErr,\n+ TransferLine.FieldCaption(\"Appl.-to Item Entry\"),\n+ ItemLedgerEntryNo,\n+ TransferLine.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -5168,6 +5262,52 @@\n Assert.AreEqual(LineCount, TransferReceiptLine.Count(), '');\n end;\n \n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchHeader(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location)\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ PurchaseHeader.Validate(\"Location Code\", Location.Code);\n+ PurchaseHeader.Modify(true);\n+\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+ end;\n+\n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location): Code[20]\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Location Code\", Location.Code);\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ exit(LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false));\n+ end;\n+\n [MessageHandler]\n [Scope('OnPrem')]\n procedure MessageHandler(Message: Text[1024])\n@@ -5394,5 +5534,19 @@\n // 0 = Item.Type::Inventory\n Assert.AreEqual('0', ItemList.Filter.GetFilter(\"Type\"), 'Item List contains non-inventory items.');\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure PostedPurchRcptLinesModalPageHandler(var PostedPurchaseReceiptLines: Page \"Posted Purchase Receipt Lines\"; var Response: Action)\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ begin\n+ PurchRcptLine.SetRange(\"Document No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.SetRange(\"No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.FindFirst();\n+ PostedPurchaseReceiptLines.SetRecord(PurchRcptLine);\n+\n+ Response := ACTION::LookupOK;\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\nindex 5fe44b4568d1..c16ab8669925 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n@@ -1304,7 +1304,7 @@ table 5740 \"Transfer Header\"\n TempPurchRcptHeader: Record \"Purch. Rcpt. Header\" temporary;\n PostedPurchaseReceipts: Page \"Posted Purchase Receipts\";\n begin\n- PurchRcptHeader.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ FindPurchRcptHeader(PurchRcptHeader);\n PostedPurchaseReceipts.SetTableView(PurchRcptHeader);\n PostedPurchaseReceipts.LookupMode := true;\n if PostedPurchaseReceipts.RunModal() = ACTION::LookupOK then begin\n@@ -1376,6 +1376,8 @@ table 5740 \"Transfer Header\"\n PurchRcptLine.FilterPstdDocLnItemLedgEntries(ItemLedgerEntry);\n ItemTrackingDocMgt.CopyItemLedgerEntriesToTemp(TempItemLedgerEntry, ItemLedgerEntry);\n ItemTrackingMgt.CopyItemLedgEntryTrkgToTransferLine(TempItemLedgerEntry, TransferLine);\n+ TransferLine.\"Appl.-to Item Entry\" := ItemLedgerEntry.\"Entry No.\";\n+ TransferLine.Modify(true);\n \n OnAfterAddTransferLineFromReceiptLine(TransferLine, PurchRcptLine, TempItemLedgerEntry, Rec);\n end;\n@@ -1546,6 +1548,31 @@ table 5740 \"Transfer Header\"\n end;\n end;\n \n+ local procedure FindPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\")\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ DocumentNo: Code[20];\n+ begin\n+ PurchRcptLine.SetLoadFields(\"Document No.\", \"Location Code\");\n+ PurchRcptLine.SetCurrentKey(\"Document No.\");\n+ PurchRcptLine.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ if PurchRcptLine.FindSet() then\n+ repeat\n+ GetPurchRcptHeader(PurchRcptHeader, PurchRcptLine, DocumentNo);\n+ until PurchRcptLine.Next() = 0;\n+ PurchRcptHeader.MarkedOnly(true);\n+ end;\n+\n+ local procedure GetPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var DocumentNo: Code[20])\n+ begin\n+ if PurchRcptLine.\"Document No.\" = DocumentNo then\n+ exit;\n+\n+ PurchRcptHeader.Get(PurchRcptLine.\"Document No.\");\n+ PurchRcptHeader.Mark(true);\n+ DocumentNo := PurchRcptLine.\"Document No.\";\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnAddTransferLineFromReceiptLineOnBeforeTransferLineInsert(var TransferLine: Record \"Transfer Line\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var TransferHeader: Record \"Transfer Header\")\n begin\n"} {"metadata": {"area": "crm", "image_count": 8}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-174087", "base_commit": "74a0b7c175da3f9a272745bd34453a4712b73e7b", "created_at": "2024-02-02", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\Marketing"], "FAIL_TO_PASS": [{"codeunitID": 136208, "functionName": ["PopulateEvaluationFieldInInteractionLogEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\nindex 4c4c73700d2a..59fff6e2be93 100644\n--- a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n+++ b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n@@ -45,6 +45,7 @@ codeunit 136208 \"Marketing Interaction\"\n LoggedSegemntEntriesCreateMsg: Label 'Logged Segment entry was created';\n AttachmentFileShouldNotBeBlankErr: Label 'Attachment File should not be blank.';\n TxtFileExt: Label 'txt';\n+ EvaluationErr: Label '%1 must be %2 in %3', Comment = '%1 = Evaluation, %2 = Positive, %3 = Interaction Log Entry';\n \n [Test]\n [Scope('OnPrem')]\n@@ -2998,6 +2999,50 @@ codeunit 136208 \"Marketing Interaction\"\n VerifyAttachmentFileIsNotBlankOnInteractionLogEntry(Contact.\"No.\");\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('CreateInteractionFromContactPageHandler')]\n+ procedure PopulateEvaluationFieldInInteractionLogEntry()\n+ var\n+ Contact: Record Contact;\n+ InteractionTemplate: Record \"Interaction Template\";\n+ InteractionLogEntry: Record \"Interaction Log Entry\";\n+ ContactCard: TestPage \"Contact Card\";\n+ InteractionEvaluation: Enum \"Interaction Evaluation\";\n+ begin\n+ // [SCENARIO 498395] When stan creates an Interaction using Create Interaction action from Contact, Evaluation field should be populated in Interaction Log Entry.\n+ Initialize();\n+\n+ // [GIVEN] Create a Contact.\n+ LibraryMarketing.CreateCompanyContact(Contact);\n+\n+ // [GIVEN] Create an Interaction Template and Validate Information Flow.\n+ LibraryMarketing.CreateInteractionTemplate(InteractionTemplate);\n+ InteractionTemplate.Validate(\"Information Flow\", InteractionTemplate.\"Information Flow\"::Outbound);\n+ InteractionTemplate.Modify(true);\n+\n+ // [GIVEN] Open Contact Card and Create Interaction.\n+ ContactCard.OpenEdit();\n+ ContactCard.GoToRecord(Contact);\n+ LibraryVariableStorage.Enqueue(InteractionTemplate.Code);\n+ LibraryVariableStorage.Enqueue(Format(InteractionEvaluation::Positive));\n+ ContactCard.\"Create &Interaction\".Invoke();\n+\n+ // [WHEN] Find Interaction Log Entry.\n+ InteractionLogEntry.SetRange(\"Contact No.\", Contact.\"No.\");\n+ InteractionLogEntry.FindFirst();\n+\n+ // [VERIFY] Interaction Log Entry has Evaluation field populated as Positive.\n+ Assert.AreEqual(\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.Evaluation,\n+ StrSubstNo(\n+ EvaluationErr,\n+ InteractionLogEntry.FieldCaption(Evaluation),\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibrarySales: Codeunit \"Library - Sales\";\n@@ -4309,5 +4354,16 @@ CopyStr(StorageLocation, 1, MaxStrLen(MarketingSetup.\"Attachment Storage Locatio\n CreateInteraction.NextInteraction.Invoke();\n CreateInteraction.Finish.Invoke();\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure CreateInteractionFromContactPageHandler(var CreateInteraction: TestPage \"Create Interaction\")\n+ begin\n+ CreateInteraction.\"Interaction Template Code\".SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.Evaluation.SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.FinishInteraction.Invoke();\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\nindex ff43f4ff6a7b..05a21a6196bf 100644\n--- a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n+++ b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n@@ -694,6 +694,7 @@ page 5077 \"Create Interaction\"\n end;\n Step::\"Step 4\":\n begin\n+ InteractionLogEntry.CopyFromSegment(Rec);\n InteractionLogEntry.Modify();\n CurrPage.Close();\n end;\n"} {"metadata": {"area": "peppol", "image_count": 1}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8059", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-08T09:31:42Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\PEPPOL\\App", "src\\Apps\\W1\\PEPPOL\\Test"], "patch": "diff --git a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\nindex 30f5f792bd..c7981a46fa 100644\n--- a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n@@ -798,6 +798,8 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n InvoiceLineNote := DelChr(Format(SalesLine.Type), '<>');\n InvoicedQuantity := Format(SalesLine.Quantity, 0, 9);\n SalesLineLineAmount := SalesLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesLineLineAmount := Round(SalesLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n InvoiceLineExtensionAmount := Format(SalesLineLineAmount, 0, 9);\n LineExtensionAmountCurrencyID := GetSalesDocCurrencyCode(SalesHeader);\n InvoiceLineAccountingCost := '';\n@@ -869,7 +871,10 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n \n InvLnAllowanceChargeIndicator := 'false';\n InvLnAllowanceChargeReason := LineDisAmtTxt;\n- InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ InvLnAllowanceChargeAmount := Format(Round(SalesLine.\"Line Discount Amount\" / (1 + SalesLine.\"VAT %\" / 100), 0.01), 0, 9)\n+ else\n+ InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n InvLnAllowanceChargeAmtCurrID := GetSalesDocCurrencyCode(SalesHeader);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139235, "functionName": ["LineAmountsConsistentWhenPricesInclVATNoDiscount"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\nindex 36931d56ed..cd237011d5 100644\n--- a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n@@ -3349,6 +3349,68 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual('', CustTaxSchemeID, 'Tax Scheme ID should be empty for Tax Category O.');\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ procedure LineAmountsConsistentWhenPricesInclVATNoDiscount()\n+ var\n+ SalesHeader: Record \"Sales Header\";\n+ SalesLine: Record \"Sales Line\";\n+ Customer: Record Customer;\n+ Item: Record Item;\n+ SalesInvoiceHeader: Record \"Sales Invoice Header\";\n+ SalesInvoiceLine: Record \"Sales Invoice Line\";\n+ PEPPOLLineInfoProvider: Interface \"PEPPOL Line Info Provider\";\n+ InvoiceLineID: Text;\n+ InvoiceLineNote: Text;\n+ InvoicedQuantity: Text;\n+ InvoiceLineExtensionAmount: Text;\n+ LineExtensionAmountCurrencyID: Text;\n+ InvoiceLineAccountingCost: Text;\n+ InvoiceLinePriceAmount: Text;\n+ InvLinePriceAmountCurrencyID: Text;\n+ BaseQuantity: Text;\n+ UnitCode: Text;\n+ PriceAmount: Decimal;\n+ LineExtensionAmt: Decimal;\n+ SalesInvoiceNo: Code[20];\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 630795] PEPPOL LineExtensionAmount equals PriceAmount times Quantity when Prices Including VAT is used\n+ Initialize();\n+\n+ // [GIVEN] Customer \"C\" with PEPPOL identifier\n+ LibrarySales.CreateCustomer(Customer);\n+ AddCustPEPPOLIdentifier(Customer.\"No.\");\n+\n+ // [GIVEN] Sales Invoice for \"C\" with \"Prices Including VAT\" = TRUE and Quantity = 7\n+ CreateItemWithPrice(Item, 139);\n+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader.\"Document Type\"::Invoice, Customer.\"No.\");\n+ SalesHeader.Validate(\"Prices Including VAT\", true);\n+ SalesHeader.Modify(true);\n+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item.\"No.\", 7);\n+\n+ // [WHEN] Post the Sales Invoice and retrieve PEPPOL line amounts\n+ SalesInvoiceNo := LibrarySales.PostSalesDocument(SalesHeader, true, true);\n+ SalesInvoiceHeader.Get(SalesInvoiceNo);\n+ SalesHeader.TransferFields(SalesInvoiceHeader);\n+ FindSalesInvoiceLine(SalesInvoiceLine, SalesInvoiceNo);\n+ SalesLine.TransferFields(SalesInvoiceLine);\n+\n+ PEPPOLLineInfoProvider := GetFormat();\n+ PEPPOLLineInfoProvider.GetLineGeneralInfo(\n+ SalesLine, SalesHeader, InvoiceLineID, InvoiceLineNote, InvoicedQuantity,\n+ InvoiceLineExtensionAmount, LineExtensionAmountCurrencyID, InvoiceLineAccountingCost);\n+ PEPPOLLineInfoProvider.GetLinePriceInfo(\n+ SalesLine, SalesHeader, InvoiceLinePriceAmount, InvLinePriceAmountCurrencyID,\n+ BaseQuantity, UnitCode);\n+\n+ // [THEN] LineExtensionAmount equals PriceAmount times Quantity per PEPPOL BIS 3.0\n+ Evaluate(PriceAmount, InvoiceLinePriceAmount, 9);\n+ Evaluate(LineExtensionAmt, InvoiceLineExtensionAmount, 9);\n+ Assert.AreEqual(PriceAmount * SalesInvoiceLine.Quantity, LineExtensionAmt,\n+ 'LineExtensionAmount must equal PriceAmount * Quantity per PEPPOL BIS 3.0');\n+ end;\n+\n var\n local procedure Initialize()\n var\n@@ -3993,6 +4055,8 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual(UnitOfMeasure.\"International Standard Code\", unitCode, '');\n Assert.AreEqual('UNECERec20', unitCodeListID, '');\n SalesInvoiceLineLineAmount := SalesInvoiceLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesInvoiceLineLineAmount := Round(SalesInvoiceLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n Assert.AreEqual(Format(SalesInvoiceLineLineAmount, 0, 9), InvoiceLineExtensionAmount, '');\n Assert.AreEqual(SalesHeader.\"Currency Code\", LineExtensionAmountCurrencyID, '');\n Assert.AreEqual('', InvoiceLineAccountingCost, '');\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8293", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-25T21:31:15Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\nindex 8d5c75124c..056de67a1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n@@ -15,12 +15,13 @@ using System.Reflection;\n codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n {\n /// \n- /// Opens the Released Production Order page for the production order linked to the given variant record.\n+ /// Opens the appropriate Production Order page (Released or Finished) for the production order linked to the given variant record.\n /// \n /// A record variant of a purchase or transfer document line.\n procedure ShowProductionOrder(RecRelatedVariant: Variant)\n var\n ProductionOrder: Record \"Production Order\";\n+ FinishedProductionOrder: Page \"Finished Production Order\";\n ReleasedProductionOrder: Page \"Released Production Order\";\n OperationNo: Code[10];\n ProdOrderNo: Code[20];\n@@ -29,11 +30,26 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n begin\n if not SetProdOrderInformationByVariant(RecRelatedVariant, ProdOrderNo, ProdOrderLineNo, RoutingNo, OperationNo) then\n exit;\n- ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ProductionOrder.SetFilter(Status, '>=%1', ProductionOrder.Status::Released);\n ProductionOrder.SetRange(\"No.\", ProdOrderNo);\n- ReleasedProductionOrder.SetTableView(ProductionOrder);\n- ReleasedProductionOrder.Editable := false;\n- ReleasedProductionOrder.Run();\n+ if not ProductionOrder.FindFirst() then\n+ exit;\n+ case ProductionOrder.Status of\n+ ProductionOrder.Status::Released:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ReleasedProductionOrder.SetTableView(ProductionOrder);\n+ ReleasedProductionOrder.Editable := false;\n+ ReleasedProductionOrder.Run();\n+ end;\n+ ProductionOrder.Status::Finished:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Finished);\n+ FinishedProductionOrder.SetTableView(ProductionOrder);\n+ FinishedProductionOrder.Editable := false;\n+ FinishedProductionOrder.Run();\n+ end;\n+ end;\n end;\n \n /// \n@@ -77,9 +93,9 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n exit(ProdOrderRoutingLine.Count());\n end;\n \n-local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n+ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n begin\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -130,7 +146,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n begin\n ProdOrderRoutingLine.SetLoadFields(\"Routing Link Code\");\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -138,7 +154,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n if ProdOrderRoutingLine.FindFirst() then\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n \n- ProdOrderComponent.SetRange(Status, ProdOrderComponent.Status::Released);\n+ ProdOrderComponent.SetFilter(Status, '>=%1', ProdOrderComponent.Status::Released);\n ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", ProdOrderLineNo);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ProdOFactboxMgmtShowsDataAfterProdOrderFinished"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 68c7fff2af..c6c56da2b8 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1875,6 +1875,57 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n 'CalcNoOfProductionOrderComponents should return a positive count for an Item Ledger Entry from a subcontracting receipt.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmArchiveOrderHandler,HandlePurchaseOrderPage')]\n+ procedure ProdOFactboxMgmtShowsDataAfterProdOrderFinished()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ SubcWorkCenter: Record \"Work Center\";\n+ SubcProdOFactboxMgmt: Codeunit \"Subc. ProdO. Factbox Mgmt.\";\n+ begin\n+ // [SCENARIO 634953] Subcontracting factbox drilldowns should work after production order is finished.\n+ Initialize();\n+\n+ // [GIVEN] A released production order with a subcontracting routing operation and a subcontracting purchase order\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateItemWithSingleSubcontractingOperation(Item, SubcWorkCenter);\n+ SubcontractingMgmtLibrary.UpdateVendorWithSubcontractingLocationCode(SubcWorkCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", SubcWorkCenter.\"No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", SubcWorkCenter.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [GIVEN] The production order is changed to Finished status\n+ LibraryManufacturing.ChangeProdOrderStatus(ProductionOrder, \"Production Order Status\"::Finished, WorkDate(), true);\n+\n+ // Re-read purchase line (the order still exists because only receipt was posted)\n+ PurchaseLine.FindFirst();\n+\n+ // [WHEN] CalcNoOfProductionOrderRoutings / CalcNoOfProductionOrderComponents are called with the Purchase Line\n+ // [THEN] Both return a positive count even though the production order is now Finished\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderRoutings(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderRoutings should return a positive count after the production order is finished.');\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderComponents(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderComponents should return a positive count after the production order is finished.');\n+ end;\n+\n [Test]\n [HandlerFunctions('ConfirmHandler')]\n procedure RoutingFactboxMgmtFiltersPurchOrderQtyByRoutingReferenceNo()\n@@ -3430,6 +3481,7 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n \n SubSetupLibrary.InitSetupFields();\n LibraryERMCountryData.CreateVATData();\n+ LibraryERMCountryData.UpdateGeneralPostingSetup();\n SubSetupLibrary.InitialSetupForGenProdPostingGroup();\n \n IsInitialized := true;\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8287", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-22T17:02:35Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\nindex b8a5c1d869..c1b2942c55 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n@@ -22,6 +22,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n IsDefaultTextTok: Label '<>''''', Locked = true;\n InvalidDataTypeErr: Label 'The value \"%1\" is not allowed for %2, it is not a %3.', Comment = '%1=the value, %2=field name,%3=field type.';\n NotInAllowableValuesErr: Label 'The value \"%1\" is not allowed for %2, it must be in the range of \"%3\".', Comment = '%1=the value, %2=field name,%3=field type.';\n+ InvalidAllowableValuesFormatErr: Label 'The allowable values \"%1\" are not a valid filter expression for %2 of type %3.', Comment = '%1=the allowable values, %2=field name, %3=field type.';\n \n trigger OnRun()\n var\n@@ -324,6 +325,110 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n ValidateAllowableValuesOnText(TestNameForError, QltyTest.\"Default Value\", QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\", TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// The test whose allowable values expression should be validated.\n+ internal procedure ValidateAllowableValuesFormat(var QltyTest: Record \"Qlty. Test\")\n+ var\n+ TestNameForError: Text;\n+ begin\n+ if QltyTest.Description <> '' then\n+ TestNameForError := QltyTest.Description\n+ else\n+ TestNameForError := QltyTest.Code;\n+\n+ ValidateAllowableValuesFormat(TestNameForError, QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\");\n+ end;\n+\n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// Friendly identifier used in error messages.\n+ /// The allowable values filter expression to validate.\n+ /// The test value type that the filter expression must match.\n+ local procedure ValidateAllowableValuesFormat(NumberOrNameOfTestNameForError: Text; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\")\n+ var\n+ IsValid: Boolean;\n+ begin\n+ if AllowableValues = '' then\n+ exit;\n+\n+ if IsBlankOrEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ if IsAnythingExceptEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ // Allowable values may contain inline expressions like [Field] that are resolved at evaluation time.\n+ // Defer validation until resolution.\n+ if AllowableValues.Contains('[') then\n+ exit;\n+\n+ IsValid := true;\n+ case QltyTestValueType of\n+ QltyTestValueType::\"Value Type Decimal\":\n+ IsValid := TryApplyDecimalFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Integer\":\n+ IsValid := TryApplyIntegerFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Boolean\":\n+ IsValid := TryApplyBooleanFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Date\":\n+ IsValid := TryApplyDateFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type DateTime\":\n+ IsValid := TryApplyDateTimeFilter(AllowableValues);\n+ end;\n+\n+ if not IsValid then\n+ Error(InvalidAllowableValuesFormatErr, AllowableValues, NumberOrNameOfTestNameForError, QltyTestValueType);\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDecimalFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionLine: Record \"Qlty. Inspection Line\" temporary;\n+ begin\n+ TempQltyInspectionLine.SetFilter(\"Derived Numeric Value\", FilterExpression);\n+ if TempQltyInspectionLine.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyIntegerFilter(FilterExpression: Text)\n+ var\n+ TempInteger: Record \"Integer\" temporary;\n+ begin\n+ TempInteger.SetFilter(Number, FilterExpression);\n+ if TempInteger.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyBooleanFilter(FilterExpression: Text)\n+ var\n+ QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n+ begin\n+ // Valid boolean allowable values are: Yes, No, True, False, 1, 0, On, Off (and variations)\n+ if not QltyBooleanParsing.CanTextBeInterpretedAsBooleanIsh(FilterExpression) then\n+ Error(InvalidAllowableValuesFormatErr, FilterExpression, '', 'Boolean');\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateFilter(FilterExpression: Text)\n+ var\n+ TempDateLookupBuffer: Record \"Date Lookup Buffer\" temporary;\n+ begin\n+ TempDateLookupBuffer.SetFilter(\"Period Start\", FilterExpression);\n+ if TempDateLookupBuffer.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateTimeFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionHeader: Record \"Qlty. Inspection Header\" temporary;\n+ begin\n+ TempQltyInspectionHeader.SetFilter(\"Finished Date\", FilterExpression);\n+ if TempQltyInspectionHeader.IsEmpty() then;\n+ end;\n+\n local procedure ValidateAllowableValuesOnText(NumberOrNameOfTestNameForError: Text; var TextToValidate: Text[250]; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\"; var TempBufferQltyTestLookupValue: Record \"Qlty. Test Lookup Value\" temporary; QltyCaseSensitivity: Enum \"Qlty. Case Sensitivity\")\n var\n QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n@@ -393,9 +498,8 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n if not (IsBlankOrEmptyCondition(AllowableValues) and (TextToValidate = '')) then\n if not QltyResultEvaluation.CheckIfValueIsString(TextToValidate, ConvertStr(AllowableValues, ',', '|'), QltyCaseSensitivity) then\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n-\n QltyTestValueType::\"Value Type Option\",\n- QltyTestValueType::\"Value Type Table Lookup\":\n+ QltyTestValueType::\"Value Type Table Lookup\":\n begin\n TextToValidate := CopyStr(TextToValidate.Trim(), 1, MaxStrLen(TextToValidate));\n \n@@ -419,6 +523,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n end;\n end;\n+\n OnAfterValidateAllowableValuesOnText(NumberOrNameOfTestNameForError, TextToValidate, AllowableValues, QltyTestValueType, TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139963, "functionName": ["ValidateAllowableValuesFormat_Boolean_ValidFormats", "ValidateAllowableValuesFormat_NonValidatedTypes", "ValidateAllowableValuesFormat_Boolean_InvalidFormats", "ValidateAllowableValuesFormat_DateTime_InvalidFormats", "ValidateAllowableValuesFormat_Integer_ValidFormats", "ValidateAllowableValuesFormat_Integer_InvalidFormats", "ValidateAllowableValuesFormat_Date_InvalidFormats", "ValidateAllowableValuesFormat_Decimal_ValidFormats", "ValidateAllowableValuesFormat_Date_ValidFormats", "ValidateAllowableValuesFormat_DateTime_ValidFormats", "ValidateAllowableValuesFormat_Decimal_InvalidFormats"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\nindex 9f4cbf3006..66e4c203fc 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n@@ -54,8 +54,11 @@ table 20401 \"Qlty. Test\"\n {\n Caption = 'Allowable Values';\n ToolTip = 'Specifies an expression for the range of values you can enter or select for the Test. Depending on the Test Value Type, the expression format varies. For example if you want a measurement such as a percentage that collects between 0 and 100 you would enter 0..100. This is not the pass or acceptable condition, these are just the technically possible values that the inspector can enter. You would then enter a passing condition in your result conditions. If you had a result of Pass being 80 to 100, you would then configure 80..100 for that result.';\n+\n trigger OnValidate()\n begin\n+ Rec.ValidateAllowableValuesFormat();\n+\n if Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Option\", Rec.\"Test Value Type\"::\"Value Type Table Lookup\"] then\n Rec.\"Allowable Values\" := CopyStr(Rec.\"Allowable Values\".Replace(', ', ','), 1, MaxStrLen(Rec.\"Allowable Values\"));\n end;\n@@ -472,6 +475,16 @@ table 20401 \"Qlty. Test\"\n QltyResultEvaluation.ValidateAllowableValuesOnTest(Rec);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the test value type.\n+ /// \n+ procedure ValidateAllowableValuesFormat()\n+ var\n+ QltyResultEvaluation: Codeunit \"Qlty. Result Evaluation\";\n+ begin\n+ QltyResultEvaluation.ValidateAllowableValuesFormat(Rec);\n+ end;\n+\n /// \n /// Code = the unique code\n /// Description = raw description.\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\nindex 91159fca6e..05f7d8a17a 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n@@ -2071,6 +2071,440 @@ codeunit 139963 \"Qlty. Tests - Result Eval.\"\n LibraryAssert.ExpectedError(StrSubstNo(Expected4Err, OptionListQltyInspectionLine.\"Test Code\"));\n end;\n \n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_ValidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC';\n+ DecimalQltyTest.Description := 'Test Decimal';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ DecimalQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ DecimalQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25.5\"\n+ DecimalQltyTest.\"Allowable Values\" := '25.5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"10|20|30\"\n+ DecimalQltyTest.\"Allowable Values\" := '10|20|30';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DecimalQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to not empty condition \"<>''\"\n+ DecimalQltyTest.\"Allowable Values\" := '<>''''';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_InvalidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC2';\n+ DecimalQltyTest.Description := 'Test Decimal Invalid';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a number\"\n+ DecimalQltyTest.\"Allowable Values\" := 'not a number';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid operator \"==5\"\n+ DecimalQltyTest.\"Allowable Values\" := '==5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_ValidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT';\n+ IntegerQltyTest.Description := 'Test Integer';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ IntegerQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ IntegerQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ IntegerQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25\"\n+ IntegerQltyTest.\"Allowable Values\" := '25';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"1|2|3|4|5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1|2|3|4|5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ IntegerQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ IntegerQltyTest.\"Allowable Values\" := '1..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_InvalidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT2';\n+ IntegerQltyTest.Description := 'Test Integer Invalid';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to decimal value \"1.5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1.5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not an integer\"\n+ IntegerQltyTest.\"Allowable Values\" := 'not an integer';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_ValidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE';\n+ DateQltyTest.Description := 'Test Date';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact date \"2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to date range \"2024-01-01..2024-12-31\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01..2024-12-31';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than date \">2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '>2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateQltyTest.\"Allowable Values\" := '>[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_InvalidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE2';\n+ DateQltyTest.Description := 'Test Date Invalid';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid date \"99/99/9999\"\n+ DateQltyTest.\"Allowable Values\" := '99/99/9999';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a date\"\n+ DateQltyTest.\"Allowable Values\" := 'not a date';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_ValidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT';\n+ DateTimeQltyTest.Description := 'Test DateTime';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact datetime \"2024-01-01 10:30:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 10:30:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to datetime range \"2024-01-01 00:00:00..2024-12-31 23:59:59\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 00:00:00..2024-12-31 23:59:59';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than datetime \">2024-01-01 10:00:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '>2024-01-01 10:00:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateTimeQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateTimeQltyTest.\"Allowable Values\" := '<[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_InvalidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT2';\n+ DateTimeQltyTest.Description := 'Test DateTime Invalid';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid datetime \"99/99/9999 99:99:99\"\n+ DateTimeQltyTest.\"Allowable Values\" := '99/99/9999 99:99:99';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a datetime\"\n+ DateTimeQltyTest.\"Allowable Values\" := 'not a datetime';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_ValidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL';\n+ BooleanQltyTest.Description := 'Test Boolean';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to \"Yes\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Yes';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"No\"\n+ BooleanQltyTest.\"Allowable Values\" := 'No';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"True\"\n+ BooleanQltyTest.\"Allowable Values\" := 'True';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"False\"\n+ BooleanQltyTest.\"Allowable Values\" := 'False';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"1\"\n+ BooleanQltyTest.\"Allowable Values\" := '1';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"0\"\n+ BooleanQltyTest.\"Allowable Values\" := '0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"On\"\n+ BooleanQltyTest.\"Allowable Values\" := 'On';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"Off\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Off';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"Y\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Y';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"N\"\n+ BooleanQltyTest.\"Allowable Values\" := 'N';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ BooleanQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ BooleanQltyTest.\"Allowable Values\" := '[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_InvalidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL2';\n+ BooleanQltyTest.Description := 'Test Boolean Invalid';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"Maybe\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Maybe';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid number \"2\"\n+ BooleanQltyTest.\"Allowable Values\" := '2';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a boolean\"\n+ BooleanQltyTest.\"Allowable Values\" := 'not a boolean';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"abc\"\n+ BooleanQltyTest.\"Allowable Values\" := 'abc';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_NonValidatedTypes()\n+ var\n+ TextQltyTest: Record \"Qlty. Test\";\n+ OptionQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat does not validate non-numeric/non-date types\n+\n+ // [GIVEN] A quality test with text type is created\n+ TextQltyTest.Init();\n+ TextQltyTest.Code := 'TESTTEXT';\n+ TextQltyTest.Description := 'Test Text';\n+ TextQltyTest.\"Test Value Type\" := TextQltyTest.\"Test Value Type\"::\"Value Type Text\";\n+ TextQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to any text value \"A|B|C\"\n+ TextQltyTest.\"Allowable Values\" := 'A|B|C';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for text type)\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to any arbitrary text\n+ TextQltyTest.\"Allowable Values\" := 'any text value';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [GIVEN] A quality test with option type is created\n+ OptionQltyTest.Init();\n+ OptionQltyTest.Code := 'TESTOPT';\n+ OptionQltyTest.Description := 'Test Option';\n+ OptionQltyTest.\"Test Value Type\" := OptionQltyTest.\"Test Value Type\"::\"Value Type Option\";\n+ OptionQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to comma-separated options \"Option1,Option2,Option3\"\n+ OptionQltyTest.\"Allowable Values\" := 'Option1,Option2,Option3';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for option type)\n+ OptionQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+\n local procedure GetTemplateLineConfigFilters(var QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\"; var OutTemplateLineQltyIResultConditConf: Record \"Qlty. I. Result Condit. Conf.\")\n begin\n OutTemplateLineQltyIResultConditConf.SetRange(\"Condition Type\", OutTemplateLineQltyIResultConditConf.\"Condition Type\"::Template);\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8286", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-22T13:07:41Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\nindex dfb07f0502..a005fa7b7c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n@@ -436,7 +436,7 @@ codeunit 99001508 \"Subc. Price Management\"\n \n GetPriceByUOM(SubcontractorPrice, PriceListQty, PriceListCost);\n if PriceListCost <> 0 then begin\n- ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityBase(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n+ ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityForUOM(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n ConvertPriceToCurrency(RequisitionLine.\"Currency Code\", SubcontractorPrice.\"Currency Code\", PriceListCost, DirectCost);\n end;\n RequisitionLine.\"Direct Unit Cost\" := DirectCost;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..73e138fe61 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -3401,6 +3401,77 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.AreEqual('', ToPurchaseHeader.\"Subc. Location Code\", 'Subc. Location Code should not be copied from archive by Copy Document');\n end;\n \n+ [Test]\n+ procedure WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion()\n+ var\n+ Item: Record Item;\n+ ItemUOM: Record \"Item Unit of Measure\";\n+ Vendor: Record Vendor;\n+ WorkCenter: Record \"Work Center\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ SubcPriceManagement: Codeunit \"Subc. Price Management\";\n+ QtyPerSet: Integer;\n+ PriceListUnitCost: Decimal;\n+ begin\n+ // [SCENARIO 636078] Calculate Subcontracts must compute Direct Unit Cost on the Subcontracting\n+ // Worksheet using the per-UoM conversion factor (GetQuantityForUOM()), not the total base\n+ // quantity (GetQuantityBase()) of the order.\n+\n+ // [GIVEN] Item with PCS base UoM and a SET alternative UoM (10 PCS per SET).\n+ Initialize();\n+ LibraryInventory.CreateItem(Item);\n+ QtyPerSet := 10;\n+ LibraryInventory.CreateItemUnitOfMeasureCode(ItemUOM, Item.\"No.\", QtyPerSet);\n+\n+ // [GIVEN] Vendor and Work Center with the vendor as its subcontractor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+ LibraryManufacturing.CreateWorkCenter(WorkCenter);\n+ WorkCenter.Validate(\"Subcontractor No.\", Vendor.\"No.\");\n+ WorkCenter.Modify(true);\n+\n+ // [GIVEN] A subcontractor price in PCS with Minimum Quantity 1 and Direct Unit Cost 1000.\n+ PriceListUnitCost := 1000;\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter.\"No.\", Vendor.\"No.\", Item.\"No.\", '', '', WorkDate(), Item.\"Base Unit of Measure\", 1, '');\n+ SubcontractorPrice.Validate(\"Direct Unit Cost\", PriceListUnitCost);\n+ SubcontractorPrice.Modify(true);\n+\n+ // [GIVEN] A staged Requisition Line for 3 SET (= 30 PCS in base UoM).\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := ItemUOM.Code;\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 3;\n+\n+ // [WHEN] The subcontractor price is applied to the requisition line.\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost = price-list cost * Qty-per-UoM (1000 * 10 = 10000),\n+ // not price-list cost * total base quantity (1000 * 30 = 30000 — the pre-fix behavior).\n+ Assert.AreEqual(\n+ PriceListUnitCost * QtyPerSet, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost on the Subcontracting Worksheet must be derived from Qty. per Unit of Measure, not from total base quantity.');\n+\n+ // [WHEN] The same price is applied to a Requisition Line using the base UoM (no conversion needed).\n+ Clear(RequisitionLine);\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := Item.\"Base Unit of Measure\";\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 30;\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost equals the price-list cost (the same-UoM path is unchanged by the fix).\n+ Assert.AreEqual(\n+ PriceListUnitCost, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost must equal the price-list cost when the worksheet UoM matches the price-list UoM.');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. Subcontracting Test\");\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8253", "base_commit": "cbbf3d36fdf3aeeaefa5bd59e13023fbc9f33c9c", "created_at": "2026-05-20T16:06:34Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\nindex ab1268332e..bb36b3cb75 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcCalcSubcontractsExt.Codeunit.al\n@@ -21,5 +21,7 @@ codeunit 99001529 \"Subc. Calc Subcontracts Ext.\"\n if WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\") then\n RequisitionLine.\"Description 2\" := WorkCenter.\"Name 2\";\n end;\n+\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex c60b6c3aaf..5086568503 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -552,6 +552,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n+ RequisitionLine.Validate(\"Subc. Standard Task Code\", ProdOrderRoutingLine.\"Standard Task Code\");\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\nindex a629087345..1440ebbf11 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcSubcontractingWorksheet.Page.al\n@@ -242,7 +242,6 @@ page 99001504 \"Subc. Subcontracting Worksheet\"\n field(\"Subc. Standard Task Code\"; Rec.\"Subc. Standard Task Code\")\n {\n ApplicationArea = Manufacturing;\n- Editable = false;\n }\n field(\"Subc. Pricelist Cost\"; Rec.\"Subc. Pricelist Cost\")\n {\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["StandardTaskCodePropagatedAndDrivesSubcPriceLookup"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..bab0c01d8c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2909,6 +2909,187 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionLineWithStdTask: Record \"Requisition Line\";\n+ RequisitionLineNoStdTask: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ StandardTask: Record \"Standard Task\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ Vendor: Record Vendor;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ CarryOutActionMsgReq: Report \"Carry Out Action Msg. - Req.\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ PriceWithoutStdTask: Decimal;\n+ PriceWithStdTask: Decimal;\n+ SecondOperationNo: Code[10];\n+ begin\n+ // [SCENARIO 633226] Standard Task Code propagates from Routing → Prod. Order Routing → Subcontracting Worksheet,\n+ // is editable on the worksheet, and drives Subcontractor Price lookup. Editing or clearing it on a worksheet\n+ // line re-applies the matching subcontractor price; carrying out creates Purchase Lines with the correct unit costs.\n+\n+ Initialize();\n+\n+ // [GIVEN] Subcontracting setup with a worksheet template\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] Work centers and a manufacturing item with routing and BOM\n+ // (helper creates one subcontracting routing line on WorkCenter[2] without a Standard Task)\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+\n+ // [GIVEN] A standard task code\n+ LibraryManufacturing.CreateStandardTask(StandardTask);\n+\n+ // [GIVEN] A second subcontracting routing line on the same work center, with the standard task assigned\n+ SecondOperationNo := AddSubcRoutingLineWithStandardTask(Item.\"Routing No.\", WorkCenter[2].\"No.\", StandardTask.Code);\n+\n+ // [GIVEN] Two subcontractor prices for the item / work center / vendor:\n+ // - PriceWithoutStdTask, with no Standard Task Code\n+ // - PriceWithStdTask = 2 * PriceWithoutStdTask, tied to StandardTask.Code\n+ Vendor.Get(WorkCenter[2].\"Subcontractor No.\");\n+ PriceWithoutStdTask := LibraryRandom.RandIntInRange(50, 200);\n+ PriceWithStdTask := PriceWithoutStdTask * 2;\n+\n+ SubcontractorPrice.Reset();\n+ SubcontractorPrice.SetRange(\"Vendor No.\", Vendor.\"No.\");\n+ SubcontractorPrice.SetRange(\"Item No.\", Item.\"No.\");\n+ SubcontractorPrice.DeleteAll();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", '', '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithoutStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ Clear(SubcontractorPrice);\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter[2].\"No.\", Vendor.\"No.\", Item.\"No.\", StandardTask.Code, '',\n+ WorkDate(), Item.\"Base Unit of Measure\", 0, Vendor.\"Currency Code\");\n+ SubcontractorPrice.\"Direct Unit Cost\" := PriceWithStdTask;\n+ SubcontractorPrice.Modify();\n+\n+ // [GIVEN] A released production order\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [THEN] Standard Task Code is propagated from Routing Line to Prod. Order Routing Line on the second operation\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ ProdOrderRoutingLine.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, ProdOrderRoutingLine.\"Standard Task Code\",\n+ 'Standard Task Code must be propagated from Routing Line to Prod. Order Routing Line.');\n+\n+ // [GIVEN] An empty subcontracting worksheet\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts is run on the worksheet\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] On the worksheet line for the operation with a standard task, Standard Task Code is populated\n+ // and the standard-task-bound price is applied\n+ RequisitionLineWithStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineWithStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineWithStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineWithStdTask.SetRange(\"Operation No.\", SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineWithStdTask.FindFirst();\n+ Assert.AreEqual(\n+ StandardTask.Code, RequisitionLineWithStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be propagated from Prod. Order Routing Line to the Subcontracting Worksheet line.');\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price tied to the Standard Task Code must be applied to the worksheet line.');\n+\n+ // [THEN] On the worksheet line for the operation without a standard task, the un-tagged subcontractor price is applied\n+ RequisitionLineNoStdTask.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLineNoStdTask.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLineNoStdTask.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ RequisitionLineNoStdTask.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+#pragma warning restore AA0210\n+ RequisitionLineNoStdTask.FindFirst();\n+ Assert.AreEqual(\n+ '', RequisitionLineNoStdTask.\"Subc. Standard Task Code\",\n+ 'Standard Task Code must be empty on the worksheet line that has no standard task on the routing.');\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineNoStdTask.\"Direct Unit Cost\",\n+ 'Subcontractor Price for the un-tagged combination must be applied to the worksheet line.');\n+\n+ // [WHEN] User clears Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", '');\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost falls back to the un-tagged subcontractor price\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Clearing Standard Task Code on the worksheet line must re-apply the un-tagged subcontractor price.');\n+\n+ // [WHEN] User re-sets Standard Task Code on the worksheet line\n+ RequisitionLineWithStdTask.Validate(\"Subc. Standard Task Code\", StandardTask.Code);\n+ RequisitionLineWithStdTask.Modify(true);\n+\n+ // [THEN] Direct Unit Cost is restored to the standard-task-bound subcontractor price\n+ Assert.AreEqual(\n+ PriceWithStdTask, RequisitionLineWithStdTask.\"Direct Unit Cost\",\n+ 'Re-setting Standard Task Code on the worksheet line must re-apply the standard-task-bound subcontractor price.');\n+\n+ // [WHEN] Carry Out Action Message creates the Subcontracting Purchase Order from the worksheet\n+ Clear(RequisitionLine);\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+ CarryOutActionMsgReq.SetReqWkshLine(RequisitionLine);\n+ CarryOutActionMsgReq.UseRequestPage(false);\n+ CarryOutActionMsgReq.RunModal();\n+\n+ // [THEN] The purchase line for the operation with a standard task has Direct Unit Cost = PriceWithStdTask\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", Item.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.SetRange(\"Operation No.\", SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation with a standard task must use the standard-task-bound subcontractor price.');\n+\n+ // [THEN] The purchase line for the operation without a standard task has Direct Unit Cost = PriceWithoutStdTask\n+ PurchaseLine.SetFilter(\"Operation No.\", '<>%1', SecondOperationNo);\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ PriceWithoutStdTask, PurchaseLine.\"Direct Unit Cost\",\n+ 'Subcontracting Purchase Line for the operation without a standard task must use the un-tagged subcontractor price.');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\n@@ -3254,6 +3435,45 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n WorkCenterNo := WorkCenter.\"No.\";\n end;\n \n+ local procedure AddSubcRoutingLineWithStandardTask(RoutingNo: Code[20]; WorkCenterNo: Code[20]; StandardTaskCode: Code[10]) NewOperationNo: Code[10]\n+ var\n+ CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+#pragma warning disable AA0210\n+ CapacityUnitOfMeasure.SetRange(Type, CapacityUnitOfMeasure.Type::Minutes);\n+#pragma warning restore AA0210\n+ CapacityUnitOfMeasure.FindFirst();\n+\n+ RoutingHeader.Get(RoutingNo);\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::New);\n+ RoutingHeader.Modify(true);\n+\n+ // Use a number larger than any existing operation so the certification-time ordering check is satisfied.\n+ NewOperationNo := CopyStr(IncStr(FindLastRoutingOperationNo(RoutingNo)), 1, MaxStrLen(NewOperationNo));\n+\n+ LibraryManufacturing.CreateRoutingLineSetup(\n+ RoutingLine, RoutingHeader, WorkCenterNo, NewOperationNo,\n+ LibraryRandom.RandInt(5), LibraryRandom.RandInt(5));\n+ RoutingLine.Validate(\"Run Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Setup Time Unit of Meas. Code\", CapacityUnitOfMeasure.Code);\n+ RoutingLine.Validate(\"Standard Task Code\", StandardTaskCode);\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+ end;\n+\n+ local procedure FindLastRoutingOperationNo(RoutingNo: Code[20]): Code[10]\n+ var\n+ RoutingLine: Record \"Routing Line\";\n+ begin\n+ RoutingLine.SetRange(\"Routing No.\", RoutingNo);\n+ RoutingLine.FindLast();\n+ exit(RoutingLine.\"Operation No.\");\n+ end;\n+\n local procedure CreateSubcontractingPurchOrderPostAndGetPurchRcptLine(var PurchRcptLine: Record \"Purch. Rcpt. Line\")\n var\n Item: Record Item;\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-7831", "base_commit": "1b05b19c9b6ecee6e567858fc839d2342c6a0526", "created_at": "2026-04-23T09:08:53Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex 32bc174557..ab8da0371c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -351,7 +351,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n begin\n GetSubmanagementSetup();\n \n- Item.SetLoadFields(\"Item Category Code\", \"Description 2\");\n+ Item.SetLoadFields(\"Item Category Code\");\n Item.Get(ProdOrderComponent.\"Item No.\");\n \n PurchaseLine.Init();\n@@ -385,7 +385,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n end;\n \n PurchaseLine.Description := ProdOrderComponent.Description;\n- PurchaseLine.\"Description 2\" := Item.\"Description 2\";\n+ PurchaseLine.\"Description 2\" := ProdOrderComponent.\"Description 2\";\n \n PurchaseLine.\"Sales Order No.\" := RequisitionLine.\"Sales Order No.\";\n PurchaseLine.\"Sales Order Line No.\" := RequisitionLine.\"Sales Order Line No.\";\n@@ -471,7 +471,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n RequisitionLine.Validate(\"Vendor No.\", WorkCenter.\"Subcontractor No.\");\n \n RequisitionLine.Description := ProdOrderRoutingLine.Description;\n- RequisitionLine.\"Description 2\" := '';\n+ RequisitionLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n SetVendorItemNo(RequisitionLine);\n \n if PurchLineExists(PurchaseLine, ProdOrderLine, ProdOrderRoutingLine) then begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\nindex 1ac46f1b37..ce5d8f339f 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pages/SubcProdOrderComponents.Page.al\n@@ -39,6 +39,11 @@ page 99001503 \"Subc. Prod. Order Components\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ToolTip = 'Specifies a second description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored. Copies the location code from the corresponding field on the production order line.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\nindex 8f992dca5e..e7a9bcd8ea 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcCreateProdOrdOpt.Codeunit.al\n@@ -479,7 +479,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n /// \n local procedure FindRoutingLinesForProdOrderLine(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n begin\n- ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Routing No.\", \"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Work Center No.\", \"Operation No.\", Description, \"Description 2\", \"Routing No.\", \"Routing Reference No.\");\n ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n ProdOrderRoutingLine.SetRange(\"Routing No.\", ProdOrderLine.\"Routing No.\");\n@@ -525,6 +525,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n SubcPriceManagement: Codeunit \"Subc. Price Management\";\n begin\n PurchaseLine.Description := ProdOrderRoutingLine.Description;\n+ PurchaseLine.\"Description 2\" := ProdOrderRoutingLine.\"Description 2\";\n PurchaseLine.\"Routing No.\" := ProdOrderRoutingLine.\"Routing No.\";\n PurchaseLine.\"Routing Reference No.\" := ProdOrderRoutingLine.\"Routing Reference No.\";\n PurchaseLine.\"Operation No.\" := ProdOrderRoutingLine.\"Operation No.\";\n@@ -817,6 +818,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProductionBOMHeader.Init();\n ProductionBOMHeader.\"No.\" := BOMNo;\n ProductionBOMHeader.Description := TempProductionBOMHeader.Description;\n+ ProductionBOMHeader.\"Description 2\" := TempProductionBOMHeader.\"Description 2\";\n ProductionBOMHeader.Validate(\"Unit of Measure Code\", TempProductionBOMHeader.\"Unit of Measure Code\");\n ProductionBOMHeader.Insert(true);\n BOMCreated := true;\n@@ -871,6 +873,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n RoutingHeader.Init();\n RoutingHeader.\"No.\" := RoutingNo;\n RoutingHeader.Description := TempRoutingHeader.Description;\n+ RoutingHeader.\"Description 2\" := TempRoutingHeader.\"Description 2\";\n RoutingHeader.Insert(true);\n RoutingCreated := true;\n \n@@ -1154,6 +1157,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderComponent.Validate(\"Item No.\", TempProdOrderComponent.\"Item No.\");\n ProdOrderComponent.Validate(\"Variant Code\", TempProdOrderComponent.\"Variant Code\");\n ProdOrderComponent.Description := TempProdOrderComponent.Description;\n+ ProdOrderComponent.\"Description 2\" := TempProdOrderComponent.\"Description 2\";\n ProdOrderComponent.Validate(\"Quantity per\", TempProdOrderComponent.\"Quantity per\");\n ProdOrderComponent.Validate(\"Unit of Measure Code\", TempProdOrderComponent.\"Unit of Measure Code\");\n ProdOrderComponent.Validate(\"Location Code\", TempProdOrderComponent.\"Location Code\");\n@@ -1185,6 +1189,7 @@ codeunit 99001556 \"Subc. Create Prod. Ord. Opt.\"\n ProdOrderRoutingLine.Validate(Type, TempProdOrderRoutingLine.Type);\n ProdOrderRoutingLine.Validate(\"No.\", TempProdOrderRoutingLine.\"No.\");\n ProdOrderRoutingLine.Description := TempProdOrderRoutingLine.Description;\n+ ProdOrderRoutingLine.\"Description 2\" := TempProdOrderRoutingLine.\"Description 2\";\n ProdOrderRoutingLine.\"Setup Time\" := TempProdOrderRoutingLine.\"Setup Time\";\n ProdOrderRoutingLine.\"Run Time\" := TempProdOrderRoutingLine.\"Run Time\";\n ProdOrderRoutingLine.\"Wait Time\" := TempProdOrderRoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\nindex 9b4c3f20cd..ec673473a8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Codeunits/SubcTempDataInitializer.Codeunit.al\n@@ -320,6 +320,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderComponent.\"Qty. per Unit of Measure\" := 1;\n TempGlobalProdOrderComponent.Validate(\"Item No.\", ProductionBOMLine.\"No.\");\n TempGlobalProdOrderComponent.Description := ProductionBOMLine.Description;\n+ TempGlobalProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n TempGlobalProdOrderComponent.Validate(\"Quantity per\", ProductionBOMLine.\"Quantity per\" * BOMQuantity);\n if ProductionBOMLine.\"Unit of Measure Code\" <> '' then\n TempGlobalProdOrderComponent.Validate(\"Unit of Measure Code\", ProductionBOMLine.\"Unit of Measure Code\");\n@@ -361,6 +362,7 @@ codeunit 99001552 \"Subc. Temp Data Initializer\"\n TempGlobalProdOrderRoutingLine.Validate(\"No.\", RoutingLine.\"No.\");\n TempGlobalProdOrderRoutingLine.Validate(\"Work Center No.\", RoutingLine.\"Work Center No.\");\n TempGlobalProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempGlobalProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempGlobalProdOrderRoutingLine.Validate(\"Setup Time\", RoutingLine.\"Setup Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Run Time\", RoutingLine.\"Run Time\");\n TempGlobalProdOrderRoutingLine.Validate(\"Wait Time\", RoutingLine.\"Wait Time\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\nindex b1559d1e61..b79da5c878 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcPurchProvisionWizard.Page.al\n@@ -66,6 +66,13 @@ page 99001505 \"Subc. PurchProvisionWizard\"\n Editable = false;\n ToolTip = 'Specifies the description of the item for which the purchase provision is being set up.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ Caption = 'Description 2';\n+ Editable = false;\n+ ToolTip = 'Specifies additional description of the item for which the purchase provision is being set up.';\n+ Visible = false;\n+ }\n group(BomRoutingTransfer)\n {\n Caption = 'BOM/Routing Transfer';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\nindex c9828740d7..3045463c27 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempBOMLines.Page.al\n@@ -41,6 +41,12 @@ page 99001506 \"Subc. Temp BOM Lines\"\n {\n ToolTip = 'Specifies a description of the item or resource.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item or resource.';\n+ Visible = false;\n+ }\n field(\"Quantity per\"; Rec.\"Quantity per\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\nindex 53edbc0781..0f07ddbe24 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrdRtngLines.Page.al\n@@ -39,6 +39,12 @@ page 99001509 \"Subc. TempProdOrdRtngLines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\nindex 43f9d2df51..6b53788fee 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempProdOrderComp.Page.al\n@@ -44,6 +44,12 @@ page 99001508 \"Subc. Temp Prod Order Comp\"\n {\n ToolTip = 'Specifies a description of the item on the line.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the item on the line.';\n+ Visible = false;\n+ }\n field(\"Location Code\"; Rec.\"Location Code\")\n {\n ToolTip = 'Specifies the location where the component is stored.';\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\nindex 7ae9ebd48c..758f7bacf8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Prod Order Creation Wizard/Pages/SubcTempRoutingLines.Page.al\n@@ -39,6 +39,12 @@ page 99001507 \"Subc. Temp Routing Lines\"\n {\n ToolTip = 'Specifies a description of the operation.';\n }\n+ field(\"Description 2\"; Rec.\"Description 2\")\n+ {\n+ ApplicationArea = Manufacturing;\n+ ToolTip = 'Specifies additional description of the operation.';\n+ Visible = false;\n+ }\n field(\"Setup Time\"; Rec.\"Setup Time\")\n {\n AutoFormatType = 0;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["Description2CopiedFromProdOrderComponentToPurchaseLine", "Description2PopulatedOnRequisitionLineFromCalculateSubcontracts"]}, {"codeunitID": 139993, "functionName": ["TestWizardPreservesDescription2ThroughBOMAndRoutingLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\nindex e7a154f191..3ce9cdaf20 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcCreateProdOrdWizLibrary.Codeunit.al\n@@ -279,4 +279,59 @@ codeunit 139986 \"Subc. CreateProdOrdWizLibrary\"\n RoutingVersion.Validate(Status, RoutingVersion.Status::Certified);\n RoutingVersion.Modify(true);\n end;\n+\n+ procedure CreateBOMWithDescription2(var BOMLineDescription2: Text[50]): Code[20]\n+ var\n+ ComponentItem: Record Item;\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ begin\n+ // Create a BOM with a single line that has Description 2 set\n+ LibraryInventory.CreateItem(ComponentItem);\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ComponentItem.\"Base Unit of Measure\");\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader, ProductionBOMLine, '', ProductionBOMLine.Type::Item, ComponentItem.\"No.\", 1);\n+ BOMLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(ProductionBOMLine.\"Description 2\")), 1, MaxStrLen(ProductionBOMLine.\"Description 2\"));\n+ ProductionBOMLine.\"Description 2\" := BOMLineDescription2;\n+ ProductionBOMLine.Modify();\n+ ProductionBOMHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ ProductionBOMHeader.Validate(Status, ProductionBOMHeader.Status::Certified);\n+ ProductionBOMHeader.Modify(true);\n+ exit(ProductionBOMHeader.\"No.\");\n+ end;\n+\n+ procedure CreateRoutingWithSubcWorkCenterAndDescription2(var SubcWorkCenterNo: Code[20]; var RoutingLineDescription2: Text[50]): Code[20]\n+ var\n+ RoutingHeader: Record \"Routing Header\";\n+ RoutingLine: Record \"Routing Line\";\n+ WorkCenter1: Record \"Work Center\";\n+ WorkCenter2: Record \"Work Center\";\n+ begin\n+ // Create a routing with two lines; the second work center is subcontracting and has Description 2 set\n+ CreateAndCalculateNeededWorkCenter(WorkCenter1, false);\n+ CreateAndCalculateNeededWorkCenter(WorkCenter2, true);\n+ SubcWorkCenterNo := WorkCenter2.\"No.\";\n+\n+ LibraryManufacturing.CreateRoutingHeader(RoutingHeader, RoutingHeader.Type::Serial);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '10', RoutingLine.Type::\"Work Center\", WorkCenter1.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 10);\n+ RoutingLine.Validate(\"Run Time\", 5);\n+ RoutingLine.Modify(true);\n+\n+ LibraryManufacturing.CreateRoutingLine(\n+ RoutingHeader, RoutingLine, '', '20', RoutingLine.Type::\"Work Center\", WorkCenter2.\"No.\");\n+ RoutingLine.Validate(\"Setup Time\", 15);\n+ RoutingLine.Validate(\"Run Time\", 8);\n+ RoutingLineDescription2 := CopyStr(LibraryRandom.RandText(MaxStrLen(RoutingLine.\"Description 2\")), 1, MaxStrLen(RoutingLine.\"Description 2\"));\n+ RoutingLine.\"Description 2\" := RoutingLineDescription2;\n+ RoutingLine.Modify(true);\n+\n+ RoutingHeader.Validate(\"Version Nos.\", LibraryERM.CreateNoSeriesCode());\n+ RoutingHeader.Validate(Status, RoutingHeader.Status::Certified);\n+ RoutingHeader.Modify(true);\n+\n+ exit(RoutingHeader.\"No.\");\n+ end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\nindex 33515efda1..333242db94 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Libraries/SubcProdOrderCheckLib.Codeunit.al\n@@ -19,6 +19,8 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n var\n Assert: Codeunit Assert;\n ProdOrderRefreshed: Boolean;\n+ Description2MismatchOnLineLbl: Label 'Description 2 mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n+ Description2MismatchOnOperationLbl: Label 'Description 2 mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DescriptionMismatchOnOperationLbl: Label 'Description mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DirectUnitCostMismatchOnOperationLbl: Label 'Direct Unit Cost mismatch on Operation %1. Expected: %2, Actual: %3', Locked = true;\n DueDateMismatchOnLineLbl: Label 'Due Date mismatch on Line %1. Expected: %2, Actual: %3', Locked = true;\n@@ -184,6 +186,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempComponent.\"Due Date\", ActualComponent.\"Due Date\",\n StrSubstNo(DueDateMismatchOnLineLbl,\n TempComponent.\"Line No.\", TempComponent.\"Due Date\", ActualComponent.\"Due Date\"));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempComponent.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempComponent.\"Description 2\", ActualComponent.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnLineLbl,\n+ TempComponent.\"Line No.\", TempComponent.\"Description 2\", ActualComponent.\"Description 2\"));\n end;\n \n procedure VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder: Record \"Production Order\"; var TempProdOrderRoutingLine: Record \"Prod. Order Routing Line\" temporary)\n@@ -284,6 +292,12 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n Assert.AreEqual(TempRoutingLine.Description, ActualRoutingLine.Description,\n StrSubstNo(DescriptionMismatchOnOperationLbl,\n TempRoutingLine.\"Operation No.\", TempRoutingLine.Description, ActualRoutingLine.Description));\n+\n+ // Verify Description 2 if set in temporary record\n+ if TempRoutingLine.\"Description 2\" <> '' then\n+ Assert.AreEqual(TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\",\n+ StrSubstNo(Description2MismatchOnOperationLbl,\n+ TempRoutingLine.\"Operation No.\", TempRoutingLine.\"Description 2\", ActualRoutingLine.\"Description 2\"));\n end;\n \n procedure CreateTempProdOrderComponentFromBOM(var TempProdOrderComponent: Record \"Prod. Order Component\" temporary; BOMNo: Code[20]; PurchLine: Record \"Purchase Line\")\n@@ -314,6 +328,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderComponent.\"Quantity per\" := ProductionBOMLine.\"Quantity per\";\n TempProdOrderComponent.\"Unit of Measure Code\" := ProductionBOMLine.\"Unit of Measure Code\";\n TempProdOrderComponent.\"Routing Link Code\" := ProductionBOMLine.\"Routing Link Code\";\n+ TempProdOrderComponent.\"Description 2\" := ProductionBOMLine.\"Description 2\";\n if ProductionBOMLine.\"Subcontracting Type\" in [ProductionBOMLine.\"Subcontracting Type\"::\"Purchase\", ProductionBOMLine.\"Subcontracting Type\"::InventoryByVendor] then\n TempProdOrderComponent.\"Location Code\" := GetVendorSubcontractingLocation(PurchLine.\"Buy-from Vendor No.\")\n else\n@@ -374,6 +389,7 @@ codeunit 139987 \"Subc. ProdOrderCheckLib\"\n TempProdOrderRoutingLine.Type := RoutingLine.Type;\n TempProdOrderRoutingLine.\"No.\" := RoutingLine.\"No.\";\n TempProdOrderRoutingLine.Description := RoutingLine.Description;\n+ TempProdOrderRoutingLine.\"Description 2\" := RoutingLine.\"Description 2\";\n TempProdOrderRoutingLine.\"Setup Time\" := RoutingLine.\"Setup Time\";\n TempProdOrderRoutingLine.\"Run Time\" := RoutingLine.\"Run Time\";\n TempProdOrderRoutingLine.\"Wait Time\" := RoutingLine.\"Wait Time\";\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 5c94936541..ecb610a1a6 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1707,6 +1707,135 @@ Comment = '|%1 = Transfer Order No.';\n Assert.AreEqual(0, ValueEntry.\"Invoiced Quantity\", 'Invoiced Quantity must be zero on value entry.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting')]\n+ procedure Description2CopiedFromProdOrderComponentToPurchaseLine()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderComp: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Component is propagated to Purchase Line\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateProdBomWithSubcontractingType(Item, \"Subcontracting Type\"::Purchase);\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ // [GIVEN] A Description 2 value is set on the Prod. Order Component with Subcontracting Type = Purchase\n+ ProdOrderComp.SetRange(Status, ProdOrderComp.Status::Released);\n+ ProdOrderComp.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderComp.SetRange(\"Subcontracting Type\", ProdOrderComp.\"Subcontracting Type\"::Purchase);\n+#pragma warning restore AA0210\n+ ProdOrderComp.FindFirst();\n+ ExpectedDescription2 := 'TestDescription2_Comp';\n+ ProdOrderComp.\"Description 2\" := ExpectedDescription2;\n+ ProdOrderComp.Modify();\n+\n+ // [WHEN] Create Subcontracting Purchase Order from Prod. Order Routing\n+ CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] Description 2 from Prod. Order Component is propagated to the component Purchase Line\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(Type, PurchaseLine.Type::Item);\n+ PurchaseLine.SetRange(\"No.\", ProdOrderComp.\"Item No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, PurchaseLine.\"Description 2\",\n+ 'Description 2 must be propagated from Prod. Order Component to Purchase Line');\n+ end;\n+\n+ [Test]\n+ procedure Description2PopulatedOnRequisitionLineFromCalculateSubcontracts()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ ReqWkshTemplate: Record \"Req. Wksh. Template\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ RequisitionWkshName: Record \"Requisition Wksh. Name\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ SubcCalculateSubContract: Report \"Subc. Calculate Subcontracts\";\n+ LibraryUtility: Codeunit \"Library - Utility\";\n+ ExpectedDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from Prod. Order Routing Line is populated on Requisition Line\n+ // via Calculate Subcontracts report\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Complete Setup of Manufacturing\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+\n+ CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+\n+ // [GIVEN] Description 2 is set on the subcontracting Work Center Name 2\n+ // (SubcCalcSubcontractsExt copies WorkCenter.\"Name 2\" → RequisitionLine.\"Description 2\")\n+ ExpectedDescription2 := 'TestDesc2_WC';\n+ WorkCenter[2].Get(WorkCenter[2].\"No.\");\n+ WorkCenter[2].Validate(\"Name 2\", ExpectedDescription2);\n+ WorkCenter[2].Modify(true);\n+\n+ // [GIVEN] Create requisition worksheet\n+ ReqWkshTemplate.DeleteAll(true);\n+ ReqWkshTemplate.Name := SelectRequisitionTemplateName();\n+ RequisitionWkshName.Init();\n+ RequisitionWkshName.Validate(\"Worksheet Template Name\", ReqWkshTemplate.Name);\n+ RequisitionWkshName.Validate(\n+ Name,\n+ CopyStr(\n+ LibraryUtility.GenerateRandomCode(RequisitionWkshName.FieldNo(Name), Database::\"Requisition Wksh. Name\"),\n+ 1, LibraryUtility.GetFieldLength(Database::\"Requisition Wksh. Name\", RequisitionWkshName.FieldNo(Name))));\n+ RequisitionWkshName.Insert(true);\n+\n+ RequisitionLine.\"Worksheet Template Name\" := RequisitionWkshName.\"Worksheet Template Name\";\n+ RequisitionLine.\"Journal Batch Name\" := RequisitionWkshName.Name;\n+\n+ // [WHEN] Calculate Subcontracts\n+ SubcCalculateSubContract.SetWkShLine(RequisitionLine);\n+ SubcCalculateSubContract.UseRequestPage(false);\n+ SubcCalculateSubContract.RunModal();\n+\n+ // [THEN] Description 2 on the Requisition Line is populated\n+ RequisitionLine.SetRange(\"Worksheet Template Name\", RequisitionWkshName.\"Worksheet Template Name\");\n+ RequisitionLine.SetRange(\"Journal Batch Name\", RequisitionWkshName.Name);\n+#pragma warning disable AA0210\n+ RequisitionLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning restore AA0210\n+ RequisitionLine.FindFirst();\n+ Assert.AreEqual(\n+ ExpectedDescription2, RequisitionLine.\"Description 2\",\n+ 'Description 2 must be populated on the Requisition Line from the subcontracting Work Center');\n+ end;\n+\n [PageHandler]\n procedure HandleTransferOrder(var TransfOrderPage: TestPage \"Transfer Order\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\nindex 339c881ccd..8d9830636f 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcWizGeneralTest.Codeunit.al\n@@ -231,6 +231,72 @@ codeunit 139993 \"Subc. Wiz. General Test\"\n ProdOrderCheckLib.VerifyProdOrderRoutingLinesMatchTempRecords(ProdOrder, TempProdOrderRoutingLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('HandlePurchProvisionWizard')]\n+ procedure TestWizardPreservesDescription2ThroughBOMAndRoutingLines()\n+ var\n+ ProdOrder: Record \"Production Order\";\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchLine: Record \"Purchase Line\";\n+ CreateProdOrdOpt: Codeunit \"Subc. Create Prod. Ord. Opt.\";\n+ BOMNo: Code[20];\n+ ItemNo: Code[20];\n+ RoutingNo: Code[20];\n+ SubcWorkCenterNo: Code[20];\n+ BOMLineDescription2: Text[50];\n+ RoutingLineDescription2: Text[50];\n+ begin\n+ // [SCENARIO] Description 2 from BOM line and Routing line is preserved end-to-end through\n+ // the Production Order Creation Wizard to Prod. Order Components and Routing Lines\n+ // [FEATURE] Bug 620556 - Subcontracting Description 2 alignment\n+\n+ // [GIVEN] Proper setup configuration\n+ Initialize();\n+\n+ // [GIVEN] A BOM with a line that has Description 2 set\n+ BOMNo := SubCreateProdOrdWizLibrary.CreateBOMWithDescription2(BOMLineDescription2);\n+\n+ // [GIVEN] A Routing with a subcontracting work center line that has Description 2 set\n+ RoutingNo := SubCreateProdOrdWizLibrary.CreateRoutingWithSubcWorkCenterAndDescription2(SubcWorkCenterNo, RoutingLineDescription2);\n+\n+ // [GIVEN] An item with the BOM and Routing above\n+ ItemNo := SubCreateProdOrdWizLibrary.CreateItemWithBOMAndRouting(BOMNo, RoutingNo);\n+\n+ // [GIVEN] A purchase line with a subcontracting vendor\n+ SubCreateProdOrdWizLibrary.CreatePurchaseLineWithSubcontractingVendor(PurchLine, ItemNo);\n+\n+ // [WHEN] Run the Production Order Creation Wizard\n+ WizardFinishedSuccessfully := false;\n+ Commit();\n+ CreateProdOrdOpt.Run(PurchLine);\n+\n+ // [THEN] Wizard completed successfully\n+ Assert.IsTrue(WizardFinishedSuccessfully, 'Wizard should have finished successfully');\n+\n+ // [THEN] Production Order was created\n+ PurchLine.Get(PurchLine.\"Document Type\", PurchLine.\"Document No.\", PurchLine.\"Line No.\");\n+ Assert.AreNotEqual('', PurchLine.\"Prod. Order No.\", 'Production Order No. should be set on Purchase Line');\n+ ProdOrder.Get(\"Production Order Status\"::Released, PurchLine.\"Prod. Order No.\");\n+\n+ // [THEN] Description 2 from the BOM line is preserved on the Prod. Order Component\n+ ProdOrderComponent.SetRange(Status, ProdOrder.Status);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ Assert.IsTrue(ProdOrderComponent.FindFirst(), 'Prod. Order Component must exist');\n+ Assert.AreEqual(\n+ BOMLineDescription2, ProdOrderComponent.\"Description 2\",\n+ 'Description 2 from the Production BOM Line must be preserved on the Prod. Order Component');\n+\n+ // [THEN] Description 2 from the Routing line is preserved on the Prod. Order Routing Line\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrder.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", SubcWorkCenterNo);\n+ Assert.IsTrue(ProdOrderRoutingLine.FindFirst(), 'Prod. Order Routing Line must exist for subcontracting work center');\n+ Assert.AreEqual(\n+ RoutingLineDescription2, ProdOrderRoutingLine.\"Description 2\",\n+ 'Description 2 from the Routing Line must be preserved on the Prod. Order Routing Line');\n+ end;\n+\n [ModalPageHandler]\n procedure HandlePurchProvisionWizard(var PurchProvisionWizard: TestPage \"Subc. PurchProvisionWizard\")\n begin\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8293", "base_commit": "01e67dc5ff263b26101f7f2db6caa1b346f090a6", "created_at": "2026-05-25T21:31:15Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\nindex 8d5c75124c..056de67a1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n@@ -15,12 +15,13 @@ using System.Reflection;\n codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n {\n /// \n- /// Opens the Released Production Order page for the production order linked to the given variant record.\n+ /// Opens the appropriate Production Order page (Released or Finished) for the production order linked to the given variant record.\n /// \n /// A record variant of a purchase or transfer document line.\n procedure ShowProductionOrder(RecRelatedVariant: Variant)\n var\n ProductionOrder: Record \"Production Order\";\n+ FinishedProductionOrder: Page \"Finished Production Order\";\n ReleasedProductionOrder: Page \"Released Production Order\";\n OperationNo: Code[10];\n ProdOrderNo: Code[20];\n@@ -29,11 +30,26 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n begin\n if not SetProdOrderInformationByVariant(RecRelatedVariant, ProdOrderNo, ProdOrderLineNo, RoutingNo, OperationNo) then\n exit;\n- ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ProductionOrder.SetFilter(Status, '>=%1', ProductionOrder.Status::Released);\n ProductionOrder.SetRange(\"No.\", ProdOrderNo);\n- ReleasedProductionOrder.SetTableView(ProductionOrder);\n- ReleasedProductionOrder.Editable := false;\n- ReleasedProductionOrder.Run();\n+ if not ProductionOrder.FindFirst() then\n+ exit;\n+ case ProductionOrder.Status of\n+ ProductionOrder.Status::Released:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ReleasedProductionOrder.SetTableView(ProductionOrder);\n+ ReleasedProductionOrder.Editable := false;\n+ ReleasedProductionOrder.Run();\n+ end;\n+ ProductionOrder.Status::Finished:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Finished);\n+ FinishedProductionOrder.SetTableView(ProductionOrder);\n+ FinishedProductionOrder.Editable := false;\n+ FinishedProductionOrder.Run();\n+ end;\n+ end;\n end;\n \n /// \n@@ -77,9 +93,9 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n exit(ProdOrderRoutingLine.Count());\n end;\n \n-local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n+ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n begin\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -130,7 +146,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n begin\n ProdOrderRoutingLine.SetLoadFields(\"Routing Link Code\");\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -138,7 +154,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n if ProdOrderRoutingLine.FindFirst() then\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n \n- ProdOrderComponent.SetRange(Status, ProdOrderComponent.Status::Released);\n+ ProdOrderComponent.SetFilter(Status, '>=%1', ProdOrderComponent.Status::Released);\n ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", ProdOrderLineNo);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ProdOFactboxMgmtShowsDataAfterProdOrderFinished"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 68c7fff2af..c6c56da2b8 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1875,6 +1875,57 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n 'CalcNoOfProductionOrderComponents should return a positive count for an Item Ledger Entry from a subcontracting receipt.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmArchiveOrderHandler,HandlePurchaseOrderPage')]\n+ procedure ProdOFactboxMgmtShowsDataAfterProdOrderFinished()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ SubcWorkCenter: Record \"Work Center\";\n+ SubcProdOFactboxMgmt: Codeunit \"Subc. ProdO. Factbox Mgmt.\";\n+ begin\n+ // [SCENARIO 634953] Subcontracting factbox drilldowns should work after production order is finished.\n+ Initialize();\n+\n+ // [GIVEN] A released production order with a subcontracting routing operation and a subcontracting purchase order\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateItemWithSingleSubcontractingOperation(Item, SubcWorkCenter);\n+ SubcontractingMgmtLibrary.UpdateVendorWithSubcontractingLocationCode(SubcWorkCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", SubcWorkCenter.\"No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", SubcWorkCenter.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [GIVEN] The production order is changed to Finished status\n+ LibraryManufacturing.ChangeProdOrderStatus(ProductionOrder, \"Production Order Status\"::Finished, WorkDate(), true);\n+\n+ // Re-read purchase line (the order still exists because only receipt was posted)\n+ PurchaseLine.FindFirst();\n+\n+ // [WHEN] CalcNoOfProductionOrderRoutings / CalcNoOfProductionOrderComponents are called with the Purchase Line\n+ // [THEN] Both return a positive count even though the production order is now Finished\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderRoutings(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderRoutings should return a positive count after the production order is finished.');\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderComponents(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderComponents should return a positive count after the production order is finished.');\n+ end;\n+\n [Test]\n [HandlerFunctions('ConfirmHandler')]\n procedure RoutingFactboxMgmtFiltersPurchOrderQtyByRoutingReferenceNo()\n@@ -3430,6 +3481,7 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n \n SubSetupLibrary.InitSetupFields();\n LibraryERMCountryData.CreateVATData();\n+ LibraryERMCountryData.UpdateGeneralPostingSetup();\n SubSetupLibrary.InitialSetupForGenProdPostingGroup();\n \n IsInitialized := true;\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8287", "base_commit": "ad39c988e2565d1ea1a8cb538a5b9a6ec4107eb4", "created_at": "2026-05-22T17:02:35Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\nindex b8a5c1d869..c1b2942c55 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n@@ -22,6 +22,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n IsDefaultTextTok: Label '<>''''', Locked = true;\n InvalidDataTypeErr: Label 'The value \"%1\" is not allowed for %2, it is not a %3.', Comment = '%1=the value, %2=field name,%3=field type.';\n NotInAllowableValuesErr: Label 'The value \"%1\" is not allowed for %2, it must be in the range of \"%3\".', Comment = '%1=the value, %2=field name,%3=field type.';\n+ InvalidAllowableValuesFormatErr: Label 'The allowable values \"%1\" are not a valid filter expression for %2 of type %3.', Comment = '%1=the allowable values, %2=field name, %3=field type.';\n \n trigger OnRun()\n var\n@@ -324,6 +325,110 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n ValidateAllowableValuesOnText(TestNameForError, QltyTest.\"Default Value\", QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\", TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// The test whose allowable values expression should be validated.\n+ internal procedure ValidateAllowableValuesFormat(var QltyTest: Record \"Qlty. Test\")\n+ var\n+ TestNameForError: Text;\n+ begin\n+ if QltyTest.Description <> '' then\n+ TestNameForError := QltyTest.Description\n+ else\n+ TestNameForError := QltyTest.Code;\n+\n+ ValidateAllowableValuesFormat(TestNameForError, QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\");\n+ end;\n+\n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// Friendly identifier used in error messages.\n+ /// The allowable values filter expression to validate.\n+ /// The test value type that the filter expression must match.\n+ local procedure ValidateAllowableValuesFormat(NumberOrNameOfTestNameForError: Text; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\")\n+ var\n+ IsValid: Boolean;\n+ begin\n+ if AllowableValues = '' then\n+ exit;\n+\n+ if IsBlankOrEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ if IsAnythingExceptEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ // Allowable values may contain inline expressions like [Field] that are resolved at evaluation time.\n+ // Defer validation until resolution.\n+ if AllowableValues.Contains('[') then\n+ exit;\n+\n+ IsValid := true;\n+ case QltyTestValueType of\n+ QltyTestValueType::\"Value Type Decimal\":\n+ IsValid := TryApplyDecimalFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Integer\":\n+ IsValid := TryApplyIntegerFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Boolean\":\n+ IsValid := TryApplyBooleanFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Date\":\n+ IsValid := TryApplyDateFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type DateTime\":\n+ IsValid := TryApplyDateTimeFilter(AllowableValues);\n+ end;\n+\n+ if not IsValid then\n+ Error(InvalidAllowableValuesFormatErr, AllowableValues, NumberOrNameOfTestNameForError, QltyTestValueType);\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDecimalFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionLine: Record \"Qlty. Inspection Line\" temporary;\n+ begin\n+ TempQltyInspectionLine.SetFilter(\"Derived Numeric Value\", FilterExpression);\n+ if TempQltyInspectionLine.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyIntegerFilter(FilterExpression: Text)\n+ var\n+ TempInteger: Record \"Integer\" temporary;\n+ begin\n+ TempInteger.SetFilter(Number, FilterExpression);\n+ if TempInteger.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyBooleanFilter(FilterExpression: Text)\n+ var\n+ QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n+ begin\n+ // Valid boolean allowable values are: Yes, No, True, False, 1, 0, On, Off (and variations)\n+ if not QltyBooleanParsing.CanTextBeInterpretedAsBooleanIsh(FilterExpression) then\n+ Error(InvalidAllowableValuesFormatErr, FilterExpression, '', 'Boolean');\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateFilter(FilterExpression: Text)\n+ var\n+ TempDateLookupBuffer: Record \"Date Lookup Buffer\" temporary;\n+ begin\n+ TempDateLookupBuffer.SetFilter(\"Period Start\", FilterExpression);\n+ if TempDateLookupBuffer.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateTimeFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionHeader: Record \"Qlty. Inspection Header\" temporary;\n+ begin\n+ TempQltyInspectionHeader.SetFilter(\"Finished Date\", FilterExpression);\n+ if TempQltyInspectionHeader.IsEmpty() then;\n+ end;\n+\n local procedure ValidateAllowableValuesOnText(NumberOrNameOfTestNameForError: Text; var TextToValidate: Text[250]; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\"; var TempBufferQltyTestLookupValue: Record \"Qlty. Test Lookup Value\" temporary; QltyCaseSensitivity: Enum \"Qlty. Case Sensitivity\")\n var\n QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n@@ -393,9 +498,8 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n if not (IsBlankOrEmptyCondition(AllowableValues) and (TextToValidate = '')) then\n if not QltyResultEvaluation.CheckIfValueIsString(TextToValidate, ConvertStr(AllowableValues, ',', '|'), QltyCaseSensitivity) then\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n-\n QltyTestValueType::\"Value Type Option\",\n- QltyTestValueType::\"Value Type Table Lookup\":\n+ QltyTestValueType::\"Value Type Table Lookup\":\n begin\n TextToValidate := CopyStr(TextToValidate.Trim(), 1, MaxStrLen(TextToValidate));\n \n@@ -419,6 +523,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n end;\n end;\n+\n OnAfterValidateAllowableValuesOnText(NumberOrNameOfTestNameForError, TextToValidate, AllowableValues, QltyTestValueType, TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139963, "functionName": ["ValidateAllowableValuesFormat_Boolean_ValidFormats", "ValidateAllowableValuesFormat_NonValidatedTypes", "ValidateAllowableValuesFormat_Boolean_InvalidFormats", "ValidateAllowableValuesFormat_DateTime_InvalidFormats", "ValidateAllowableValuesFormat_Integer_ValidFormats", "ValidateAllowableValuesFormat_Integer_InvalidFormats", "ValidateAllowableValuesFormat_Date_InvalidFormats", "ValidateAllowableValuesFormat_Decimal_ValidFormats", "ValidateAllowableValuesFormat_Date_ValidFormats", "ValidateAllowableValuesFormat_DateTime_ValidFormats", "ValidateAllowableValuesFormat_Decimal_InvalidFormats"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\nindex 9f4cbf3006..66e4c203fc 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n@@ -54,8 +54,11 @@ table 20401 \"Qlty. Test\"\n {\n Caption = 'Allowable Values';\n ToolTip = 'Specifies an expression for the range of values you can enter or select for the Test. Depending on the Test Value Type, the expression format varies. For example if you want a measurement such as a percentage that collects between 0 and 100 you would enter 0..100. This is not the pass or acceptable condition, these are just the technically possible values that the inspector can enter. You would then enter a passing condition in your result conditions. If you had a result of Pass being 80 to 100, you would then configure 80..100 for that result.';\n+\n trigger OnValidate()\n begin\n+ Rec.ValidateAllowableValuesFormat();\n+\n if Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Option\", Rec.\"Test Value Type\"::\"Value Type Table Lookup\"] then\n Rec.\"Allowable Values\" := CopyStr(Rec.\"Allowable Values\".Replace(', ', ','), 1, MaxStrLen(Rec.\"Allowable Values\"));\n end;\n@@ -472,6 +475,16 @@ table 20401 \"Qlty. Test\"\n QltyResultEvaluation.ValidateAllowableValuesOnTest(Rec);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the test value type.\n+ /// \n+ procedure ValidateAllowableValuesFormat()\n+ var\n+ QltyResultEvaluation: Codeunit \"Qlty. Result Evaluation\";\n+ begin\n+ QltyResultEvaluation.ValidateAllowableValuesFormat(Rec);\n+ end;\n+\n /// \n /// Code = the unique code\n /// Description = raw description.\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\nindex 91159fca6e..05f7d8a17a 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n@@ -2071,6 +2071,440 @@ codeunit 139963 \"Qlty. Tests - Result Eval.\"\n LibraryAssert.ExpectedError(StrSubstNo(Expected4Err, OptionListQltyInspectionLine.\"Test Code\"));\n end;\n \n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_ValidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC';\n+ DecimalQltyTest.Description := 'Test Decimal';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ DecimalQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ DecimalQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25.5\"\n+ DecimalQltyTest.\"Allowable Values\" := '25.5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"10|20|30\"\n+ DecimalQltyTest.\"Allowable Values\" := '10|20|30';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DecimalQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to not empty condition \"<>''\"\n+ DecimalQltyTest.\"Allowable Values\" := '<>''''';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_InvalidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC2';\n+ DecimalQltyTest.Description := 'Test Decimal Invalid';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a number\"\n+ DecimalQltyTest.\"Allowable Values\" := 'not a number';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid operator \"==5\"\n+ DecimalQltyTest.\"Allowable Values\" := '==5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_ValidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT';\n+ IntegerQltyTest.Description := 'Test Integer';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ IntegerQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ IntegerQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ IntegerQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25\"\n+ IntegerQltyTest.\"Allowable Values\" := '25';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"1|2|3|4|5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1|2|3|4|5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ IntegerQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ IntegerQltyTest.\"Allowable Values\" := '1..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_InvalidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT2';\n+ IntegerQltyTest.Description := 'Test Integer Invalid';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to decimal value \"1.5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1.5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not an integer\"\n+ IntegerQltyTest.\"Allowable Values\" := 'not an integer';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_ValidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE';\n+ DateQltyTest.Description := 'Test Date';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact date \"2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to date range \"2024-01-01..2024-12-31\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01..2024-12-31';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than date \">2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '>2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateQltyTest.\"Allowable Values\" := '>[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_InvalidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE2';\n+ DateQltyTest.Description := 'Test Date Invalid';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid date \"99/99/9999\"\n+ DateQltyTest.\"Allowable Values\" := '99/99/9999';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a date\"\n+ DateQltyTest.\"Allowable Values\" := 'not a date';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_ValidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT';\n+ DateTimeQltyTest.Description := 'Test DateTime';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact datetime \"2024-01-01 10:30:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 10:30:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to datetime range \"2024-01-01 00:00:00..2024-12-31 23:59:59\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 00:00:00..2024-12-31 23:59:59';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than datetime \">2024-01-01 10:00:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '>2024-01-01 10:00:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateTimeQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateTimeQltyTest.\"Allowable Values\" := '<[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_InvalidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT2';\n+ DateTimeQltyTest.Description := 'Test DateTime Invalid';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid datetime \"99/99/9999 99:99:99\"\n+ DateTimeQltyTest.\"Allowable Values\" := '99/99/9999 99:99:99';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a datetime\"\n+ DateTimeQltyTest.\"Allowable Values\" := 'not a datetime';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_ValidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL';\n+ BooleanQltyTest.Description := 'Test Boolean';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to \"Yes\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Yes';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"No\"\n+ BooleanQltyTest.\"Allowable Values\" := 'No';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"True\"\n+ BooleanQltyTest.\"Allowable Values\" := 'True';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"False\"\n+ BooleanQltyTest.\"Allowable Values\" := 'False';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"1\"\n+ BooleanQltyTest.\"Allowable Values\" := '1';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"0\"\n+ BooleanQltyTest.\"Allowable Values\" := '0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"On\"\n+ BooleanQltyTest.\"Allowable Values\" := 'On';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"Off\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Off';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"Y\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Y';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"N\"\n+ BooleanQltyTest.\"Allowable Values\" := 'N';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ BooleanQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ BooleanQltyTest.\"Allowable Values\" := '[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_InvalidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL2';\n+ BooleanQltyTest.Description := 'Test Boolean Invalid';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"Maybe\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Maybe';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid number \"2\"\n+ BooleanQltyTest.\"Allowable Values\" := '2';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a boolean\"\n+ BooleanQltyTest.\"Allowable Values\" := 'not a boolean';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"abc\"\n+ BooleanQltyTest.\"Allowable Values\" := 'abc';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_NonValidatedTypes()\n+ var\n+ TextQltyTest: Record \"Qlty. Test\";\n+ OptionQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat does not validate non-numeric/non-date types\n+\n+ // [GIVEN] A quality test with text type is created\n+ TextQltyTest.Init();\n+ TextQltyTest.Code := 'TESTTEXT';\n+ TextQltyTest.Description := 'Test Text';\n+ TextQltyTest.\"Test Value Type\" := TextQltyTest.\"Test Value Type\"::\"Value Type Text\";\n+ TextQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to any text value \"A|B|C\"\n+ TextQltyTest.\"Allowable Values\" := 'A|B|C';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for text type)\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to any arbitrary text\n+ TextQltyTest.\"Allowable Values\" := 'any text value';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [GIVEN] A quality test with option type is created\n+ OptionQltyTest.Init();\n+ OptionQltyTest.Code := 'TESTOPT';\n+ OptionQltyTest.Description := 'Test Option';\n+ OptionQltyTest.\"Test Value Type\" := OptionQltyTest.\"Test Value Type\"::\"Value Type Option\";\n+ OptionQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to comma-separated options \"Option1,Option2,Option3\"\n+ OptionQltyTest.\"Allowable Values\" := 'Option1,Option2,Option3';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for option type)\n+ OptionQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+\n local procedure GetTemplateLineConfigFilters(var QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\"; var OutTemplateLineQltyIResultConditConf: Record \"Qlty. I. Result Condit. Conf.\")\n begin\n OutTemplateLineQltyIResultConditConf.SetRange(\"Condition Type\", OutTemplateLineQltyIResultConditConf.\"Condition Type\"::Template);\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8286", "base_commit": "9e4bca5d3428c17d51fbe6e903f0efe2bc9e410b", "created_at": "2026-05-22T13:07:41Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\nindex dfb07f0502..a005fa7b7c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n@@ -436,7 +436,7 @@ codeunit 99001508 \"Subc. Price Management\"\n \n GetPriceByUOM(SubcontractorPrice, PriceListQty, PriceListCost);\n if PriceListCost <> 0 then begin\n- ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityBase(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n+ ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityForUOM(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n ConvertPriceToCurrency(RequisitionLine.\"Currency Code\", SubcontractorPrice.\"Currency Code\", PriceListCost, DirectCost);\n end;\n RequisitionLine.\"Direct Unit Cost\" := DirectCost;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..73e138fe61 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -3401,6 +3401,77 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.AreEqual('', ToPurchaseHeader.\"Subc. Location Code\", 'Subc. Location Code should not be copied from archive by Copy Document');\n end;\n \n+ [Test]\n+ procedure WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion()\n+ var\n+ Item: Record Item;\n+ ItemUOM: Record \"Item Unit of Measure\";\n+ Vendor: Record Vendor;\n+ WorkCenter: Record \"Work Center\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ SubcPriceManagement: Codeunit \"Subc. Price Management\";\n+ QtyPerSet: Integer;\n+ PriceListUnitCost: Decimal;\n+ begin\n+ // [SCENARIO 636078] Calculate Subcontracts must compute Direct Unit Cost on the Subcontracting\n+ // Worksheet using the per-UoM conversion factor (GetQuantityForUOM()), not the total base\n+ // quantity (GetQuantityBase()) of the order.\n+\n+ // [GIVEN] Item with PCS base UoM and a SET alternative UoM (10 PCS per SET).\n+ Initialize();\n+ LibraryInventory.CreateItem(Item);\n+ QtyPerSet := 10;\n+ LibraryInventory.CreateItemUnitOfMeasureCode(ItemUOM, Item.\"No.\", QtyPerSet);\n+\n+ // [GIVEN] Vendor and Work Center with the vendor as its subcontractor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+ LibraryManufacturing.CreateWorkCenter(WorkCenter);\n+ WorkCenter.Validate(\"Subcontractor No.\", Vendor.\"No.\");\n+ WorkCenter.Modify(true);\n+\n+ // [GIVEN] A subcontractor price in PCS with Minimum Quantity 1 and Direct Unit Cost 1000.\n+ PriceListUnitCost := 1000;\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter.\"No.\", Vendor.\"No.\", Item.\"No.\", '', '', WorkDate(), Item.\"Base Unit of Measure\", 1, '');\n+ SubcontractorPrice.Validate(\"Direct Unit Cost\", PriceListUnitCost);\n+ SubcontractorPrice.Modify(true);\n+\n+ // [GIVEN] A staged Requisition Line for 3 SET (= 30 PCS in base UoM).\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := ItemUOM.Code;\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 3;\n+\n+ // [WHEN] The subcontractor price is applied to the requisition line.\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost = price-list cost * Qty-per-UoM (1000 * 10 = 10000),\n+ // not price-list cost * total base quantity (1000 * 30 = 30000 — the pre-fix behavior).\n+ Assert.AreEqual(\n+ PriceListUnitCost * QtyPerSet, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost on the Subcontracting Worksheet must be derived from Qty. per Unit of Measure, not from total base quantity.');\n+\n+ // [WHEN] The same price is applied to a Requisition Line using the base UoM (no conversion needed).\n+ Clear(RequisitionLine);\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := Item.\"Base Unit of Measure\";\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 30;\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost equals the price-list cost (the same-UoM path is unchanged by the fix).\n+ Assert.AreEqual(\n+ PriceListUnitCost, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost must equal the price-list cost when the worksheet UoM matches the price-list UoM.');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. Subcontracting Test\");\n"} From c3cc02ba767ed1e60ce595846a7cca7c828d66f3 Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Thu, 4 Jun 2026 14:15:50 +0200 Subject: [PATCH 10/14] change 8286 --- dataset/bcbench.jsonl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index 660b7f7f6..c568b9299 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -102,4 +102,4 @@ {"metadata": {"area": "peppol", "image_count": 1}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8059", "base_commit": "396e3bb12d0593738c9368371d6273a6d41c6826", "created_at": "2026-05-08T09:31:42Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\PEPPOL\\App", "src\\Apps\\W1\\PEPPOL\\Test"], "patch": "diff --git a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\nindex 30f5f792bd..c7981a46fa 100644\n--- a/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/App/src/Common/PEPPOL30Impl.Codeunit.al\n@@ -798,6 +798,8 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n InvoiceLineNote := DelChr(Format(SalesLine.Type), '<>');\n InvoicedQuantity := Format(SalesLine.Quantity, 0, 9);\n SalesLineLineAmount := SalesLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesLineLineAmount := Round(SalesLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n InvoiceLineExtensionAmount := Format(SalesLineLineAmount, 0, 9);\n LineExtensionAmountCurrencyID := GetSalesDocCurrencyCode(SalesHeader);\n InvoiceLineAccountingCost := '';\n@@ -869,7 +871,10 @@ codeunit 37201 \"PEPPOL30 Impl.\"\n \n InvLnAllowanceChargeIndicator := 'false';\n InvLnAllowanceChargeReason := LineDisAmtTxt;\n- InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ InvLnAllowanceChargeAmount := Format(Round(SalesLine.\"Line Discount Amount\" / (1 + SalesLine.\"VAT %\" / 100), 0.01), 0, 9)\n+ else\n+ InvLnAllowanceChargeAmount := Format(SalesLine.\"Line Discount Amount\", 0, 9);\n InvLnAllowanceChargeAmtCurrID := GetSalesDocCurrencyCode(SalesHeader);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139235, "functionName": ["LineAmountsConsistentWhenPricesInclVATNoDiscount"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\nindex 36931d56ed..cd237011d5 100644\n--- a/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n+++ b/src/Apps/W1/PEPPOL/Test/src/PEPPOL30ManagementTests.Codeunit.al\n@@ -3349,6 +3349,68 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual('', CustTaxSchemeID, 'Tax Scheme ID should be empty for Tax Category O.');\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ procedure LineAmountsConsistentWhenPricesInclVATNoDiscount()\n+ var\n+ SalesHeader: Record \"Sales Header\";\n+ SalesLine: Record \"Sales Line\";\n+ Customer: Record Customer;\n+ Item: Record Item;\n+ SalesInvoiceHeader: Record \"Sales Invoice Header\";\n+ SalesInvoiceLine: Record \"Sales Invoice Line\";\n+ PEPPOLLineInfoProvider: Interface \"PEPPOL Line Info Provider\";\n+ InvoiceLineID: Text;\n+ InvoiceLineNote: Text;\n+ InvoicedQuantity: Text;\n+ InvoiceLineExtensionAmount: Text;\n+ LineExtensionAmountCurrencyID: Text;\n+ InvoiceLineAccountingCost: Text;\n+ InvoiceLinePriceAmount: Text;\n+ InvLinePriceAmountCurrencyID: Text;\n+ BaseQuantity: Text;\n+ UnitCode: Text;\n+ PriceAmount: Decimal;\n+ LineExtensionAmt: Decimal;\n+ SalesInvoiceNo: Code[20];\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 630795] PEPPOL LineExtensionAmount equals PriceAmount times Quantity when Prices Including VAT is used\n+ Initialize();\n+\n+ // [GIVEN] Customer \"C\" with PEPPOL identifier\n+ LibrarySales.CreateCustomer(Customer);\n+ AddCustPEPPOLIdentifier(Customer.\"No.\");\n+\n+ // [GIVEN] Sales Invoice for \"C\" with \"Prices Including VAT\" = TRUE and Quantity = 7\n+ CreateItemWithPrice(Item, 139);\n+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader.\"Document Type\"::Invoice, Customer.\"No.\");\n+ SalesHeader.Validate(\"Prices Including VAT\", true);\n+ SalesHeader.Modify(true);\n+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item.\"No.\", 7);\n+\n+ // [WHEN] Post the Sales Invoice and retrieve PEPPOL line amounts\n+ SalesInvoiceNo := LibrarySales.PostSalesDocument(SalesHeader, true, true);\n+ SalesInvoiceHeader.Get(SalesInvoiceNo);\n+ SalesHeader.TransferFields(SalesInvoiceHeader);\n+ FindSalesInvoiceLine(SalesInvoiceLine, SalesInvoiceNo);\n+ SalesLine.TransferFields(SalesInvoiceLine);\n+\n+ PEPPOLLineInfoProvider := GetFormat();\n+ PEPPOLLineInfoProvider.GetLineGeneralInfo(\n+ SalesLine, SalesHeader, InvoiceLineID, InvoiceLineNote, InvoicedQuantity,\n+ InvoiceLineExtensionAmount, LineExtensionAmountCurrencyID, InvoiceLineAccountingCost);\n+ PEPPOLLineInfoProvider.GetLinePriceInfo(\n+ SalesLine, SalesHeader, InvoiceLinePriceAmount, InvLinePriceAmountCurrencyID,\n+ BaseQuantity, UnitCode);\n+\n+ // [THEN] LineExtensionAmount equals PriceAmount times Quantity per PEPPOL BIS 3.0\n+ Evaluate(PriceAmount, InvoiceLinePriceAmount, 9);\n+ Evaluate(LineExtensionAmt, InvoiceLineExtensionAmount, 9);\n+ Assert.AreEqual(PriceAmount * SalesInvoiceLine.Quantity, LineExtensionAmt,\n+ 'LineExtensionAmount must equal PriceAmount * Quantity per PEPPOL BIS 3.0');\n+ end;\n+\n var\n local procedure Initialize()\n var\n@@ -3993,6 +4055,8 @@ codeunit 139235 \"PEPPOL30 Management Tests\"\n Assert.AreEqual(UnitOfMeasure.\"International Standard Code\", unitCode, '');\n Assert.AreEqual('UNECERec20', unitCodeListID, '');\n SalesInvoiceLineLineAmount := SalesInvoiceLine.\"Line Amount\";\n+ if SalesHeader.\"Prices Including VAT\" and (SalesLine.\"VAT %\" <> 0) then\n+ SalesInvoiceLineLineAmount := Round(SalesInvoiceLineLineAmount / (1 + SalesLine.\"VAT %\" / 100), 0.01);\n Assert.AreEqual(Format(SalesInvoiceLineLineAmount, 0, 9), InvoiceLineExtensionAmount, '');\n Assert.AreEqual(SalesHeader.\"Currency Code\", LineExtensionAmountCurrencyID, '');\n Assert.AreEqual('', InvoiceLineAccountingCost, '');\n"} {"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8293", "base_commit": "01e67dc5ff263b26101f7f2db6caa1b346f090a6", "created_at": "2026-05-25T21:31:15Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\nindex 8d5c75124c..056de67a1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n@@ -15,12 +15,13 @@ using System.Reflection;\n codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n {\n /// \n- /// Opens the Released Production Order page for the production order linked to the given variant record.\n+ /// Opens the appropriate Production Order page (Released or Finished) for the production order linked to the given variant record.\n /// \n /// A record variant of a purchase or transfer document line.\n procedure ShowProductionOrder(RecRelatedVariant: Variant)\n var\n ProductionOrder: Record \"Production Order\";\n+ FinishedProductionOrder: Page \"Finished Production Order\";\n ReleasedProductionOrder: Page \"Released Production Order\";\n OperationNo: Code[10];\n ProdOrderNo: Code[20];\n@@ -29,11 +30,26 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n begin\n if not SetProdOrderInformationByVariant(RecRelatedVariant, ProdOrderNo, ProdOrderLineNo, RoutingNo, OperationNo) then\n exit;\n- ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ProductionOrder.SetFilter(Status, '>=%1', ProductionOrder.Status::Released);\n ProductionOrder.SetRange(\"No.\", ProdOrderNo);\n- ReleasedProductionOrder.SetTableView(ProductionOrder);\n- ReleasedProductionOrder.Editable := false;\n- ReleasedProductionOrder.Run();\n+ if not ProductionOrder.FindFirst() then\n+ exit;\n+ case ProductionOrder.Status of\n+ ProductionOrder.Status::Released:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ReleasedProductionOrder.SetTableView(ProductionOrder);\n+ ReleasedProductionOrder.Editable := false;\n+ ReleasedProductionOrder.Run();\n+ end;\n+ ProductionOrder.Status::Finished:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Finished);\n+ FinishedProductionOrder.SetTableView(ProductionOrder);\n+ FinishedProductionOrder.Editable := false;\n+ FinishedProductionOrder.Run();\n+ end;\n+ end;\n end;\n \n /// \n@@ -77,9 +93,9 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n exit(ProdOrderRoutingLine.Count());\n end;\n \n-local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n+ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n begin\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -130,7 +146,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n begin\n ProdOrderRoutingLine.SetLoadFields(\"Routing Link Code\");\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -138,7 +154,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n if ProdOrderRoutingLine.FindFirst() then\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n \n- ProdOrderComponent.SetRange(Status, ProdOrderComponent.Status::Released);\n+ ProdOrderComponent.SetFilter(Status, '>=%1', ProdOrderComponent.Status::Released);\n ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", ProdOrderLineNo);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ProdOFactboxMgmtShowsDataAfterProdOrderFinished"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 68c7fff2af..c6c56da2b8 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1875,6 +1875,57 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n 'CalcNoOfProductionOrderComponents should return a positive count for an Item Ledger Entry from a subcontracting receipt.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmArchiveOrderHandler,HandlePurchaseOrderPage')]\n+ procedure ProdOFactboxMgmtShowsDataAfterProdOrderFinished()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ SubcWorkCenter: Record \"Work Center\";\n+ SubcProdOFactboxMgmt: Codeunit \"Subc. ProdO. Factbox Mgmt.\";\n+ begin\n+ // [SCENARIO 634953] Subcontracting factbox drilldowns should work after production order is finished.\n+ Initialize();\n+\n+ // [GIVEN] A released production order with a subcontracting routing operation and a subcontracting purchase order\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateItemWithSingleSubcontractingOperation(Item, SubcWorkCenter);\n+ SubcontractingMgmtLibrary.UpdateVendorWithSubcontractingLocationCode(SubcWorkCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", SubcWorkCenter.\"No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", SubcWorkCenter.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [GIVEN] The production order is changed to Finished status\n+ LibraryManufacturing.ChangeProdOrderStatus(ProductionOrder, \"Production Order Status\"::Finished, WorkDate(), true);\n+\n+ // Re-read purchase line (the order still exists because only receipt was posted)\n+ PurchaseLine.FindFirst();\n+\n+ // [WHEN] CalcNoOfProductionOrderRoutings / CalcNoOfProductionOrderComponents are called with the Purchase Line\n+ // [THEN] Both return a positive count even though the production order is now Finished\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderRoutings(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderRoutings should return a positive count after the production order is finished.');\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderComponents(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderComponents should return a positive count after the production order is finished.');\n+ end;\n+\n [Test]\n [HandlerFunctions('ConfirmHandler')]\n procedure RoutingFactboxMgmtFiltersPurchOrderQtyByRoutingReferenceNo()\n@@ -3430,6 +3481,7 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n \n SubSetupLibrary.InitSetupFields();\n LibraryERMCountryData.CreateVATData();\n+ LibraryERMCountryData.UpdateGeneralPostingSetup();\n SubSetupLibrary.InitialSetupForGenProdPostingGroup();\n \n IsInitialized := true;\n"} {"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8287", "base_commit": "ad39c988e2565d1ea1a8cb538a5b9a6ec4107eb4", "created_at": "2026-05-22T17:02:35Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\nindex b8a5c1d869..c1b2942c55 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n@@ -22,6 +22,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n IsDefaultTextTok: Label '<>''''', Locked = true;\n InvalidDataTypeErr: Label 'The value \"%1\" is not allowed for %2, it is not a %3.', Comment = '%1=the value, %2=field name,%3=field type.';\n NotInAllowableValuesErr: Label 'The value \"%1\" is not allowed for %2, it must be in the range of \"%3\".', Comment = '%1=the value, %2=field name,%3=field type.';\n+ InvalidAllowableValuesFormatErr: Label 'The allowable values \"%1\" are not a valid filter expression for %2 of type %3.', Comment = '%1=the allowable values, %2=field name, %3=field type.';\n \n trigger OnRun()\n var\n@@ -324,6 +325,110 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n ValidateAllowableValuesOnText(TestNameForError, QltyTest.\"Default Value\", QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\", TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// The test whose allowable values expression should be validated.\n+ internal procedure ValidateAllowableValuesFormat(var QltyTest: Record \"Qlty. Test\")\n+ var\n+ TestNameForError: Text;\n+ begin\n+ if QltyTest.Description <> '' then\n+ TestNameForError := QltyTest.Description\n+ else\n+ TestNameForError := QltyTest.Code;\n+\n+ ValidateAllowableValuesFormat(TestNameForError, QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\");\n+ end;\n+\n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// Friendly identifier used in error messages.\n+ /// The allowable values filter expression to validate.\n+ /// The test value type that the filter expression must match.\n+ local procedure ValidateAllowableValuesFormat(NumberOrNameOfTestNameForError: Text; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\")\n+ var\n+ IsValid: Boolean;\n+ begin\n+ if AllowableValues = '' then\n+ exit;\n+\n+ if IsBlankOrEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ if IsAnythingExceptEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ // Allowable values may contain inline expressions like [Field] that are resolved at evaluation time.\n+ // Defer validation until resolution.\n+ if AllowableValues.Contains('[') then\n+ exit;\n+\n+ IsValid := true;\n+ case QltyTestValueType of\n+ QltyTestValueType::\"Value Type Decimal\":\n+ IsValid := TryApplyDecimalFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Integer\":\n+ IsValid := TryApplyIntegerFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Boolean\":\n+ IsValid := TryApplyBooleanFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Date\":\n+ IsValid := TryApplyDateFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type DateTime\":\n+ IsValid := TryApplyDateTimeFilter(AllowableValues);\n+ end;\n+\n+ if not IsValid then\n+ Error(InvalidAllowableValuesFormatErr, AllowableValues, NumberOrNameOfTestNameForError, QltyTestValueType);\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDecimalFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionLine: Record \"Qlty. Inspection Line\" temporary;\n+ begin\n+ TempQltyInspectionLine.SetFilter(\"Derived Numeric Value\", FilterExpression);\n+ if TempQltyInspectionLine.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyIntegerFilter(FilterExpression: Text)\n+ var\n+ TempInteger: Record \"Integer\" temporary;\n+ begin\n+ TempInteger.SetFilter(Number, FilterExpression);\n+ if TempInteger.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyBooleanFilter(FilterExpression: Text)\n+ var\n+ QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n+ begin\n+ // Valid boolean allowable values are: Yes, No, True, False, 1, 0, On, Off (and variations)\n+ if not QltyBooleanParsing.CanTextBeInterpretedAsBooleanIsh(FilterExpression) then\n+ Error(InvalidAllowableValuesFormatErr, FilterExpression, '', 'Boolean');\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateFilter(FilterExpression: Text)\n+ var\n+ TempDateLookupBuffer: Record \"Date Lookup Buffer\" temporary;\n+ begin\n+ TempDateLookupBuffer.SetFilter(\"Period Start\", FilterExpression);\n+ if TempDateLookupBuffer.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateTimeFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionHeader: Record \"Qlty. Inspection Header\" temporary;\n+ begin\n+ TempQltyInspectionHeader.SetFilter(\"Finished Date\", FilterExpression);\n+ if TempQltyInspectionHeader.IsEmpty() then;\n+ end;\n+\n local procedure ValidateAllowableValuesOnText(NumberOrNameOfTestNameForError: Text; var TextToValidate: Text[250]; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\"; var TempBufferQltyTestLookupValue: Record \"Qlty. Test Lookup Value\" temporary; QltyCaseSensitivity: Enum \"Qlty. Case Sensitivity\")\n var\n QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n@@ -393,9 +498,8 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n if not (IsBlankOrEmptyCondition(AllowableValues) and (TextToValidate = '')) then\n if not QltyResultEvaluation.CheckIfValueIsString(TextToValidate, ConvertStr(AllowableValues, ',', '|'), QltyCaseSensitivity) then\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n-\n QltyTestValueType::\"Value Type Option\",\n- QltyTestValueType::\"Value Type Table Lookup\":\n+ QltyTestValueType::\"Value Type Table Lookup\":\n begin\n TextToValidate := CopyStr(TextToValidate.Trim(), 1, MaxStrLen(TextToValidate));\n \n@@ -419,6 +523,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n end;\n end;\n+\n OnAfterValidateAllowableValuesOnText(NumberOrNameOfTestNameForError, TextToValidate, AllowableValues, QltyTestValueType, TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139963, "functionName": ["ValidateAllowableValuesFormat_Boolean_ValidFormats", "ValidateAllowableValuesFormat_NonValidatedTypes", "ValidateAllowableValuesFormat_Boolean_InvalidFormats", "ValidateAllowableValuesFormat_DateTime_InvalidFormats", "ValidateAllowableValuesFormat_Integer_ValidFormats", "ValidateAllowableValuesFormat_Integer_InvalidFormats", "ValidateAllowableValuesFormat_Date_InvalidFormats", "ValidateAllowableValuesFormat_Decimal_ValidFormats", "ValidateAllowableValuesFormat_Date_ValidFormats", "ValidateAllowableValuesFormat_DateTime_ValidFormats", "ValidateAllowableValuesFormat_Decimal_InvalidFormats"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\nindex 9f4cbf3006..66e4c203fc 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n@@ -54,8 +54,11 @@ table 20401 \"Qlty. Test\"\n {\n Caption = 'Allowable Values';\n ToolTip = 'Specifies an expression for the range of values you can enter or select for the Test. Depending on the Test Value Type, the expression format varies. For example if you want a measurement such as a percentage that collects between 0 and 100 you would enter 0..100. This is not the pass or acceptable condition, these are just the technically possible values that the inspector can enter. You would then enter a passing condition in your result conditions. If you had a result of Pass being 80 to 100, you would then configure 80..100 for that result.';\n+\n trigger OnValidate()\n begin\n+ Rec.ValidateAllowableValuesFormat();\n+\n if Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Option\", Rec.\"Test Value Type\"::\"Value Type Table Lookup\"] then\n Rec.\"Allowable Values\" := CopyStr(Rec.\"Allowable Values\".Replace(', ', ','), 1, MaxStrLen(Rec.\"Allowable Values\"));\n end;\n@@ -472,6 +475,16 @@ table 20401 \"Qlty. Test\"\n QltyResultEvaluation.ValidateAllowableValuesOnTest(Rec);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the test value type.\n+ /// \n+ procedure ValidateAllowableValuesFormat()\n+ var\n+ QltyResultEvaluation: Codeunit \"Qlty. Result Evaluation\";\n+ begin\n+ QltyResultEvaluation.ValidateAllowableValuesFormat(Rec);\n+ end;\n+\n /// \n /// Code = the unique code\n /// Description = raw description.\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\nindex 91159fca6e..05f7d8a17a 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n@@ -2071,6 +2071,440 @@ codeunit 139963 \"Qlty. Tests - Result Eval.\"\n LibraryAssert.ExpectedError(StrSubstNo(Expected4Err, OptionListQltyInspectionLine.\"Test Code\"));\n end;\n \n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_ValidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC';\n+ DecimalQltyTest.Description := 'Test Decimal';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ DecimalQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ DecimalQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25.5\"\n+ DecimalQltyTest.\"Allowable Values\" := '25.5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"10|20|30\"\n+ DecimalQltyTest.\"Allowable Values\" := '10|20|30';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DecimalQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to not empty condition \"<>''\"\n+ DecimalQltyTest.\"Allowable Values\" := '<>''''';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_InvalidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC2';\n+ DecimalQltyTest.Description := 'Test Decimal Invalid';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a number\"\n+ DecimalQltyTest.\"Allowable Values\" := 'not a number';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid operator \"==5\"\n+ DecimalQltyTest.\"Allowable Values\" := '==5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_ValidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT';\n+ IntegerQltyTest.Description := 'Test Integer';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ IntegerQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ IntegerQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ IntegerQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25\"\n+ IntegerQltyTest.\"Allowable Values\" := '25';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"1|2|3|4|5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1|2|3|4|5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ IntegerQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ IntegerQltyTest.\"Allowable Values\" := '1..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_InvalidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT2';\n+ IntegerQltyTest.Description := 'Test Integer Invalid';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to decimal value \"1.5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1.5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not an integer\"\n+ IntegerQltyTest.\"Allowable Values\" := 'not an integer';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_ValidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE';\n+ DateQltyTest.Description := 'Test Date';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact date \"2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to date range \"2024-01-01..2024-12-31\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01..2024-12-31';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than date \">2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '>2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateQltyTest.\"Allowable Values\" := '>[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_InvalidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE2';\n+ DateQltyTest.Description := 'Test Date Invalid';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid date \"99/99/9999\"\n+ DateQltyTest.\"Allowable Values\" := '99/99/9999';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a date\"\n+ DateQltyTest.\"Allowable Values\" := 'not a date';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_ValidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT';\n+ DateTimeQltyTest.Description := 'Test DateTime';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact datetime \"2024-01-01 10:30:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 10:30:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to datetime range \"2024-01-01 00:00:00..2024-12-31 23:59:59\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 00:00:00..2024-12-31 23:59:59';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than datetime \">2024-01-01 10:00:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '>2024-01-01 10:00:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateTimeQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateTimeQltyTest.\"Allowable Values\" := '<[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_InvalidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT2';\n+ DateTimeQltyTest.Description := 'Test DateTime Invalid';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid datetime \"99/99/9999 99:99:99\"\n+ DateTimeQltyTest.\"Allowable Values\" := '99/99/9999 99:99:99';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a datetime\"\n+ DateTimeQltyTest.\"Allowable Values\" := 'not a datetime';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_ValidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL';\n+ BooleanQltyTest.Description := 'Test Boolean';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to \"Yes\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Yes';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"No\"\n+ BooleanQltyTest.\"Allowable Values\" := 'No';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"True\"\n+ BooleanQltyTest.\"Allowable Values\" := 'True';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"False\"\n+ BooleanQltyTest.\"Allowable Values\" := 'False';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"1\"\n+ BooleanQltyTest.\"Allowable Values\" := '1';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"0\"\n+ BooleanQltyTest.\"Allowable Values\" := '0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"On\"\n+ BooleanQltyTest.\"Allowable Values\" := 'On';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"Off\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Off';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"Y\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Y';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"N\"\n+ BooleanQltyTest.\"Allowable Values\" := 'N';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ BooleanQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ BooleanQltyTest.\"Allowable Values\" := '[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_InvalidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL2';\n+ BooleanQltyTest.Description := 'Test Boolean Invalid';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"Maybe\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Maybe';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid number \"2\"\n+ BooleanQltyTest.\"Allowable Values\" := '2';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a boolean\"\n+ BooleanQltyTest.\"Allowable Values\" := 'not a boolean';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"abc\"\n+ BooleanQltyTest.\"Allowable Values\" := 'abc';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_NonValidatedTypes()\n+ var\n+ TextQltyTest: Record \"Qlty. Test\";\n+ OptionQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat does not validate non-numeric/non-date types\n+\n+ // [GIVEN] A quality test with text type is created\n+ TextQltyTest.Init();\n+ TextQltyTest.Code := 'TESTTEXT';\n+ TextQltyTest.Description := 'Test Text';\n+ TextQltyTest.\"Test Value Type\" := TextQltyTest.\"Test Value Type\"::\"Value Type Text\";\n+ TextQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to any text value \"A|B|C\"\n+ TextQltyTest.\"Allowable Values\" := 'A|B|C';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for text type)\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to any arbitrary text\n+ TextQltyTest.\"Allowable Values\" := 'any text value';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [GIVEN] A quality test with option type is created\n+ OptionQltyTest.Init();\n+ OptionQltyTest.Code := 'TESTOPT';\n+ OptionQltyTest.Description := 'Test Option';\n+ OptionQltyTest.\"Test Value Type\" := OptionQltyTest.\"Test Value Type\"::\"Value Type Option\";\n+ OptionQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to comma-separated options \"Option1,Option2,Option3\"\n+ OptionQltyTest.\"Allowable Values\" := 'Option1,Option2,Option3';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for option type)\n+ OptionQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+\n local procedure GetTemplateLineConfigFilters(var QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\"; var OutTemplateLineQltyIResultConditConf: Record \"Qlty. I. Result Condit. Conf.\")\n begin\n OutTemplateLineQltyIResultConditConf.SetRange(\"Condition Type\", OutTemplateLineQltyIResultConditConf.\"Condition Type\"::Template);\n"} -{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8286", "base_commit": "9e4bca5d3428c17d51fbe6e903f0efe2bc9e410b", "created_at": "2026-05-22T13:07:41Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\nindex dfb07f0502..a005fa7b7c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n@@ -436,7 +436,7 @@ codeunit 99001508 \"Subc. Price Management\"\n \n GetPriceByUOM(SubcontractorPrice, PriceListQty, PriceListCost);\n if PriceListCost <> 0 then begin\n- ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityBase(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n+ ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityForUOM(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n ConvertPriceToCurrency(RequisitionLine.\"Currency Code\", SubcontractorPrice.\"Currency Code\", PriceListCost, DirectCost);\n end;\n RequisitionLine.\"Direct Unit Cost\" := DirectCost;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..73e138fe61 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -3401,6 +3401,77 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.AreEqual('', ToPurchaseHeader.\"Subc. Location Code\", 'Subc. Location Code should not be copied from archive by Copy Document');\n end;\n \n+ [Test]\n+ procedure WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion()\n+ var\n+ Item: Record Item;\n+ ItemUOM: Record \"Item Unit of Measure\";\n+ Vendor: Record Vendor;\n+ WorkCenter: Record \"Work Center\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ SubcPriceManagement: Codeunit \"Subc. Price Management\";\n+ QtyPerSet: Integer;\n+ PriceListUnitCost: Decimal;\n+ begin\n+ // [SCENARIO 636078] Calculate Subcontracts must compute Direct Unit Cost on the Subcontracting\n+ // Worksheet using the per-UoM conversion factor (GetQuantityForUOM()), not the total base\n+ // quantity (GetQuantityBase()) of the order.\n+\n+ // [GIVEN] Item with PCS base UoM and a SET alternative UoM (10 PCS per SET).\n+ Initialize();\n+ LibraryInventory.CreateItem(Item);\n+ QtyPerSet := 10;\n+ LibraryInventory.CreateItemUnitOfMeasureCode(ItemUOM, Item.\"No.\", QtyPerSet);\n+\n+ // [GIVEN] Vendor and Work Center with the vendor as its subcontractor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+ LibraryManufacturing.CreateWorkCenter(WorkCenter);\n+ WorkCenter.Validate(\"Subcontractor No.\", Vendor.\"No.\");\n+ WorkCenter.Modify(true);\n+\n+ // [GIVEN] A subcontractor price in PCS with Minimum Quantity 1 and Direct Unit Cost 1000.\n+ PriceListUnitCost := 1000;\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter.\"No.\", Vendor.\"No.\", Item.\"No.\", '', '', WorkDate(), Item.\"Base Unit of Measure\", 1, '');\n+ SubcontractorPrice.Validate(\"Direct Unit Cost\", PriceListUnitCost);\n+ SubcontractorPrice.Modify(true);\n+\n+ // [GIVEN] A staged Requisition Line for 3 SET (= 30 PCS in base UoM).\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := ItemUOM.Code;\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 3;\n+\n+ // [WHEN] The subcontractor price is applied to the requisition line.\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost = price-list cost * Qty-per-UoM (1000 * 10 = 10000),\n+ // not price-list cost * total base quantity (1000 * 30 = 30000 — the pre-fix behavior).\n+ Assert.AreEqual(\n+ PriceListUnitCost * QtyPerSet, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost on the Subcontracting Worksheet must be derived from Qty. per Unit of Measure, not from total base quantity.');\n+\n+ // [WHEN] The same price is applied to a Requisition Line using the base UoM (no conversion needed).\n+ Clear(RequisitionLine);\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := Item.\"Base Unit of Measure\";\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 30;\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost equals the price-list cost (the same-UoM path is unchanged by the fix).\n+ Assert.AreEqual(\n+ PriceListUnitCost, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost must equal the price-list cost when the worksheet UoM matches the price-list UoM.');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. Subcontracting Test\");\n"} +{"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8286", "base_commit": "70fd0246a0a4dbc72cb183ca719106722c03be4d", "created_at": "2026-05-22T13:07:41Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\nindex dfb07f0502..a005fa7b7c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n@@ -436,7 +436,7 @@ codeunit 99001508 \"Subc. Price Management\"\n \n GetPriceByUOM(SubcontractorPrice, PriceListQty, PriceListCost);\n if PriceListCost <> 0 then begin\n- ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityBase(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n+ ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityForUOM(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n ConvertPriceToCurrency(RequisitionLine.\"Currency Code\", SubcontractorPrice.\"Currency Code\", PriceListCost, DirectCost);\n end;\n RequisitionLine.\"Direct Unit Cost\" := DirectCost;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..73e138fe61 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -3401,6 +3401,77 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.AreEqual('', ToPurchaseHeader.\"Subc. Location Code\", 'Subc. Location Code should not be copied from archive by Copy Document');\n end;\n \n+ [Test]\n+ procedure WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion()\n+ var\n+ Item: Record Item;\n+ ItemUOM: Record \"Item Unit of Measure\";\n+ Vendor: Record Vendor;\n+ WorkCenter: Record \"Work Center\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ SubcPriceManagement: Codeunit \"Subc. Price Management\";\n+ QtyPerSet: Integer;\n+ PriceListUnitCost: Decimal;\n+ begin\n+ // [SCENARIO 636078] Calculate Subcontracts must compute Direct Unit Cost on the Subcontracting\n+ // Worksheet using the per-UoM conversion factor (GetQuantityForUOM()), not the total base\n+ // quantity (GetQuantityBase()) of the order.\n+\n+ // [GIVEN] Item with PCS base UoM and a SET alternative UoM (10 PCS per SET).\n+ Initialize();\n+ LibraryInventory.CreateItem(Item);\n+ QtyPerSet := 10;\n+ LibraryInventory.CreateItemUnitOfMeasureCode(ItemUOM, Item.\"No.\", QtyPerSet);\n+\n+ // [GIVEN] Vendor and Work Center with the vendor as its subcontractor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+ LibraryManufacturing.CreateWorkCenter(WorkCenter);\n+ WorkCenter.Validate(\"Subcontractor No.\", Vendor.\"No.\");\n+ WorkCenter.Modify(true);\n+\n+ // [GIVEN] A subcontractor price in PCS with Minimum Quantity 1 and Direct Unit Cost 1000.\n+ PriceListUnitCost := 1000;\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter.\"No.\", Vendor.\"No.\", Item.\"No.\", '', '', WorkDate(), Item.\"Base Unit of Measure\", 1, '');\n+ SubcontractorPrice.Validate(\"Direct Unit Cost\", PriceListUnitCost);\n+ SubcontractorPrice.Modify(true);\n+\n+ // [GIVEN] A staged Requisition Line for 3 SET (= 30 PCS in base UoM).\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := ItemUOM.Code;\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 3;\n+\n+ // [WHEN] The subcontractor price is applied to the requisition line.\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost = price-list cost * Qty-per-UoM (1000 * 10 = 10000),\n+ // not price-list cost * total base quantity (1000 * 30 = 30000 — the pre-fix behavior).\n+ Assert.AreEqual(\n+ PriceListUnitCost * QtyPerSet, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost on the Subcontracting Worksheet must be derived from Qty. per Unit of Measure, not from total base quantity.');\n+\n+ // [WHEN] The same price is applied to a Requisition Line using the base UoM (no conversion needed).\n+ Clear(RequisitionLine);\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := Item.\"Base Unit of Measure\";\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 30;\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost equals the price-list cost (the same-UoM path is unchanged by the fix).\n+ Assert.AreEqual(\n+ PriceListUnitCost, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost must equal the price-list cost when the worksheet UoM matches the price-list UoM.');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. Subcontracting Test\");\n"} From ec58029a353d11b121336f9b3fe590200f40ee15 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 22 Jun 2026 05:45:54 +0000 Subject: [PATCH 11/14] auto: collect candidates from microsoft/BCApps --- dataset/bcbench.jsonl | 5 ++ .../microsoft__BCApps-8386/README.md | 39 ++++++++++++++ .../microsoft__BCApps-8600/README.md | 24 +++++++++ .../microsoft__BCApps-8612/README.md | 54 +++++++++++++++++++ .../microsoft__BCApps-8616/README.md | 21 ++++++++ .../microsoft__BCApps-8632/README.md | 15 ++++++ 6 files changed, 158 insertions(+) create mode 100644 dataset/problemstatement/microsoft__BCApps-8386/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8600/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8612/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8616/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8632/README.md diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index 54796b9fb..fbe312865 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -99,3 +99,8 @@ {"metadata": {"area": "inventory", "image_count": 0}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-178045", "base_commit": "22d8978231eb8792d03f150d61431d485d3c92a9", "created_at": "2024-03-11", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137404, "functionName": ["ConsumptionIsPostedForMultipleILEsOfSameLotNo"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al\nindex 9467380d9f9b..e1036e0420d9 100644\n--- a/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMManufacturing.Codeunit.al\n@@ -47,6 +47,7 @@ codeunit 137404 \"SCM Manufacturing\"\n Capacity2: Decimal;\n GLB_ItemTrackingQty: Integer;\n GLB_SerialNo: Code[50];\n+ ItemTrackingMode: Option \" \",\"Assign Lot No.\",\"Select Entries\",\"Update Quantity\",\"Manual Lot No.\"; \n DocumentNoDoesNotExistErr: Label 'Document No. %1 does not exist.', Comment = '%1: Document number (Code)';\n ExpectedQuantityErr: Label 'Quantity must be %1.', Comment = '%1: Quantity (decimal value)';\n ModifyRtngErr: Label 'You cannot modify Routing No. %1 because there is at least one %2 associated with it.';\n@@ -80,6 +81,7 @@ codeunit 137404 \"SCM Manufacturing\"\n DidntExpectWhsePickMsg: Label 'Did not expect a Warehouse Pick Request associated with the Production Order Component Line, since the line doesn''t have a postitive remaining quantity';\n ProdOrderNoHandlerErr: Label 'Prod. Order No. must be %1, actual value is %2.', Comment = '%1: Expected Prod. Order No. Value; %2: Actual Prod. Order No. Value.';\n ProdOrderStatusHandlerErr: Label 'Prod. Order Status must be %1, actual value is %2.', Comment = '%1: Expected Prod. Order Status Value; %2: Actual Prod. Order Status Value.';\n+ ItemLedgerEntryMustBeFoundErr: Label 'Item Ledger Entry must be found.';\n \n [Test]\n [HandlerFunctions('ConfirmHandlerTrue,OutputJournalItemtrackingPageHandler,MessageHandler')]\n@@ -4149,6 +4151,104 @@ codeunit 137404 \"SCM Manufacturing\"\n LibraryInventory.PostItemJournalLine(ItemJournalBatch.\"Journal Template Name\", ItemJournalBatch.Name);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('ItemTrackingAssignLotNoPageHandler,ProductionJournalPageHandlerOnlyConsumption,ConfirmHandlerTrue,MessageHandler')]\n+ procedure ConsumptionIsPostedForMultipleILEsOfSameLotNo()\n+ var\n+ CompItem, ProdItem : Record Item;\n+ Location: Record Location;\n+ UnitOfMeasure: Record \"Unit of Measure\";\n+ ItemUnitOfMeasure: Record \"Item Unit of Measure\";\n+ ItemTrackingCode: Record \"Item Tracking Code\";\n+ ProductionBOMHeader: Record \"Production BOM Header\";\n+ ProductionBOMLine: Record \"Production BOM Line\";\n+ ProductionOrder: Record \"Production Order\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ LotNo: Code[10];\n+ Quantity: Decimal;\n+ ReleasedProdOrder: TestPage \"Released Production Order\";\n+ begin\n+ // [SCENARIO 501830] Consumption is posted against multiple Item Ledger Entries of same Lot No. when you post Production Journal from a Released Production Order.\n+ Initialize();\n+\n+ // [GIVEN] Create Item Tracking Code.\n+ LibraryItemTracking.CreateItemTrackingCode(ItemTrackingCode, false, true);\n+\n+ // [GIVEN] Create Unit of Measure.\n+ LibraryInventory.CreateUnitOfMeasureCode(UnitOfMeasure);\n+\n+ // [GIVEN] Create Component Item with Unit of Measure.\n+ CreateItemWithUOM(CompItem, UnitOfMeasure, ItemUnitOfMeasure);\n+ CompItem.Validate(\"Replenishment System\", CompItem.\"Replenishment System\"::Purchase);\n+ CompItem.Validate(Reserve, CompItem.Reserve::Always);\n+ CompItem.Validate(\"Flushing Method\", CompItem.\"Flushing Method\"::Manual);\n+ CompItem.Validate(\"Item Tracking Code\", ItemTrackingCode.Code);\n+ CompItem.Modify(true);\n+\n+ // [GIVEN] Create Location with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+\n+ // [GIVEN] Create Production Item with Unit of Measure.\n+ CreateItemWithUOM(ProdItem, UnitOfMeasure, ItemUnitOfMeasure);\n+\n+ // [GIVEN] Generate and save Lot No. and Quantity in two different Variable.\n+ LotNo := Format(LibraryRandom.RandText(4));\n+ Quantity := LibraryRandom.RandIntInRange(35, 35);\n+\n+ // [GIVEN] Create and Post three Item Journal Lines with same Lot No.\n+ CreateAndPostItemJournalLineWithLotNo(CompItem.\"No.\", LibraryRandom.RandIntInRange(5, 5), LotNo, '', Location.Code, true);\n+ CreateAndPostItemJournalLineWithLotNo(CompItem.\"No.\", LibraryRandom.RandIntInRange(10, 10), LotNo, '', Location.Code, true);\n+ CreateAndPostItemJournalLineWithLotNo(CompItem.\"No.\", LibraryRandom.RandIntInRange(20, 20), LotNo, '', Location.Code, true);\n+\n+ // [GIVEN] Create a production BOM for the Production Item.\n+ LibraryManufacturing.CreateProductionBOMHeader(ProductionBOMHeader, ItemUnitOfMeasure.Code);\n+ LibraryManufacturing.CreateProductionBOMLine(\n+ ProductionBOMHeader,\n+ ProductionBOMLine,\n+ '',\n+ ProductionBOMLine.Type::Item,\n+ CompItem.\"No.\",\n+ LibraryRandom.RandIntInRange(1, 1));\n+\n+ // [GIVEN] Validate Unit of Measure in Production BOM.\n+ ProductionBOMLine.Validate(\"Unit of Measure Code\", ItemUnitOfMeasure.Code);\n+ ProductionBOMLine.Modify(true);\n+\n+ // [GIVEN] Change Status of Production BOM.\n+ LibraryManufacturing.UpdateProductionBOMStatus(ProductionBOMHeader, ProductionBOMHeader.Status::Certified);\n+\n+ // [GIVEN] Validate Replenishment System and Production BOM No. in Production Item.\n+ ProdItem.Validate(\"Replenishment System\", ProdItem.\"Replenishment System\"::\"Prod. Order\");\n+ ProdItem.Validate(\"Production BOM No.\", ProductionBOMHeader.\"No.\");\n+ ProdItem.Modify(true);\n+\n+ // [GIVEN] Create and Refresh Production Order.\n+ CreateAndRefreshProdOrder(\n+ ProductionOrder,\n+ ProductionOrder.Status::Released,\n+ ProdItem.\"No.\",\n+ Quantity,\n+ Location.Code,\n+ '');\n+\n+ // [GIVEN] Open Released Production Order page and run Production Journal action.\n+ ReleasedProdOrder.OpenEdit();\n+ ReleasedProdOrder.GoToRecord(ProductionOrder);\n+ LibraryVariableStorage.Enqueue(Quantity);\n+ LibraryVariableStorage.Enqueue(ItemTrackingMode::\"Assign Lot No.\");\n+ LibraryVariableStorage.Enqueue(LotNo);\n+ LibraryVariableStorage.Enqueue(Quantity);\n+ ReleasedProdOrder.ProdOrderLines.ProductionJournal.Invoke();\n+\n+ // [WHEN] Find Item Ledger Entry.\n+ ItemLedgerEntry.SetRange(\"Item No.\", CompItem.\"No.\");\n+ ItemLedgerEntry.SetRange(Quantity, -Quantity);\n+\n+ // [VERIFY] Item Ledger Entry is found.\n+ Assert.IsFalse(ItemLedgerEntry.IsEmpty(), ItemLedgerEntryMustBeFoundErr);\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -6772,6 +6872,39 @@ codeunit 137404 \"SCM Manufacturing\"\n ReservationPage.OK().Invoke();\n end;\n \n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure ItemTrackingAssignLotNoPageHandler(var ItemTrackingLines: TestPage \"Item Tracking Lines\")\n+ var\n+ DequeueVariable: Variant;\n+ begin\n+ LibraryVariableStorage.Dequeue(DequeueVariable);\n+ ItemTrackingMode := DequeueVariable;\n+ case ItemTrackingMode of\n+ ItemTrackingMode::\"Assign Lot No.\":\n+ begin\n+ ItemTrackingLines.\"Lot No.\".SetValue(LibraryVariableStorage.DequeueText());\n+ LibraryVariableStorage.Dequeue(DequeueVariable);\n+ ItemTrackingLines.\"Quantity (Base)\".SetValue(DequeueVariable);\n+ end;\n+ end;\n+ ItemTrackingLines.OK().Invoke();\n+ end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure ProductionJournalPageHandlerOnlyConsumption(var ProductionJournal: TestPage \"Production Journal\")\n+ var\n+ EntryType: Enum \"Item Ledger Entry Type\";\n+ begin\n+ Assert.IsTrue(ProductionJournal.FindFirstField(ProductionJournal.\"Entry Type\", EntryType::Output), '');\n+ ProductionJournal.\"Output Quantity\".SetValue(0);\n+ Assert.IsTrue(ProductionJournal.FindFirstField(ProductionJournal.\"Entry Type\", EntryType::Consumption), '');\n+ ProductionJournal.Quantity.SetValue(LibraryVariableStorage.DequeueDecimal());\n+ ProductionJournal.ItemTrackingLines.Invoke();\n+ ProductionJournal.Post.Invoke();\n+ end;\n+\n [PageHandler]\n procedure BOMStructurePageHandler(var BOMStructure: TestPage \"BOM Structure\")\n begin\n@@ -6840,5 +6973,74 @@ codeunit 137404 \"SCM Manufacturing\"\n DT2Time(ExpStartDateTime), DT2Time(ProdOrderLine.\"Starting Date-Time\"), StrSubstNo(WrongDateTimeErr, ProdOrderLine.FieldCaption(\"Starting Time\")));\n until ProdOrderLine.Next() = 0;\n end;\n+\n+ local procedure CreateItemWithUOM(\n+ var Item: Record Item;\n+ var UnitOfMeasure: Record \"Unit of Measure\";\n+ var ItemUnitOfMeasure: Record \"Item Unit of Measure\")\n+ begin\n+ LibraryInventory.CreateItem(Item);\n+\n+ LibraryInventory.CreateItemUnitOfMeasure(\n+ ItemUnitOfMeasure,\n+ Item.\"No.\",\n+ UnitOfMeasure.Code,\n+ LibraryRandom.RandInt(0));\n+\n+ Item.Validate(\"Base Unit of Measure\", UnitOfMeasure.Code);\n+ Item.Modify(true);\n+ end;\n+\n+ local procedure CreateAndPostItemJournalLineWithLotNo(\n+ ItemNo: Code[20];\n+ Quantity: Decimal;\n+ LotNo: Code[50];\n+ BinCode: Code[20];\n+ LocationCode: Code[10];\n+ Tracking: Boolean)\n+ var\n+ ItemJournalLine: Record \"Item Journal Line\";\n+ begin\n+ CreateItemJournalLine(ItemJournalLine, ItemNo, Quantity, BinCode, LocationCode);\n+ if Tracking then begin\n+ LibraryVariableStorage.Enqueue(ItemTrackingMode::\"Assign Lot No.\");\n+ LibraryVariableStorage.Enqueue(LotNo);\n+ LibraryVariableStorage.Enqueue(Quantity);\n+ ItemJournalLine.OpenItemTrackingLines(false);\n+ end;\n+ LibraryInventory.PostItemJournalLine(ItemJournalLine.\"Journal Template Name\", ItemJournalLine.\"Journal Batch Name\");\n+ end;\n+\n+ local procedure CreateItemJournalLine(var ItemJournalLine: Record \"Item Journal Line\"; ItemNo: Code[20]; Quantity: Decimal; BinCode: Code[20]; LocationCode: Code[10])\n+ var\n+ ItemJournalTemplate: Record \"Item Journal Template\";\n+ ItemJournalBatch: Record \"Item Journal Batch\";\n+ begin\n+ LibraryInventory.ClearItemJournal(ItemJournalTemplate, ItemJournalBatch);\n+ LibraryInventory.CreateItemJournalTemplate(ItemJournalTemplate);\n+ LibraryInventory.CreateItemJournalBatch(ItemJournalBatch, ItemJournalTemplate.Name);\n+ LibraryInventory.CreateItemJournalLine(\n+ ItemJournalLine,\n+ ItemJournalBatch.\"Journal Template Name\",\n+ ItemJournalBatch.Name,\n+ ItemJournalLine.\"Entry Type\"::\"Positive Adjmt.\",\n+ ItemNo,\n+ Quantity);\n+\n+ ItemJournalLine.Validate(\"Unit Cost\", LibraryRandom.RandDec(10, 2));\n+ ItemJournalLine.Validate(\"Location Code\", LocationCode);\n+ ItemJournalLine.Validate(\"Bin Code\", BinCode);\n+ ItemJournalLine.Modify(true);\n+ end;\n+\n+ local procedure CreateAndRefreshProdOrder(var ProductionOrder: Record \"Production Order\"; Status: Enum \"Production Order Status\"; SourceNo: Code[20]; Quantity: Decimal; LocationCode: Code[10]; BinCode: Code[20])\n+ begin\n+ LibraryManufacturing.CreateProductionOrder(ProductionOrder, Status, ProductionOrder.\"Source Type\"::Item, SourceNo, Quantity);\n+ ProductionOrder.Validate(\"Location Code\", LocationCode);\n+ ProductionOrder.Validate(\"Bin Code\", BinCode);\n+ ProductionOrder.Modify(true);\n+\n+ LibraryManufacturing.RefreshProdOrder(ProductionOrder, false, true, true, true, false);\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al b/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al\nindex 7e739c297201..ffe0b880ce8d 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Posting/ItemJnlPostLine.Codeunit.al\n@@ -1946,8 +1946,11 @@ codeunit 22 \"Item Jnl.-Post Line\"\n Abs(ItemLedgEntry.\"Remaining Quantity\" - ItemLedgEntry.\"Reserved Quantity\")\n then\n AppliedQty := ItemLedgEntry.\"Remaining Quantity\" - ItemLedgEntry.\"Reserved Quantity\"\n- else\n+ else begin\n AppliedQty := -(OldItemLedgEntry.\"Remaining Quantity\" - OldItemLedgEntry.\"Reserved Quantity\");\n+ if AppliedQty = 0 then\n+ AppliedQty := UpdateAppliedQtyIfConsumptionEntry(ItemLedgEntry, OldItemLedgEntry);\n+ end;\n \n OnApplyItemLedgEntryOnAfterCalcAppliedQty(OldItemLedgEntry, ItemLedgEntry, AppliedQty);\n \n@@ -5908,6 +5911,17 @@ codeunit 22 \"Item Jnl.-Post Line\"\n (ItemJournalLine.\"Applies-to Entry\" <> 0)));\n end;\n \n+ local procedure UpdateAppliedQtyIfConsumptionEntry(ItemLedgerEntry: Record \"Item Ledger Entry\"; OldItemLedgerEntry: Record \"Item Ledger Entry\"): Decimal\n+ begin\n+ if ItemLedgerEntry.\"Entry Type\" <> ItemLedgerEntry.\"Entry Type\"::Consumption then\n+ exit(0);\n+\n+ if (ItemLedgerEntry.\"Remaining Quantity\" + OldItemLedgerEntry.\"Remaining Quantity\") > 0 then\n+ exit(0);\n+\n+ exit(-Abs(OldItemLedgerEntry.\"Reserved Quantity\"));\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnBeforeAllowProdApplication(OldItemLedgerEntry: Record \"Item Ledger Entry\"; ItemLedgerEntry: Record \"Item Ledger Entry\"; var AllowApplication: Boolean)\n begin\n"} {"metadata": {"area": "inventory", "image_count": 7}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-176082", "base_commit": "cb30d50fe1ed2c716c6349370fdc31c6bd0ce956", "created_at": "2024-02-23", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\SCM"], "FAIL_TO_PASS": [{"codeunitID": 137038, "functionName": ["GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\nindex e0b3ba5f0bf7..ffa98cfbb351 100644\n--- a/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n+++ b/App/Layers/W1/Tests/SCM/SCMTransfers.Codeunit.al\n@@ -48,6 +48,7 @@\n UndoneTransLineQtyErr: Label 'Expected Quantity to be 0 after Transfer Shipment was undone';\n DerivedTransLineErr: Label 'Expected no Derived Transfer Line i.e. line with \"Derived From Line No.\" equal to original transfer line.';\n IncorrectSNUndoneErr: Label 'The Serial No. of the item on the transfer shipment line that was undone was different from the SN on the corresponding transfer line.';\n+ ApplToItemEntryErr: Label '%1 must be %2 in %3.', Comment = '%1 is Appl-to Item Entry, %2 is Item Ledger Entry No. and %3 is Transfer Line';\n \n [Test]\n [HandlerFunctions('MessageHandler')]\n@@ -3655,6 +3656,99 @@\n ItemLedgerEntry.TestField(\"Cost Amount (Actual)\", NewCost);\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('PostedPurchaseReceiptsModalPageHandler,PostedPurchRcptLinesModalPageHandler')]\n+ procedure GetReceiptLinesShowListOfPostedPurchRcptsHavingTransferFromCodeInLocationCodeOfPurchRcptLines()\n+ var\n+ Item: Record Item;\n+ Vendor: Record Vendor;\n+ Location: Record Location;\n+ Location2: Record Location;\n+ Location3: Record Location;\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseHeader2: Record \"Purchase Header\";\n+ PurchaseHeader3: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ PurchaseLine2: Record \"Purchase Line\";\n+ PurchaseLine3: Record \"Purchase Line\";\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ TransferHeader: Record \"Transfer Header\";\n+ TransferLine: Record \"Transfer Line\";\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ ItemLedgerEntryNo: Integer;\n+ PurchaseReceiptNo: Code[20];\n+ TransferOrder: TestPage \"Transfer Order\";\n+ begin\n+ // [SCENARIO 500597] Get Receipt Lines action on Transfer Order shows list of Posted Purchase Receipts having Transfer-from Code in Location Code of Purch Rcpt Lines and after selecting it populates Appl-to Item Entry field in Transfer Lines.\n+ Initialize();\n+\n+ // [GIVEN] Create an Item and Validate Costing Method.\n+ LibraryInventory.CreateItem(Item);\n+ Item.Validate(\"Costing Method\", Item.\"Costing Method\"::FIFO);\n+ Item.Modify(true);\n+\n+ // [GIVEN] Create two Locations with Inventory Posting Setup.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location2);\n+\n+ // [GIVEN] Create another Location with Inventory Posting Setup \n+ // And Validate Use As In-Transit.\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location3);\n+ Location3.Validate(\"Use As In-Transit\", true);\n+ Location3.Modify(true);\n+\n+ // [GIVEN] Create a Vendor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+\n+ // [GIVEN] Create and Post Purchase Receipt with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader, PurchaseLine, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 2 with Location Code on Header.\n+ CreateAndPostPurchRcptWithLocationCodeInPurchHeader(PurchaseHeader2, PurchaseLine2, Vendor, Item, Location);\n+\n+ // [GIVEN] Create and Post Purchase Receipt 3 with Location Code on Line.\n+ PurchaseReceiptNo := CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ PurchaseHeader3,\n+ PurchaseLine3,\n+ Vendor,\n+ Item,\n+ Location);\n+\n+ // [GIVEN] Find and save Item Ledger Entry No. in a Variable.\n+ ItemLedgerEntry.SetRange(\"Document No.\", PurchaseReceiptNo);\n+ ItemLedgerEntry.FindFirst();\n+ ItemLedgerEntryNo := ItemLedgerEntry.\"Entry No.\";\n+\n+ // [GIVEN] Find Purch. Rcpt Line.\n+ FindRandomReceiptLine(PurchaseReceiptNo, PurchRcptLine);\n+\n+ // [GIVEN] Create Transfer Header.\n+ LibraryInventory.CreateTransferHeader(TransferHeader, Location.Code, Location2.Code, Location3.Code);\n+\n+ // [GIVEN] Open Transfer Order page and run Get Receipt Line action.\n+ TransferOrder.OpenEdit();\n+ TransferOrder.GoToRecord(TransferHeader);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchaseReceiptNo);\n+ LibraryVariableStorage.Enqueue(PurchRcptLine.\"No.\");\n+ TransferOrder.GetReceiptLines.Invoke();\n+\n+ // [WHEN] Find Transfer Line.\n+ TransferLine.SetRange(\"Document No.\", TransferHeader.\"No.\");\n+ TransferLine.FindFirst();\n+\n+ // [VERIFY] Appl-to Item Entry and Item Ledger Entry No. are same.\n+ Assert.AreEqual(\n+ ItemLedgerEntryNo,\n+ TransferLine.\"Appl.-to Item Entry\",\n+ StrSubstNo(\n+ ApplToItemEntryErr,\n+ TransferLine.FieldCaption(\"Appl.-to Item Entry\"),\n+ ItemLedgerEntryNo,\n+ TransferLine.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -5168,6 +5262,52 @@\n Assert.AreEqual(LineCount, TransferReceiptLine.Count(), '');\n end;\n \n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchHeader(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location)\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ PurchaseHeader.Validate(\"Location Code\", Location.Code);\n+ PurchaseHeader.Modify(true);\n+\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+ end;\n+\n+ local procedure CreateAndPostPurchRcptWithLocationCodeInPurchLine(\n+ var PurchaseHeader: Record \"Purchase Header\";\n+ var PurchaseLine: Record \"Purchase Line\";\n+ Vendor: Record Vendor;\n+ Item: Record Item;\n+ Location: Record Location): Code[20]\n+ begin\n+ LibraryPurchase.CreatePurchHeader(PurchaseHeader, PurchaseHeader.\"Document Type\"::Order, Vendor.\"No.\");\n+ LibraryPurchase.CreatePurchaseLine(\n+ PurchaseLine,\n+ PurchaseHeader,\n+ PurchaseLine.Type::Item,\n+ Item.\"No.\",\n+ LibraryRandom.RandIntInRange(10, 10));\n+\n+ PurchaseLine.Validate(\"Location Code\", Location.Code);\n+ PurchaseLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandInt(15000));\n+ PurchaseLine.Modify(true);\n+\n+ exit(LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false));\n+ end;\n+\n [MessageHandler]\n [Scope('OnPrem')]\n procedure MessageHandler(Message: Text[1024])\n@@ -5394,5 +5534,19 @@\n // 0 = Item.Type::Inventory\n Assert.AreEqual('0', ItemList.Filter.GetFilter(\"Type\"), 'Item List contains non-inventory items.');\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure PostedPurchRcptLinesModalPageHandler(var PostedPurchaseReceiptLines: Page \"Posted Purchase Receipt Lines\"; var Response: Action)\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ begin\n+ PurchRcptLine.SetRange(\"Document No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.SetRange(\"No.\", LibraryVariableStorage.DequeueText());\n+ PurchRcptLine.FindFirst();\n+ PostedPurchaseReceiptLines.SetRecord(PurchRcptLine);\n+\n+ Response := ACTION::LookupOK;\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\nindex 5fe44b4568d1..c16ab8669925 100644\n--- a/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n+++ b/App/Layers/W1/BaseApp/Inventory/Transfer/TransferHeader.Table.al\n@@ -1304,7 +1304,7 @@ table 5740 \"Transfer Header\"\n TempPurchRcptHeader: Record \"Purch. Rcpt. Header\" temporary;\n PostedPurchaseReceipts: Page \"Posted Purchase Receipts\";\n begin\n- PurchRcptHeader.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ FindPurchRcptHeader(PurchRcptHeader);\n PostedPurchaseReceipts.SetTableView(PurchRcptHeader);\n PostedPurchaseReceipts.LookupMode := true;\n if PostedPurchaseReceipts.RunModal() = ACTION::LookupOK then begin\n@@ -1376,6 +1376,8 @@ table 5740 \"Transfer Header\"\n PurchRcptLine.FilterPstdDocLnItemLedgEntries(ItemLedgerEntry);\n ItemTrackingDocMgt.CopyItemLedgerEntriesToTemp(TempItemLedgerEntry, ItemLedgerEntry);\n ItemTrackingMgt.CopyItemLedgEntryTrkgToTransferLine(TempItemLedgerEntry, TransferLine);\n+ TransferLine.\"Appl.-to Item Entry\" := ItemLedgerEntry.\"Entry No.\";\n+ TransferLine.Modify(true);\n \n OnAfterAddTransferLineFromReceiptLine(TransferLine, PurchRcptLine, TempItemLedgerEntry, Rec);\n end;\n@@ -1546,6 +1548,31 @@ table 5740 \"Transfer Header\"\n end;\n end;\n \n+ local procedure FindPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\")\n+ var\n+ PurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ DocumentNo: Code[20];\n+ begin\n+ PurchRcptLine.SetLoadFields(\"Document No.\", \"Location Code\");\n+ PurchRcptLine.SetCurrentKey(\"Document No.\");\n+ PurchRcptLine.SetRange(\"Location Code\", \"Transfer-from Code\");\n+ if PurchRcptLine.FindSet() then\n+ repeat\n+ GetPurchRcptHeader(PurchRcptHeader, PurchRcptLine, DocumentNo);\n+ until PurchRcptLine.Next() = 0;\n+ PurchRcptHeader.MarkedOnly(true);\n+ end;\n+\n+ local procedure GetPurchRcptHeader(var PurchRcptHeader: Record \"Purch. Rcpt. Header\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var DocumentNo: Code[20])\n+ begin\n+ if PurchRcptLine.\"Document No.\" = DocumentNo then\n+ exit;\n+\n+ PurchRcptHeader.Get(PurchRcptLine.\"Document No.\");\n+ PurchRcptHeader.Mark(true);\n+ DocumentNo := PurchRcptLine.\"Document No.\";\n+ end;\n+\n [IntegrationEvent(false, false)]\n local procedure OnAddTransferLineFromReceiptLineOnBeforeTransferLineInsert(var TransferLine: Record \"Transfer Line\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; var TransferHeader: Record \"Transfer Header\")\n begin\n"} {"metadata": {"area": "crm", "image_count": 8}, "repo": "microsoftInternal/NAV", "instance_id": "microsoftInternal__NAV-174087", "base_commit": "74a0b7c175da3f9a272745bd34453a4712b73e7b", "created_at": "2024-02-02", "environment_setup_version": "24.0", "project_paths": ["App\\Layers\\W1\\BaseApp", "App\\Layers\\W1\\Tests\\TestLibraries", "App\\Layers\\W1\\Tests\\Marketing"], "FAIL_TO_PASS": [{"codeunitID": 136208, "functionName": ["PopulateEvaluationFieldInInteractionLogEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\nindex 4c4c73700d2a..59fff6e2be93 100644\n--- a/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n+++ b/App/Layers/W1/Tests/Marketing/MarketingInteraction.Codeunit.al\n@@ -45,6 +45,7 @@ codeunit 136208 \"Marketing Interaction\"\n LoggedSegemntEntriesCreateMsg: Label 'Logged Segment entry was created';\n AttachmentFileShouldNotBeBlankErr: Label 'Attachment File should not be blank.';\n TxtFileExt: Label 'txt';\n+ EvaluationErr: Label '%1 must be %2 in %3', Comment = '%1 = Evaluation, %2 = Positive, %3 = Interaction Log Entry';\n \n [Test]\n [Scope('OnPrem')]\n@@ -2998,6 +2999,50 @@ codeunit 136208 \"Marketing Interaction\"\n VerifyAttachmentFileIsNotBlankOnInteractionLogEntry(Contact.\"No.\");\n end;\n \n+ [Test]\n+ [Scope('OnPrem')]\n+ [HandlerFunctions('CreateInteractionFromContactPageHandler')]\n+ procedure PopulateEvaluationFieldInInteractionLogEntry()\n+ var\n+ Contact: Record Contact;\n+ InteractionTemplate: Record \"Interaction Template\";\n+ InteractionLogEntry: Record \"Interaction Log Entry\";\n+ ContactCard: TestPage \"Contact Card\";\n+ InteractionEvaluation: Enum \"Interaction Evaluation\";\n+ begin\n+ // [SCENARIO 498395] When stan creates an Interaction using Create Interaction action from Contact, Evaluation field should be populated in Interaction Log Entry.\n+ Initialize();\n+\n+ // [GIVEN] Create a Contact.\n+ LibraryMarketing.CreateCompanyContact(Contact);\n+\n+ // [GIVEN] Create an Interaction Template and Validate Information Flow.\n+ LibraryMarketing.CreateInteractionTemplate(InteractionTemplate);\n+ InteractionTemplate.Validate(\"Information Flow\", InteractionTemplate.\"Information Flow\"::Outbound);\n+ InteractionTemplate.Modify(true);\n+\n+ // [GIVEN] Open Contact Card and Create Interaction.\n+ ContactCard.OpenEdit();\n+ ContactCard.GoToRecord(Contact);\n+ LibraryVariableStorage.Enqueue(InteractionTemplate.Code);\n+ LibraryVariableStorage.Enqueue(Format(InteractionEvaluation::Positive));\n+ ContactCard.\"Create &Interaction\".Invoke();\n+\n+ // [WHEN] Find Interaction Log Entry.\n+ InteractionLogEntry.SetRange(\"Contact No.\", Contact.\"No.\");\n+ InteractionLogEntry.FindFirst();\n+\n+ // [VERIFY] Interaction Log Entry has Evaluation field populated as Positive.\n+ Assert.AreEqual(\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.Evaluation,\n+ StrSubstNo(\n+ EvaluationErr,\n+ InteractionLogEntry.FieldCaption(Evaluation),\n+ InteractionEvaluation::Positive,\n+ InteractionLogEntry.TableCaption));\n+ end;\n+\n local procedure Initialize()\n var\n LibrarySales: Codeunit \"Library - Sales\";\n@@ -4309,5 +4354,16 @@ CopyStr(StorageLocation, 1, MaxStrLen(MarketingSetup.\"Attachment Storage Locatio\n CreateInteraction.NextInteraction.Invoke();\n CreateInteraction.Finish.Invoke();\n end;\n+\n+ [ModalPageHandler]\n+ [Scope('OnPrem')]\n+ procedure CreateInteractionFromContactPageHandler(var CreateInteraction: TestPage \"Create Interaction\")\n+ begin\n+ CreateInteraction.\"Interaction Template Code\".SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.NextInteraction.Invoke();\n+ CreateInteraction.Evaluation.SetValue(LibraryVariableStorage.DequeueText());\n+ CreateInteraction.FinishInteraction.Invoke();\n+ end;\n }\n \n", "patch": "diff --git a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\nindex ff43f4ff6a7b..05a21a6196bf 100644\n--- a/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n+++ b/App/Layers/W1/BaseApp/CRM/Segment/CreateInteraction.Page.al\n@@ -694,6 +694,7 @@ page 5077 \"Create Interaction\"\n end;\n Step::\"Step 4\":\n begin\n+ InteractionLogEntry.CopyFromSegment(Rec);\n InteractionLogEntry.Modify();\n CurrPage.Close();\n end;\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8632", "base_commit": "b3d3921ad18ebb9ae148c196ba465a7af8abb91f", "created_at": "2026-06-16T06:33:07Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchFactboxMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchFactboxMgmt.Codeunit.al\nindex a3dce9b95a..42b769b1c0 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchFactboxMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchFactboxMgmt.Codeunit.al\n@@ -376,6 +376,41 @@ codeunit 99001560 \"Subc. Purch. Factbox Mgmt.\"\n end;\n end;\n \n+ /// \n+ /// Opens the subcontracting transfer order(s) linked to the given production order.\n+ /// \n+ /// The production order to show the related subcontracting transfer orders for.\n+ procedure ShowTransferOrdersFromProductionOrder(ProductionOrder: Record \"Production Order\")\n+ var\n+ TransferHeader: Record \"Transfer Header\";\n+ TransferHeaderToOpen: Record \"Transfer Header\";\n+ TransferLine: Record \"Transfer Line\";\n+ PageManagement: Codeunit \"Page Management\";\n+ SelectionFilterMgt: Codeunit SelectionFilterManagement;\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ TransferLine.SetCurrentKey(\"Subc. Prod. Order No.\", \"Subc. Prod. Order Line No.\", \"Subc. Routing Reference No.\", \"Subc. Routing No.\", \"Subc. Operation No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+ TransferLine.SetRange(\"Derived From Line No.\", 0);\n+ if TransferLine.FindSet() then\n+ repeat\n+ if TransferHeader.Get(TransferLine.\"Document No.\") then\n+ TransferHeader.Mark(true);\n+ until TransferLine.Next() = 0;\n+ TransferHeader.MarkedOnly(true);\n+\n+ if TransferHeader.IsEmpty() then\n+ TransferHeaderToOpen.SetRange(\"No.\", '')\n+ else\n+ TransferHeaderToOpen.SetFilter(\"No.\", SelectionFilterMgt.GetSelectionFilterForTransferHeader(TransferHeader));\n+ PageManagement.PageRunList(TransferHeaderToOpen);\n+ end;\n+\n /// \n /// Returns the number of subcontractor prices matching the given purchase line.\n /// \ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrder.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrder.PageExt.al\nindex 3fe5eb00ce..9305138f0c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrder.PageExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrder.PageExt.al\n@@ -1,55 +1,69 @@\n-// ------------------------------------------------------------------------------------------------\n-// Copyright (c) Microsoft Corporation. All rights reserved.\n-// Licensed under the MIT License. See License.txt in the project root for license information.\n-// ------------------------------------------------------------------------------------------------\n-namespace Microsoft.Manufacturing.Subcontracting;\n-\n-using Microsoft.Inventory.Ledger;\n-using Microsoft.Manufacturing.Document;\n-using Microsoft.Purchases.Document;\n-\n-pageextension 99001548 \"Subc. Finished Prod. Order\" extends \"Finished Production Order\"\n-{\n- actions\n- {\n- addafter(\"Registered Put-away Lines\")\n- {\n- action(\"Subcontracting Purchase Lines\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting Order Lines';\n- Image = SubcontractingWorksheet;\n- RunObject = page \"Purchase Lines\";\n- RunPageLink = \"Document Type\" = const(Order), \"Prod. Order No.\" = field(\"No.\");\n- ToolTip = 'Show purchase order lines for subcontracting.';\n- }\n- }\n- addafter(\"&Warehouse Entries\")\n- {\n- action(\"Subc. Transfer Entries\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting Transfer Entries';\n- Image = ItemLedger;\n- RunObject = page \"Item Ledger Entries\";\n- RunPageLink = \"Entry Type\" = const(Transfer), \"Subc. Prod. Order No.\" = field(\"No.\");\n- RunPageView = sorting(\"Order Type\", \"Order No.\");\n- ToolTip = 'View the list of subcontracting transfers.';\n- }\n- action(\"WIP Ledger Entries\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting WIP Entries';\n- Image = LedgerEntries;\n- RunObject = page \"Subc. WIP Ledger Entries\";\n- RunPageLink = \"Prod. Order Status\" = field(Status), \"Prod. Order No.\" = field(\"No.\");\n- ToolTip = 'View the Subcontracting WIP Entries for this production order.';\n- }\n- }\n- addlast(Category_Entries)\n- {\n- actionref(\"Subc. Transfer Entries_Promoted\"; \"Subc. Transfer Entries\") { }\n- actionref(\"WIP Ledger Entries_Promoted\"; \"WIP Ledger Entries\") { }\n- }\n- }\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+namespace Microsoft.Manufacturing.Subcontracting;\n+\n+using Microsoft.Inventory.Ledger;\n+using Microsoft.Manufacturing.Document;\n+using Microsoft.Purchases.Document;\n+\n+pageextension 99001548 \"Subc. Finished Prod. Order\" extends \"Finished Production Order\"\n+{\n+ actions\n+ {\n+ addafter(\"Registered Put-away Lines\")\n+ {\n+ action(\"Subcontracting Purchase Lines\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Order Lines';\n+ Image = SubcontractingWorksheet;\n+ RunObject = page \"Purchase Lines\";\n+ RunPageLink = \"Document Type\" = const(Order), \"Prod. Order No.\" = field(\"No.\");\n+ ToolTip = 'Show purchase order lines for subcontracting.';\n+ }\n+ }\n+ addafter(\"&Warehouse Entries\")\n+ {\n+ action(\"Subc. Transfer Orders\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Orders';\n+ Image = TransferOrder;\n+ ToolTip = 'View the subcontracting transfer orders related to this production order.';\n+\n+ trigger OnAction()\n+ var\n+ SubcPurchFactboxMgmt: Codeunit \"Subc. Purch. Factbox Mgmt.\";\n+ begin\n+ SubcPurchFactboxMgmt.ShowTransferOrdersFromProductionOrder(Rec);\n+ end;\n+ }\n+ action(\"Subc. Transfer Entries\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Entries';\n+ Image = ItemLedger;\n+ RunObject = page \"Item Ledger Entries\";\n+ RunPageLink = \"Entry Type\" = const(Transfer), \"Subc. Prod. Order No.\" = field(\"No.\");\n+ RunPageView = sorting(\"Order Type\", \"Order No.\");\n+ ToolTip = 'View the list of subcontracting transfers.';\n+ }\n+ action(\"WIP Ledger Entries\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting WIP Entries';\n+ Image = LedgerEntries;\n+ RunObject = page \"Subc. WIP Ledger Entries\";\n+ RunPageLink = \"Prod. Order Status\" = field(Status), \"Prod. Order No.\" = field(\"No.\");\n+ ToolTip = 'View the Subcontracting WIP Entries for this production order.';\n+ }\n+ }\n+ addlast(Category_Entries)\n+ {\n+ actionref(\"Subc. Transfer Entries_Promoted\"; \"Subc. Transfer Entries\") { }\n+ actionref(\"WIP Ledger Entries_Promoted\"; \"WIP Ledger Entries\") { }\n+ }\n+ }\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrders.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrders.PageExt.al\nindex d6753ba257..ff954e609e 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrders.PageExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrders.PageExt.al\n@@ -1,50 +1,64 @@\n-// ------------------------------------------------------------------------------------------------\n-// Copyright (c) Microsoft Corporation. All rights reserved.\n-// Licensed under the MIT License. See License.txt in the project root for license information.\n-// ------------------------------------------------------------------------------------------------\n-namespace Microsoft.Manufacturing.Subcontracting;\n-\n-using Microsoft.Inventory.Ledger;\n-using Microsoft.Manufacturing.Document;\n-using Microsoft.Purchases.Document;\n-\n-pageextension 99001543 \"Subc. Finished Prod. Orders\" extends \"Finished Production Orders\"\n-{\n- actions\n- {\n- addafter(\"E&ntries\")\n- {\n- action(\"Subcontracting Purchase Lines\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting Order Lines';\n- Image = SubcontractingWorksheet;\n- RunObject = page \"Purchase Lines\";\n- RunPageLink = \"Document Type\" = const(Order), \"Prod. Order No.\" = field(\"No.\");\n- ToolTip = 'Show purchase order lines for subcontracting.';\n- }\n- }\n- addafter(\"&Warehouse Entries\")\n- {\n- action(\"Subc. Transfer Entries\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting Transfer Entries';\n- Image = ItemLedger;\n- RunObject = page \"Item Ledger Entries\";\n- RunPageLink = \"Entry Type\" = const(Transfer), \"Subc. Prod. Order No.\" = field(\"No.\");\n- RunPageView = sorting(\"Order Type\", \"Order No.\");\n- ToolTip = 'View the list of subcontracting transfers.';\n- }\n- action(\"WIP Ledger Entries\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting WIP Entries';\n- Image = LedgerEntries;\n- RunObject = page \"Subc. WIP Ledger Entries\";\n- RunPageLink = \"Prod. Order Status\" = field(Status), \"Prod. Order No.\" = field(\"No.\");\n- ToolTip = 'View the Subcontracting WIP Entries for this production order.';\n- }\n- }\n- }\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+namespace Microsoft.Manufacturing.Subcontracting;\n+\n+using Microsoft.Inventory.Ledger;\n+using Microsoft.Manufacturing.Document;\n+using Microsoft.Purchases.Document;\n+\n+pageextension 99001543 \"Subc. Finished Prod. Orders\" extends \"Finished Production Orders\"\n+{\n+ actions\n+ {\n+ addafter(\"E&ntries\")\n+ {\n+ action(\"Subcontracting Purchase Lines\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Order Lines';\n+ Image = SubcontractingWorksheet;\n+ RunObject = page \"Purchase Lines\";\n+ RunPageLink = \"Document Type\" = const(Order), \"Prod. Order No.\" = field(\"No.\");\n+ ToolTip = 'Show purchase order lines for subcontracting.';\n+ }\n+ }\n+ addafter(\"&Warehouse Entries\")\n+ {\n+ action(\"Subc. Transfer Orders\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Orders';\n+ Image = TransferOrder;\n+ ToolTip = 'View the subcontracting transfer orders related to this production order.';\n+\n+ trigger OnAction()\n+ var\n+ SubcPurchFactboxMgmt: Codeunit \"Subc. Purch. Factbox Mgmt.\";\n+ begin\n+ SubcPurchFactboxMgmt.ShowTransferOrdersFromProductionOrder(Rec);\n+ end;\n+ }\n+ action(\"Subc. Transfer Entries\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Entries';\n+ Image = ItemLedger;\n+ RunObject = page \"Item Ledger Entries\";\n+ RunPageLink = \"Entry Type\" = const(Transfer), \"Subc. Prod. Order No.\" = field(\"No.\");\n+ RunPageView = sorting(\"Order Type\", \"Order No.\");\n+ ToolTip = 'View the list of subcontracting transfers.';\n+ }\n+ action(\"WIP Ledger Entries\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting WIP Entries';\n+ Image = LedgerEntries;\n+ RunObject = page \"Subc. WIP Ledger Entries\";\n+ RunPageLink = \"Prod. Order Status\" = field(Status), \"Prod. Order No.\" = field(\"No.\");\n+ ToolTip = 'View the Subcontracting WIP Entries for this production order.';\n+ }\n+ }\n+ }\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrder.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrder.PageExt.al\nindex fae7afb0ca..7612fdcf78 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrder.PageExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrder.PageExt.al\n@@ -25,6 +25,20 @@ pageextension 99001504 \"Subc. Rel. Prod. Order\" extends \"Released Production Ord\n }\n addafter(\"&Warehouse Entries\")\n {\n+ action(\"Subc. Transfer Orders\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Orders';\n+ Image = TransferOrder;\n+ ToolTip = 'View the subcontracting transfer orders related to this production order.';\n+\n+ trigger OnAction()\n+ var\n+ SubcPurchFactboxMgmt: Codeunit \"Subc. Purch. Factbox Mgmt.\";\n+ begin\n+ SubcPurchFactboxMgmt.ShowTransferOrdersFromProductionOrder(Rec);\n+ end;\n+ }\n action(\"Subc. Transfer Entries\")\n {\n ApplicationArea = Subcontracting;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrders.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrders.PageExt.al\nindex a6a74dc3d3..0446a28a16 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrders.PageExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrders.PageExt.al\n@@ -25,6 +25,20 @@ pageextension 99001505 \"Subc. Rel. Prod. Orders\" extends \"Released Production Or\n }\n addafter(\"&Warehouse Entries\")\n {\n+ action(\"Subc. Transfer Orders\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Orders';\n+ Image = TransferOrder;\n+ ToolTip = 'View the subcontracting transfer orders related to this production order.';\n+\n+ trigger OnAction()\n+ var\n+ SubcPurchFactboxMgmt: Codeunit \"Subc. Purch. Factbox Mgmt.\";\n+ begin\n+ SubcPurchFactboxMgmt.ShowTransferOrdersFromProductionOrder(Rec);\n+ end;\n+ }\n action(\"Subc. Transfer Entries\")\n {\n ApplicationArea = Subcontracting;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["SubcTransferOrdersActionOnProductionOrdersListOpensRelatedTransferOrder", "SubcTransferOrdersActionOnProductionOrderOpensRelatedTransferOrder"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex c2ad504090..ef56e4265d 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -164,6 +164,72 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.RecordIsNotEmpty(TransferLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmHandler,HandleTransferOrder,HandleSubcTransferOrdersList')]\n+ procedure SubcTransferOrdersActionOnProductionOrderOpensRelatedTransferOrder()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ UnrelatedProductionOrder: Record \"Production Order\";\n+ ProductionLocation: Record Location;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedTransferOrderNo: Code[20];\n+ ReleasedProductionOrder: TestPage \"Released Production Order\";\n+ begin\n+ // [SCENARIO 638532] The Released Production Order card provides a navigation action to view only its related subcontracting transfer orders.\n+\n+ // [GIVEN] Subcontracting setup with two released production orders, each ending up with its own subcontracting purchase order and transfer order.\n+ // The transfer route is location-based (component location -> subcontractor location), so it is created only for the first order and reused by the second.\n+ SetupSubcontractingForTransferOrderTests(Item, WorkCenter, ProductionLocation);\n+ ExpectedTransferOrderNo := CreateProductionOrderWithSubcTransferOrder(Item, WorkCenter, ProductionLocation.Code, true, ProductionOrder);\n+ CreateProductionOrderWithSubcTransferOrder(Item, WorkCenter, ProductionLocation.Code, false, UnrelatedProductionOrder);\n+\n+ // [WHEN] Invoking the \"Subcontracting Transfer Orders\" action on the first production order card\n+ OpenedTransferOrderListNo := '';\n+ ReleasedProductionOrder.OpenView();\n+ ReleasedProductionOrder.GoToRecord(ProductionOrder);\n+ ReleasedProductionOrder.\"Subc. Transfer Orders\".Invoke();\n+ ReleasedProductionOrder.Close();\n+\n+ // [THEN] Only the related transfer order is shown - the handler asserts exactly one record, so the unrelated order is excluded\n+ Assert.AreEqual(\n+ ExpectedTransferOrderNo, OpenedTransferOrderListNo,\n+ 'The production order card action must open only the related subcontracting transfer order.');\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('ConfirmHandler,HandleTransferOrder,HandleSubcTransferOrdersList')]\n+ procedure SubcTransferOrdersActionOnProductionOrdersListOpensRelatedTransferOrder()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ UnrelatedProductionOrder: Record \"Production Order\";\n+ ProductionLocation: Record Location;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedTransferOrderNo: Code[20];\n+ ReleasedProductionOrders: TestPage \"Released Production Orders\";\n+ begin\n+ // [SCENARIO 638532] The Released Production Orders list provides a navigation action to view only the related subcontracting transfer orders.\n+\n+ // [GIVEN] Subcontracting setup with two released production orders, each ending up with its own subcontracting purchase order and transfer order.\n+ // The transfer route is location-based (component location -> subcontractor location), so it is created only for the first order and reused by the second.\n+ SetupSubcontractingForTransferOrderTests(Item, WorkCenter, ProductionLocation);\n+ ExpectedTransferOrderNo := CreateProductionOrderWithSubcTransferOrder(Item, WorkCenter, ProductionLocation.Code, true, ProductionOrder);\n+ CreateProductionOrderWithSubcTransferOrder(Item, WorkCenter, ProductionLocation.Code, false, UnrelatedProductionOrder);\n+\n+ // [WHEN] Invoking the \"Subcontracting Transfer Orders\" action on the first production order in the list\n+ OpenedTransferOrderListNo := '';\n+ ReleasedProductionOrders.OpenView();\n+ ReleasedProductionOrders.GoToRecord(ProductionOrder);\n+ ReleasedProductionOrders.\"Subc. Transfer Orders\".Invoke();\n+ ReleasedProductionOrders.Close();\n+\n+ // [THEN] Only the related transfer order is shown - the handler asserts exactly one record, so the unrelated order is excluded\n+ Assert.AreEqual(\n+ ExpectedTransferOrderNo, OpenedTransferOrderListNo,\n+ 'The production orders list action must open only the related subcontracting transfer order.');\n+ end;\n+\n [Test]\n [HandlerFunctions('ConfirmHandler,HandleTransferOrder')]\n procedure CannotDeleteSubcontractingOrderWithAssociatedTransferOrder()\n@@ -3013,6 +3079,15 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n TransfOrderPage.OK().Invoke();\n end;\n \n+ [PageHandler]\n+ procedure HandleSubcTransferOrdersList(var TransferOrders: TestPage \"Transfer Orders\")\n+ begin\n+ Assert.IsTrue(TransferOrders.First(), 'Expected at least one subcontracting transfer order in the list.');\n+ OpenedTransferOrderListNo := CopyStr(TransferOrders.\"No.\".Value(), 1, MaxStrLen(OpenedTransferOrderListNo));\n+ Assert.IsFalse(TransferOrders.Next(), 'Expected exactly one subcontracting transfer order in the list.');\n+ TransferOrders.OK().Invoke();\n+ end;\n+\n [ConfirmHandler]\n procedure ConfirmYesShowSubcontractingPurchOrders(Question: Text[1024]; var Reply: Boolean)\n begin\n@@ -3131,6 +3206,65 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n exit(RoutingLine.\"Operation No.\");\n end;\n \n+ local procedure SetupSubcontractingForTransferOrderTests(var Item: Record Item; var WorkCenter: array[2] of Record \"Work Center\"; var ProductionLocation: Record Location)\n+ var\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ begin\n+ Initialize();\n+ SubcontractingMgmtLibrary.UpdateManufacturingSetupWithSubcontractingLocation();\n+ SubcontractingMgmtLibrary.SetupInventorySetup();\n+\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ SubcontractingMgmtLibrary.UpdateProdBomWithComponentSupplyMethod(Item, \"Component Supply Method\"::\"Transfer to Vendor\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(ProductionLocation);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+ end;\n+\n+ local procedure CreateProductionOrderWithSubcTransferOrder(Item: Record Item; var WorkCenter: array[2] of Record \"Work Center\"; ProductionLocationCode: Code[10]; CreateTransferRouteForOrder: Boolean; var ProductionOrder: Record \"Production Order\"): Code[20]\n+ var\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ TransferHeader: Record \"Transfer Header\";\n+ ReleasedProdOrderRtng: TestPage \"Prod. Order Routing\";\n+ PurchaseHeaderPage: TestPage \"Purchase Order\";\n+ begin\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ SetAllProdOrderTransferComponentLocations(ProductionOrder.\"No.\", ProductionLocationCode);\n+ // The transfer route is keyed by from/to location, so it must be created only once for a given location pair.\n+ // Callers that reuse the same locations pass false for subsequent orders to reuse the existing route.\n+ if CreateTransferRouteForOrder then\n+ SubcontractingMgmtLibrary.CreateTransferRoute(WorkCenter[2], ProductionOrder);\n+\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", WorkCenter[2].\"No.\");\n+ ProdOrderRoutingLine.FindFirst();\n+ ReleasedProdOrderRtng.OpenView();\n+ ReleasedProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ ReleasedProdOrderRtng.CreateSubcontracting.Invoke();\n+ ReleasedProdOrderRtng.Close();\n+\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+\n+ PurchaseHeaderPage.OpenView();\n+ PurchaseHeaderPage.GoToRecord(PurchaseHeader);\n+ PurchaseHeaderPage.CreateTransfOrdToSubcontractor.Invoke();\n+ PurchaseHeaderPage.Close();\n+\n+ TransferHeader.SetRange(\"Subcontr. Purch. Order No.\", PurchaseHeader.\"No.\");\n+ Assert.IsTrue(TransferHeader.FindFirst(), 'Expected a subcontracting transfer order for the production order.');\n+ exit(TransferHeader.\"No.\");\n+ end;\n+\n local procedure CreateAndCalculateNeededWorkAndMachineCenter(var WorkCenter: array[2] of Record \"Work Center\"; var MachineCenter: array[2] of Record \"Machine Center\")\n var\n CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n@@ -3983,6 +4117,7 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n IsInitialized: Boolean;\n Subcontracting: Boolean;\n OpenedTransferOrderNo: Code[20];\n+ OpenedTransferOrderListNo: Code[20];\n PurchaseOrderPageOpened: Boolean;\n PurchaseLinesPageOpened: Boolean;\n UnitCostCalculation: Option Time,Units;\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8616", "base_commit": "096b97ae84daae3c907fe58295a761b331801a42", "created_at": "2026-06-15T21:29:21Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al\nindex 2631e38aec..8af3d51e41 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al\n@@ -4,7 +4,6 @@\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting;\n \n-using Microsoft.QualityManagement.Setup.ApplicationAreas;\n using System.Upgrade;\n \n codeunit 99001501 \"Subcontracting Install\"\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al b/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al\nindex 74a24a8bf0..42b5428962 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al\n@@ -3,8 +3,8 @@\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting;\n+\n using Microsoft.Manufacturing.Planning;\n-using Microsoft.QualityManagement.Setup.ApplicationAreas;\n \n permissionset 99001501 \"Subcontract. - Objs\"\n {\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al\nindex 260fe4b050..d1d232c956 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al\n@@ -49,6 +49,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Production Order';\n+ Enabled = Rec.\"Subc. Prod. Order No.\" <> '';\n Image = Production;\n ToolTip = 'View the related production order.';\n trigger OnAction()\n@@ -60,6 +61,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Production Order Routing';\n+ Enabled = Rec.\"Subc. Prod. Order No.\" <> '';\n Image = Route;\n ToolTip = 'View the related production order routing.';\n trigger OnAction()\n@@ -71,6 +73,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Production Order Components';\n+ Enabled = Rec.\"Subc. Prod. Order No.\" <> '';\n Image = Components;\n ToolTip = 'View the related production order components.';\n trigger OnAction()\n@@ -82,6 +85,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Subcontracting Purchase Order';\n+ Enabled = Rec.\"Subc. Purch. Order No.\" <> '';\n Image = Order;\n ToolTip = 'View the related subcontracting purchase order.';\n trigger OnAction()\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al\nindex 3449fe2689..88abec2181 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al\n@@ -2,7 +2,7 @@\n // Copyright (c) Microsoft Corporation. All rights reserved.\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n-namespace Microsoft.QualityManagement.Setup.ApplicationAreas;\n+namespace Microsoft.Manufacturing.Subcontracting;\n \n #if not CLEAN29\n using Microsoft.Manufacturing.Setup;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al\nindex 109321363f..6551dec314 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al\n@@ -2,7 +2,7 @@\n // Copyright (c) Microsoft Corporation. All rights reserved.\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n-namespace Microsoft.QualityManagement.Setup.ApplicationAreas;\n+namespace Microsoft.Manufacturing.Subcontracting;\n \n using System.Environment.Configuration;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139990, "functionName": ["ItemLedgerEntriesSubcActionsEnabledWhenSubcontracting", "ItemLedgerEntriesSubcActionsDisabledWhenNotSubcontracting"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al\nindex 46606182df..c598c8c43c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al\n@@ -4,6 +4,7 @@\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting.Test;\n \n+using Microsoft.Inventory.Ledger;\n using Microsoft.Inventory.Planning;\n using Microsoft.Inventory.Requisition;\n using Microsoft.Manufacturing.Capacity;\n@@ -588,6 +589,91 @@ codeunit 139990 \"Subc. Subcontracting UI Test\"\n PurchaseOrder.Close();\n end;\n \n+ [Test]\n+ procedure ItemLedgerEntriesSubcActionsDisabledWhenNotSubcontracting()\n+ var\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ ItemLedgerEntries: TestPage \"Item Ledger Entries\";\n+ begin\n+ // [SCENARIO 638458] Subcontracting actions on Item Ledger Entries are disabled when the entry has no subcontracting production order or purchase order.\n+ Initialize();\n+\n+ // [GIVEN] An Item Ledger Entry that is NOT related to subcontracting (no Subc. Prod. Order No. or Subc. Purch. Order No.)\n+ ItemLedgerEntry.Init();\n+ ItemLedgerEntry.\"Entry No.\" := GetNextItemLedgerEntryNo();\n+ ItemLedgerEntry.\"Item No.\" := 'TEST-ITEM';\n+ ItemLedgerEntry.\"Entry Type\" := ItemLedgerEntry.\"Entry Type\"::Purchase;\n+ ItemLedgerEntry.\"Subc. Prod. Order No.\" := '';\n+ ItemLedgerEntry.\"Subc. Purch. Order No.\" := '';\n+ ItemLedgerEntry.Insert();\n+\n+ // [WHEN] The Item Ledger Entries page is opened for that entry\n+ ItemLedgerEntries.OpenView();\n+ ItemLedgerEntries.GoToRecord(ItemLedgerEntry);\n+\n+ // [THEN] The Production Order action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Production Order\".Enabled(), ILEProdActionsEnabledErr);\n+ // [THEN] The Production Order Routing action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Production Order Routing\".Enabled(), ILEProdActionsEnabledErr);\n+ // [THEN] The Production Order Components action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Production Order Components\".Enabled(), ILEProdActionsEnabledErr);\n+ // [THEN] The Purchase Order action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Purchase Order\".Enabled(), ILEPurchActionsEnabledErr);\n+\n+ ItemLedgerEntries.Close();\n+\n+ // Cleanup\n+ ItemLedgerEntry.Delete();\n+ end;\n+\n+ [Test]\n+ procedure ItemLedgerEntriesSubcActionsEnabledWhenSubcontracting()\n+ var\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ ItemLedgerEntries: TestPage \"Item Ledger Entries\";\n+ begin\n+ // [SCENARIO 638458] Subcontracting actions on Item Ledger Entries are enabled when the entry is related to a subcontracting production order and purchase order.\n+ Initialize();\n+\n+ // [GIVEN] An Item Ledger Entry that IS related to subcontracting\n+ ItemLedgerEntry.Init();\n+ ItemLedgerEntry.\"Entry No.\" := GetNextItemLedgerEntryNo();\n+ ItemLedgerEntry.\"Item No.\" := 'TEST-ITEM';\n+ ItemLedgerEntry.\"Entry Type\" := ItemLedgerEntry.\"Entry Type\"::Purchase;\n+ ItemLedgerEntry.\"Subc. Prod. Order No.\" := 'PO-SUBC-001';\n+ ItemLedgerEntry.\"Subc. Prod. Order Line No.\" := 10000;\n+ ItemLedgerEntry.\"Subc. Purch. Order No.\" := 'PURCH-SUBC-001';\n+ ItemLedgerEntry.\"Subc. Purch. Order Line No.\" := 10000;\n+ ItemLedgerEntry.Insert();\n+\n+ // [WHEN] The Item Ledger Entries page is opened for that entry\n+ ItemLedgerEntries.OpenView();\n+ ItemLedgerEntries.GoToRecord(ItemLedgerEntry);\n+\n+ // [THEN] The Production Order action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Production Order\".Enabled(), ILEProdActionsNotEnabledErr);\n+ // [THEN] The Production Order Routing action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Production Order Routing\".Enabled(), ILEProdActionsNotEnabledErr);\n+ // [THEN] The Production Order Components action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Production Order Components\".Enabled(), ILEProdActionsNotEnabledErr);\n+ // [THEN] The Purchase Order action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Purchase Order\".Enabled(), ILEPurchActionsNotEnabledErr);\n+\n+ ItemLedgerEntries.Close();\n+\n+ // Cleanup\n+ ItemLedgerEntry.Delete();\n+ end;\n+\n+ local procedure GetNextItemLedgerEntryNo(): Integer\n+ var\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ begin\n+ if ItemLedgerEntry.FindLast() then\n+ exit(ItemLedgerEntry.\"Entry No.\" + 1);\n+ exit(1);\n+ end;\n+\n var\n Assert: Codeunit Assert;\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -602,4 +688,8 @@ codeunit 139990 \"Subc. Subcontracting UI Test\"\n SubcontractingActionsEnabledErr: Label 'Subcontractor Prices action should not be enabled for a non-subcontracting Work Center.';\n SubcontractingActionsNotVisibleErr: Label 'Subcontractor Prices action should be visible for a subcontracting Work Center.';\n SubcontractingActionsNotEnabledErr: Label 'Subcontractor Prices action should be enabled for a subcontracting Work Center.';\n+ ILEProdActionsEnabledErr: Label 'Production actions should not be enabled for a non-subcontracting Item Ledger Entry.';\n+ ILEProdActionsNotEnabledErr: Label 'Production actions should be enabled for a subcontracting Item Ledger Entry.';\n+ ILEPurchActionsEnabledErr: Label 'Purchase Order action should not be enabled for a non-subcontracting Item Ledger Entry.';\n+ ILEPurchActionsNotEnabledErr: Label 'Purchase Order action should be enabled for a subcontracting Item Ledger Entry.';\n }\n\\ No newline at end of file\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8612", "base_commit": "096b97ae84daae3c907fe58295a761b331801a42", "created_at": "2026-06-15T14:26:39Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex b6de5b5ea0..6a958ce4b4 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -39,7 +39,6 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n PurchOrderCreatedPluralTxt: Label '%1 purchase orders were created.\\\\Do you want to view them?', Comment = '%1 = number of purchase orders created';\n PurchOrderAlreadyCreatedQst: Label 'Purchase orders have already been created.\\\\Do you want to view them?';\n CreationOfSubcontractingOrderIsNotAllowedErr: Label 'You cannot create Subcontracting Order, because the Production Order %1 is not released.', Comment = '%1=Production Order No.';\n- NoProdOrderLineWithRemQtyErr: Label 'No Prod. Order Line with Remaining Quantity.';\n BlankLocationConfirmQst: Label 'One or more Prod. Order Components with Component Supply Method Transfer to Vendor have a blank Location Code. Without a Location Code, you will not be able to create a transfer order to send the components to the subcontractor.\\\\Do you want to create the Subcontracting Order anyway?';\n SameAsSubcLocConfirmQst: Label 'One or more Prod. Order Components with Component Supply Method Transfer to Vendor have Location Code %1, which is the same as the Subcontracting Location Code of vendor %2. A transfer order cannot be created from and to the same location.\\\\Do you want to create the Subcontracting Order anyway?', Comment = '%1=Component Location Code, %2=Vendor No.';\n NotEnoughSpaceErr: Label 'There is not enough space to insert the subcontracting info line.';\n@@ -61,7 +60,8 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n ManufacturingSetup.TestField(\"Subcontracting Template Name\");\n ManufacturingSetup.TestField(\"Subcontracting Batch Name\");\n \n- CheckProdOrderRtngLine(ProdOrderRoutingLine, ProdOrderLine);\n+ if not CheckProdOrderRtngLine(ProdOrderRoutingLine, ProdOrderLine) then\n+ exit(0);\n \n if not CheckProdOrderComponentLines(ProdOrderRoutingLine) then\n exit;\n@@ -259,7 +259,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n Clear(RoutingReferenceNo);\n end;\n \n- local procedure CheckProdOrderRtngLine(ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\")\n+ local procedure CheckProdOrderRtngLine(ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n var\n WorkCenter: Record \"Work Center\";\n begin\n@@ -273,12 +273,13 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n ProdOrderLine.SetRange(\"Routing Reference No.\", ProdOrderRoutingLine.\"Routing Reference No.\");\n ProdOrderLine.SetFilter(\"Remaining Quantity\", '<>%1', 0);\n if ProdOrderLine.IsEmpty() then\n- Error(NoProdOrderLineWithRemQtyErr);\n+ exit(false);\n \n WorkCenter.SetLoadFields(\"Gen. Prod. Posting Group\", \"Subcontractor No.\");\n WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\");\n WorkCenter.TestField(\"Subcontractor No.\");\n WorkCenter.TestField(\"Gen. Prod. Posting Group\");\n+ exit(true);\n end;\n \n internal procedure ShowExistingPurchaseOrdersForRoutingLines(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\")\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ShowExistingPurchOrdersAfterReceiptDoesNotError"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 950c628cf5..c2ad504090 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2774,6 +2774,50 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmYesShowSubcontractingPurchOrders,HandlePurchaseOrderPage,HandlePurchaseLinesPage')]\n+ procedure ShowExistingPurchOrdersAfterReceiptDoesNotError()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ begin\n+ // [SCENARIO 637777] Re-running Create Subcontracting Order after fully receiving the existing subcontracting purchase order should offer to view the existing order instead of raising \"No Prod. Order Line with Remaining Quantity.\"\n+\n+ // [GIVEN] Manufacturing setup with subcontracting work center, item with routing/BOM, released production order, and a created subcontracting purchase order\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", WorkCenter[2].\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+\n+ // [GIVEN] The existing subcontracting purchase order is fully received\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [WHEN] Create Subcontracting Order is invoked again from the same routing line\n+ PurchaseLinesPageOpened := false;\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] The existing purchase lines are shown and no raw remaining-quantity error is raised\n+ Assert.IsTrue(PurchaseLinesPageOpened, 'Purchase Lines list should open when the subcontracting purchase order already exists after full receipt.');\n+ end;\n+\n [Test]\n procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n var\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8600", "base_commit": "b6cf95ea86c0daf4ac6400435549bdd45a4de677", "created_at": "2026-06-12T15:07:44Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al\nindex 3d906b1720..bb2d4555e8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al\n@@ -25,6 +25,8 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n ExistingPurchLineErr: Label 'You cannot change this field because the component is already assigned to subcontracting purchase order %1.\\\\Updating the quantity is only allowed through the purchase order.', Comment = '%1=Document No';\n ExistingTransferLineQst: Label 'The component has already been assigned to the subcontracting transfer order %1.\\\\The quantity may only be updated via the purchase order and processing of the stock transfer.', Comment = '%1=Transfer Order No';\n ExistingTransferLineErr: Label 'You cannot open Tracking Specification because this component is already specified in Transfer Order %1.', Comment = '%1=Document No.';\n+ CannotModifyCompTransferExistsErr: Label 'You cannot change this component because transfer orders exist for the linked production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n+ CannotModifyCompStockAtSubcErr: Label 'You cannot change this component because there are remaining components or WIP items transferred to the subcontractor for production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n \n [EventSubscriber(ObjectType::Codeunit, Codeunit::\"Prod. Order Comp.-Reserve\", OnAfterInitFromProdOrderComp, '', false, false)]\n local procedure OnAfterInitFromProdOrderComp(ProdOrderComponent: Record \"Prod. Order Component\")\n@@ -92,6 +94,65 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n if Rec.IsTemporary then\n exit;\n CheckExistingSubcontractingTransferOrder(Rec, xRec, CurrFieldNo);\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Location Code\" <> xRec.\"Location Code\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Bin Code\", false, false)]\n+ local procedure OnBeforeValidateBinCode(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Bin Code\" <> xRec.\"Bin Code\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Item No.\", false, false)]\n+ local procedure OnBeforeValidateItemNo(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Item No.\" <> xRec.\"Item No.\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Variant Code\", false, false)]\n+ local procedure OnBeforeValidateVariantCode(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Variant Code\" <> xRec.\"Variant Code\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n end;\n \n [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Quantity per\", false, false)]\n@@ -106,6 +167,65 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n if Rec.IsTemporary then\n exit;\n CheckExistingDocumentsForSubcontracting(Rec, xRec, CurrFieldNo);\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Quantity per\" <> xRec.\"Quantity per\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Expected Quantity\", false, false)]\n+ local procedure OnBeforeValidateExpectedQuantity(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Expected Quantity\" <> xRec.\"Expected Quantity\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Component Supply Method\", false, false)]\n+ local procedure OnBeforeValidateComponentSupplyMethod(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Component Supply Method\" <> xRec.\"Component Supply Method\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeDeleteEvent, '', false, false)]\n+ local procedure OnBeforeDeleteProdOrderComponent(var Rec: Record \"Prod. Order Component\"; RunTrigger: Boolean)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+ if not RunTrigger then\n+ exit;\n+\n+ if Rec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(Rec);\n end;\n \n local procedure CheckExistingPostedSubcontractingTransferOrder(ProdOrderComponent: Record \"Prod. Order Component\"): Boolean\n@@ -364,4 +484,66 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n CheckExistingSubcontractingPurchaseOrder(ProdOrderComponent);\n end;\n end;\n+\n+ local procedure CheckUncompletedSubcontractingDocumentsExist(ProdOrderComponent: Record \"Prod. Order Component\")\n+ var\n+ ProdOrderLine: Record \"Prod. Order Line\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ begin\n+ ProdOrderLine.SetLoadFields(\"Routing Reference No.\", \"Routing No.\");\n+ if not ProdOrderLine.Get(ProdOrderComponent.Status, ProdOrderComponent.\"Prod. Order No.\", ProdOrderComponent.\"Prod. Order Line No.\") then\n+ exit;\n+\n+ PurchaseLine.SetCurrentKey(\"Document Type\", Type, \"Prod. Order No.\", \"Prod. Order Line No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProdOrderComponent.\"Prod. Order No.\");\n+ PurchaseLine.SetRange(\"Prod. Order Line No.\", ProdOrderComponent.\"Prod. Order Line No.\");\n+\n+ if ProdOrderComponent.\"Routing Link Code\" <> '' then begin\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n+ ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLine.\"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetRange(\"Routing Link Code\", ProdOrderComponent.\"Routing Link Code\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Operation No.\");\n+ if ProdOrderRoutingLine.FindFirst() then\n+ PurchaseLine.SetRange(\"Operation No.\", ProdOrderRoutingLine.\"Operation No.\");\n+ end;\n+\n+ if PurchaseLine.FindSet() then\n+ repeat\n+ if HasSubcTransferForPurchLine(PurchaseLine, ProdOrderComponent) then\n+ Error(CannotModifyCompTransferExistsErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+\n+ ProdOrderComponent.SetRange(\"Subc. Purchase Order Filter\", PurchaseLine.\"Document No.\");\n+ if HasStockAtSubcLocationForComponentForPurchLine(ProdOrderComponent) then\n+ Error(CannotModifyCompStockAtSubcErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+ until PurchaseLine.Next() = 0;\n+ end;\n+\n+ local procedure HasSubcTransferForPurchLine(PurchaseLine: Record \"Purchase Line\"; ProdOrderComponent: Record \"Prod. Order Component\"): Boolean\n+ var\n+ TransferLine: Record \"Transfer Line\";\n+ begin\n+ TransferLine.SetCurrentKey(\"Subc. Purch. Order No.\", \"Subc. Prod. Order No.\", \"Subc. Prod. Order Line No.\", \"Subc. Operation No.\");\n+ TransferLine.SetRange(\"Subc. Purch. Order No.\", PurchaseLine.\"Document No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Order No.\", ProdOrderComponent.\"Prod. Order No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Order Line No.\", ProdOrderComponent.\"Prod. Order Line No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Ord. Comp Line No.\", ProdOrderComponent.\"Line No.\");\n+ exit(not TransferLine.IsEmpty());\n+ end;\n+\n+ local procedure HasStockAtSubcLocationForComponentForPurchLine(ProdOrderComponent: Record \"Prod. Order Component\"): Boolean\n+ var\n+ SubcTransferManagement: Codeunit \"Subc. Transfer Management\";\n+ NetStockAtSubcLocation: Decimal;\n+ begin\n+ ProdOrderComponent.CalcFields(\"Subc. Qty. transf. to Subcontr\");\n+ if ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\" = 0 then\n+ exit(false);\n+\n+ NetStockAtSubcLocation := ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\";\n+ NetStockAtSubcLocation -= SubcTransferManagement.CalcConsumedQtyAtSubcLocation(ProdOrderComponent);\n+ exit(NetStockAtSubcLocation > 0);\n+ end;\n }\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al\nindex e7e85257d3..0c886fc5ec 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al\n@@ -1,22 +1,45 @@\n-// ------------------------------------------------------------------------------------------------\n+// ------------------------------------------------------------------------------------------------\n // Copyright (c) Microsoft Corporation. All rights reserved.\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting;\n \n+using Microsoft.Inventory.Transfer;\n using Microsoft.Manufacturing.Document;\n using Microsoft.Manufacturing.Routing;\n using Microsoft.Manufacturing.WorkCenter;\n+using Microsoft.Purchases.Document;\n \n codeunit 99001520 \"Subc. Prod. Order Rtng. Ext.\"\n {\n-#if not CLEAN29\n var\n+#if not CLEAN29\n #pragma warning disable AL0432\n SubcFeatureFlagHandler: Codeunit \"Subc. Feature Flag Handler\";\n #pragma warning restore AL0432\n+#endif\n+ CannotModifyRtngLineTransferExistsErr: Label 'You cannot change this routing line because transfer orders exist for the linked production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n+ CannotModifyRtngLineStockAtSubcErr: Label 'You cannot change this routing line because there are remaining components or WIP items transferred to the subcontractor for production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n \n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeDeleteEvent, '', false, false)]\n+ local procedure OnBeforeDeleteProdOrderRtngLine(var Rec: Record \"Prod. Order Routing Line\"; RunTrigger: Boolean)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n #endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if not RunTrigger then\n+ exit;\n+\n+ if Rec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(Rec);\n+ end;\n+\n [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnAfterDeleteEvent, '', false, false)]\n local procedure OnAfterDeleteProdOrderRtngLine(var Rec: Record \"Prod. Order Routing Line\"; RunTrigger: Boolean)\n begin\n@@ -49,10 +72,82 @@ codeunit 99001520 \"Subc. Prod. Order Rtng. Ext.\"\n if Rec.IsTemporary then\n exit;\n \n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"No.\" <> Rec.\"No.\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+\n if (xRec.\"No.\" <> Rec.\"No.\") and (Rec.\"Routing Link Code\" <> '') then\n SubcontractingManagement.UpdLinkedComponents(Rec, true);\n end;\n \n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Operation No.\", false, false)]\n+ local procedure OnBeforeValidateOperationNo(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"Operation No.\" <> Rec.\"Operation No.\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Routing Link Code\", false, false)]\n+ local procedure OnBeforeValidateRoutingLinkCode(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"Routing Link Code\" <> Rec.\"Routing Link Code\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Type\", false, false)]\n+ local procedure OnBeforeValidateType(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.Type <> Rec.Type) and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Transfer WIP Item\", false, false)]\n+ local procedure OnBeforeValidateTransferWIPItem(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"Transfer WIP Item\" <> Rec.\"Transfer WIP Item\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnAfterValidateEvent, \"Routing Link Code\", false, false)]\n local procedure OnAfterValidateRoutingLinkCode(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n begin\n@@ -150,4 +245,73 @@ codeunit 99001520 \"Subc. Prod. Order Rtng. Ext.\"\n SubcontractingManagement.DelLocationLinkedComponents(ProdOrderRoutingLine, false);\n end;\n end;\n-}\n\\ No newline at end of file\n+\n+ local procedure CheckSubcRtngLineDocumentsExist(ProdOrderRoutingLine: Record \"Prod. Order Routing Line\")\n+ var\n+ PurchaseLine: Record \"Purchase Line\";\n+ begin\n+ PurchaseLine.SetCurrentKey(\"Document Type\", Type, \"Prod. Order No.\", \"Prod. Order Line No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProdOrderRoutingLine.\"Prod. Order No.\");\n+ PurchaseLine.SetRange(\"Routing No.\", ProdOrderRoutingLine.\"Routing No.\");\n+ PurchaseLine.SetRange(\"Routing Reference No.\", ProdOrderRoutingLine.\"Routing Reference No.\");\n+ PurchaseLine.SetRange(\"Operation No.\", ProdOrderRoutingLine.\"Operation No.\");\n+ if PurchaseLine.FindSet() then\n+ repeat\n+ if HasSubcTransferForPurchLine(PurchaseLine) then\n+ Error(CannotModifyRtngLineTransferExistsErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+ if HasStockAtSubcLocation(PurchaseLine, ProdOrderRoutingLine) then\n+ Error(CannotModifyRtngLineStockAtSubcErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+ until PurchaseLine.Next() = 0;\n+ end;\n+\n+ local procedure HasSubcTransferForPurchLine(PurchaseLine: Record \"Purchase Line\"): Boolean\n+ var\n+ TransferLine: Record \"Transfer Line\";\n+ begin\n+ TransferLine.SetRange(\"Subc. Purch. Order No.\", PurchaseLine.\"Document No.\");\n+ TransferLine.SetRange(\"Subc. Purch. Order Line No.\", PurchaseLine.\"Line No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Order No.\", PurchaseLine.\"Prod. Order No.\");\n+ exit(not TransferLine.IsEmpty());\n+ end;\n+\n+ local procedure HasStockAtSubcLocation(PurchaseLine: Record \"Purchase Line\"; ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"): Boolean\n+ var\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ SubcWIPLedgerEntry: Record \"Subcontractor WIP Ledger Entry\";\n+ SubcTransferManagement: Codeunit \"Subc. Transfer Management\";\n+ NetStockAtSubcLocation: Decimal;\n+ begin\n+ ProdOrderComponent.SetCurrentKey(Status, \"Prod. Order No.\", \"Routing Link Code\");\n+ ProdOrderComponent.SetRange(Status, \"Production Order Status\"::Released);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", PurchaseLine.\"Prod. Order No.\");\n+ ProdOrderComponent.SetRange(\"Prod. Order Line No.\", PurchaseLine.\"Prod. Order Line No.\");\n+ ProdOrderComponent.SetRange(\"Component Supply Method\", ProdOrderComponent.\"Component Supply Method\"::\"Transfer to Vendor\");\n+ ProdOrderComponent.SetRange(\"Subc. Purchase Order Filter\", PurchaseLine.\"Document No.\");\n+ ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n+ ProdOrderComponent.SetAutoCalcFields(\"Subc. Qty. transf. to Subcontr\");\n+ if ProdOrderComponent.FindSet() then\n+ repeat\n+ if ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\" <> 0 then begin\n+ NetStockAtSubcLocation := ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\";\n+ NetStockAtSubcLocation -= SubcTransferManagement.CalcConsumedQtyAtSubcLocation(ProdOrderComponent);\n+ if NetStockAtSubcLocation > 0 then\n+ exit(true);\n+ end;\n+ until ProdOrderComponent.Next() = 0;\n+\n+ SubcWIPLedgerEntry.SetCurrentKey(\"Prod. Order No.\", \"Prod. Order Status\", \"Prod. Order Line No.\", \"Routing Reference No.\", \"Routing No.\", \"Operation No.\", \"Location Code\");\n+ SubcWIPLedgerEntry.SetRange(\"Prod. Order No.\", PurchaseLine.\"Prod. Order No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Prod. Order Status\", \"Production Order Status\"::Released);\n+ SubcWIPLedgerEntry.SetRange(\"Prod. Order Line No.\", PurchaseLine.\"Prod. Order Line No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Routing Reference No.\", ProdOrderRoutingLine.\"Routing Reference No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Routing No.\", ProdOrderRoutingLine.\"Routing No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Operation No.\", ProdOrderRoutingLine.\"Operation No.\");\n+ SubcWIPLedgerEntry.SetRange(\"In Transit\", false);\n+ SubcWIPLedgerEntry.CalcSums(\"Quantity (Base)\");\n+ if SubcWIPLedgerEntry.\"Quantity (Base)\" <> 0 then\n+ exit(true);\n+\n+ exit(false);\n+ end;\n+}\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al\nindex 40d3598456..41e67eba1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al\n@@ -104,6 +104,7 @@ codeunit 99001516 \"Subc. Req. Wksh. Make Ord.\"\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", RequisitionLine.\"Prod. Order Line No.\");\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n ProdOrderComponent.SetRange(\"Component Supply Method\", \"Component Supply Method\"::\"Vendor-Supplied\");\n+ ProdOrderComponent.SetLoadFields(\"Item No.\", \"Variant Code\", \"Remaining Quantity\");\n if ProdOrderComponent.FindSet() then\n repeat\n PurchaseLineComp.SetRange(\"Document Type\", PurchaseLine.\"Document Type\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al\nindex c84eace729..e90d3f7160 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al\n@@ -134,7 +134,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(Quantity) then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.Quantity = xRec.Quantity then\n@@ -160,7 +160,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"No.\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"No.\" = xRec.\"No.\" then\n@@ -186,7 +186,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Location Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Location Code\" = xRec.\"Location Code\" then\n@@ -212,7 +212,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Bin Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Bin Code\" = xRec.\"Bin Code\" then\n@@ -238,7 +238,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Variant Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Variant Code\" = xRec.\"Variant Code\" then\n@@ -264,7 +264,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Unit of Measure Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Unit of Measure Code\" = xRec.\"Unit of Measure Code\" then\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al\nindex 11e9867475..0918e43ef0 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al\n@@ -62,7 +62,7 @@ codeunit 99001544 \"Subc. Transfer Line Ext.\"\n if Rec.IsTemporary() then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Item No.\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Item No.\" = xRec.\"Item No.\" then\n@@ -85,7 +85,7 @@ codeunit 99001544 \"Subc. Transfer Line Ext.\"\n if Rec.IsTemporary() then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Variant Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Variant Code\" = xRec.\"Variant Code\" then\n@@ -108,7 +108,7 @@ codeunit 99001544 \"Subc. Transfer Line Ext.\"\n if Rec.IsTemporary() then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(Quantity) then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.Quantity = xRec.Quantity then\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al\nindex f6150f7b04..b6246cfb5d 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al\n@@ -389,6 +389,7 @@ codeunit 99001504 \"Subc. Transfer Management\"\n ProdOrderComponent.SetRange(\"Subc. Purchase Order Filter\", PurchaseLine.\"Document No.\");\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n ProdOrderComponent.SetRange(\"Component Supply Method\", ProdOrderComponent.\"Component Supply Method\"::\"Transfer to Vendor\");\n+ ProdOrderComponent.SetLoadFields(\"Subc. Qty. transf. to Subcontr\", \"Location Code\");\n ProdOrderComponent.SetAutoCalcFields(\"Subc. Qty. transf. to Subcontr\");\n if ProdOrderComponent.FindSet() then\n repeat\n@@ -407,7 +408,6 @@ codeunit 99001504 \"Subc. Transfer Management\"\n SubcWIPLedgerEntry.SetRange(\"Routing Reference No.\", PurchaseLine.\"Routing Reference No.\");\n SubcWIPLedgerEntry.SetRange(\"Routing No.\", PurchaseLine.\"Routing No.\");\n SubcWIPLedgerEntry.SetRange(\"Operation No.\", PurchaseLine.\"Operation No.\");\n-\n SubcWIPLedgerEntry.SetRange(\"In Transit\", false);\n SubcWIPLedgerEntry.CalcSums(\"Quantity (Base)\");\n if SubcWIPLedgerEntry.\"Quantity (Base)\" <> 0 then\n@@ -427,6 +427,7 @@ codeunit 99001504 \"Subc. Transfer Management\"\n ItemLedgerEntry.SetRange(\"Entry Type\", ItemLedgerEntry.\"Entry Type\"::Consumption);\n ItemLedgerEntry.SetRange(\"Prod. Order Comp. Line No.\", ProdOrderComponent.\"Line No.\");\n ItemLedgerEntry.SetRange(\"Location Code\", ProdOrderComponent.\"Location Code\");\n+ ItemLedgerEntry.SetLoadFields(Quantity);\n ItemLedgerEntry.CalcSums(Quantity);\n exit(-ItemLedgerEntry.Quantity);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139991, "functionName": ["CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithTransferToVendor", "CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithVendorSupplied"]}, {"codeunitID": 149915, "functionName": ["CannotModifyOrDeleteProdOrderComponentWhenTransferOrderExists"]}], "PASS_TO_PASS": [], "test_patch": "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\nindex f07c0afb34..0f6b7901b3 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcPurchSubcontTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcPurchSubcontTest.Codeunit.al\n@@ -510,6 +510,118 @@ codeunit 139991 \"Subc. Purch. Subcont. Test\"\n PostDirectTransferOrder(ReturnTransferHeader);\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoConfirmCreateProdOrderForSubcontractingProcess,HandleTransferOrder')]\n+ procedure CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithTransferToVendor()\n+ var\n+ Item: Record Item;\n+ HomeLocation: Record Location;\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderRtng: TestPage \"Prod. Order Routing\";\n+ begin\n+ // [SCENARIO] Modifying key fields or deleting a Prod. Order Routing Line must be blocked\n+ // when subcontracting transfer orders exist for Transfer to Vendor components.\n+ Initialize();\n+\n+ // [GIVEN] A subcontracting purchase order with a linked transfer order\n+ SetupSubContractingProdOrder(Item, HomeLocation, WorkCenter, MachineCenter, ProductionOrder, \"Component Supply Method\"::\"Transfer to Vendor\", LibraryRandom.RandIntInRange(1, 10));\n+ CreateSubcontractingPurchaseOrderForProdOrder(PurchaseHeader, PurchaseLine, Item, WorkCenter, ProductionOrder);\n+ CreateTransferOrderForPurchaseOrder(PurchaseHeader);\n+\n+ // [GIVEN] Find routing line for the subcontracting work center\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderRoutingLine.SetRange(\"Transfer WIP Item\", true);\n+#pragma warning restore AA0210\n+ ProdOrderRoutingLine.FindFirst();\n+\n+ // [THEN] Changing No. is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"No.\".SetValue(WorkCenter[1].\"No.\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Type is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.Type.SetValue(ProdOrderRoutingLine.Type::\"Machine Center\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Routing Link Code is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"Routing Link Code\".SetValue('');\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Deleting the routing line is blocked\n+ asserterror ProdOrderRoutingLine.Delete(true);\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('DoConfirmCreateProdOrderForSubcontractingProcess,HandleTransferOrder')]\n+ procedure CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithVendorSupplied()\n+ var\n+ Item: Record Item;\n+ HomeLocation: Record Location;\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderRtng: TestPage \"Prod. Order Routing\";\n+ begin\n+ // [SCENARIO] Modifying key fields or deleting a Prod. Order Routing Line must be blocked\n+ // when subcontracting transfer orders exist for Transfer to Vendor components.\n+ Initialize();\n+\n+ // [GIVEN] A subcontracting purchase order with a linked transfer order\n+ SetupSubContractingProdOrder(Item, HomeLocation, WorkCenter, MachineCenter, ProductionOrder, \"Component Supply Method\"::\"Vendor-Supplied\", LibraryRandom.RandIntInRange(1, 10));\n+ CreateSubcontractingPurchaseOrderForProdOrder(PurchaseHeader, PurchaseLine, Item, WorkCenter, ProductionOrder);\n+ CreateTransferOrderForPurchaseOrder(PurchaseHeader);\n+\n+ // [GIVEN] Find routing line for the subcontracting work center\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderRoutingLine.SetRange(\"Transfer WIP Item\", true);\n+#pragma warning restore AA0210\n+ ProdOrderRoutingLine.FindFirst();\n+\n+ // [THEN] Changing No. is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"No.\".SetValue(WorkCenter[1].\"No.\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Type is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.Type.SetValue(ProdOrderRoutingLine.Type::\"Machine Center\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Routing Link Code is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"Routing Link Code\".SetValue('');\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Deleting the routing line is blocked\n+ asserterror ProdOrderRoutingLine.Delete(true);\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ end;\n+\n [ModalPageHandler]\n procedure ItemTrackingLinesSimpleHandler(var ItemTrackingLines: TestPage \"Item Tracking Lines\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al\nindex ca4426c340..79a2777217 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al\n@@ -341,6 +341,58 @@ codeunit 149915 \"Subc. TransOrd. Reserv. Test\"\n Assert.AreEqual(30, TransferLine.\"Quantity (Base)\", 'Recreated transfer line must have the full component quantity');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting,HandleTransferOrder')]\n+ procedure CannotModifyOrDeleteProdOrderComponentWhenTransferOrderExists()\n+ var\n+ Item: Record Item;\n+ NewItem: Record Item;\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderCompPage: TestPage \"Prod. Order Components\";\n+ begin\n+ // [SCENARIO] Modifying key fields or deleting a Prod. Order Component with Component Supply Method = Transfer to Vendor\n+ // must be blocked when a subcontracting transfer order exists.\n+ Initialize();\n+\n+ // [GIVEN] A subcontracting transfer order linked to a production order with Transfer to Vendor components\n+ SetupTransferReservationScenario(Item, WorkCenter, MachineCenter, ProductionOrder, ProdOrderComponent, 10, 3, false);\n+ CreateSubcontractingPurchaseOrderAndReduceQuantity(Item, WorkCenter[2], ProductionOrder, PurchaseHeader, PurchaseLine, 0);\n+ CreateTransferOrder(PurchaseHeader);\n+\n+ // [GIVEN] Create another item to use for Item No. change\n+ LibraryInventory.CreateItem(NewItem);\n+\n+ // [THEN] Changing Item No. is blocked\n+ ProdOrderCompPage.OpenEdit();\n+ ProdOrderCompPage.GoToRecord(ProdOrderComponent);\n+ asserterror ProdOrderCompPage.\"Item No.\".SetValue(NewItem.\"No.\");\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ ProdOrderCompPage.Close();\n+\n+ // [THEN] Changing Quantity per is blocked\n+ ProdOrderCompPage.OpenEdit();\n+ ProdOrderCompPage.GoToRecord(ProdOrderComponent);\n+ asserterror ProdOrderCompPage.\"Quantity per\".SetValue(ProdOrderComponent.\"Quantity per\" + 1);\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ ProdOrderCompPage.Close();\n+\n+ // [THEN] Changing Component Supply Method is blocked\n+ ProdOrderCompPage.OpenEdit();\n+ ProdOrderCompPage.GoToRecord(ProdOrderComponent);\n+ asserterror ProdOrderCompPage.\"Component Supply Method\".SetValue(\"Component Supply Method\"::Empty);\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ ProdOrderCompPage.Close();\n+\n+ // [THEN] Deleting the component is blocked\n+ asserterror ProdOrderComponent.Delete(true);\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. TransOrd. Reserv. Test\");\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8386", "base_commit": "34cc7ccdc6ab40f6212196856671d9f4c531677b", "created_at": "2026-06-01T09:42:51Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Shopify\\App", "src\\Apps\\W1\\Shopify\\Test"], "patch": "diff --git a/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al b/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al\nindex b4508e5546..884b8bdd71 100644\n--- a/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al\n@@ -88,7 +88,8 @@ codeunit 30281 \"Shpfy Bulk UpdateProductPrice\" implements \"Shpfy IBulk Operation\n ShopifyVariant.Price := JVariant.GetDecimal('price');\n ShopifyVariant.\"Compare at Price\" := JVariant.GetDecimal('compareAtPrice');\n ShopifyVariant.\"Updated At\" := JVariant.GetDateTime('updatedAt');\n- ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n+ if JVariant.Contains('unitCost') then\n+ ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n ShopifyVariant.Modify();\n end;\n end;\ndiff --git a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\nindex cee48d5400..91bcde34a8 100644\n--- a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\n@@ -894,7 +894,8 @@ codeunit 30178 \"Shpfy Product Export\"\n ShopifyVariant.Price := JVariant.GetDecimal('price');\n ShopifyVariant.\"Compare at Price\" := JVariant.GetDecimal('compareAtPrice');\n ShopifyVariant.\"Updated At\" := JVariant.GetDateTime('updatedAt');\n- ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n+ if JVariant.Contains('unitCost') then\n+ ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n ShopifyVariant.Modify();\n end;\n exit;\n", "FAIL_TO_PASS": [{"codeunitID": 139633, "functionName": ["TestBulkOperationRevertFailedWithLegacyRequestDataMissingUnitCost"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al\nindex 86c7a952fd..6a6e049ec0 100644\n--- a/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al\n+++ b/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al\n@@ -314,6 +314,70 @@ codeunit 139633 \"Shpfy Bulk Operations Test\"\n ClearSetup();\n end;\n \n+ [Test]\n+ [HandlerFunctions('BulkOperationHttpHandler')]\n+ procedure TestBulkOperationRevertFailedWithLegacyRequestDataMissingUnitCost()\n+ var\n+ ShopifyVariant: Record \"Shpfy Variant\";\n+ BulkOperation: Record \"Shpfy Bulk Operation\";\n+ BulkOperationType: Enum \"Shpfy Bulk Operation Type\";\n+ ProductId: BigInteger;\n+ VariantId: BigInteger;\n+ VariantIds: List of [BigInteger];\n+ Index: Integer;\n+ begin\n+ // [SCENARIO] A bulk operation persisted before the unitCost key was added still\n+ // completes its revert without throwing, leaving Unit Cost untouched.\n+ // Regression for bug 637250.\n+\n+ // [GIVEN] A bulk operation whose request data was written by the pre-unitCost code\n+ // (i.e. the JSON objects only contain id/price/compareAtPrice/updatedAt) and four variants\n+ Initialize();\n+ for Index := 1 to 4 do begin\n+ ProductId := Any.IntegerInRange(100000, 555555);\n+ VariantId := Any.IntegerInRange(100000, 555555);\n+ VariantIds.Add(VariantId);\n+ ShopifyVariant.\"Product Id\" := ProductId;\n+ ShopifyVariant.Id := VariantId;\n+ ShopifyVariant.Price := 200;\n+ ShopifyVariant.\"Compare at Price\" := 250;\n+ ShopifyVariant.\"Unit Cost\" := 75;\n+ ShopifyVariant.Insert();\n+ end;\n+ BulkOperationUrl := 'https://storage.googleapis.com/shopify-bulk-result/' + Any.AlphabeticText(20);\n+ BulkOperation := CreateBulkOperation(BulkOperationId1, BulkOperationType::UpdateProductPrice, Shop.Code, BulkOperationUrl, GenerateLegacyRequestDataWithoutUnitCost(VariantIds, 100, 150));\n+\n+ // [WHEN] Bulk operation is completed\n+ BulkOperationIdCurrent := BulkOperationId1;\n+ VariantId1 := VariantIds.Get(1);\n+ VariantId2 := VariantIds.Get(4);\n+ BulkOperation.Status := BulkOperation.Status::Completed;\n+ BulkOperation.Modify(true);\n+\n+ // [THEN] The bulk operation is processed without throwing on the missing unitCost key,\n+ // failed variants have their Price/Compare at Price reverted, and Unit Cost is left\n+ // untouched on every variant (since the legacy blob doesn't know the pre-update value).\n+ BulkOperation.Get(BulkOperationId1, Shop.Code, BulkOperation.Type::mutation);\n+ LibraryAssert.IsTrue(BulkOperation.Processed, 'Bulk operation should be processed.');\n+ ShopifyVariant.Get(VariantIds.Get(1));\n+ LibraryAssert.AreEqual(200, ShopifyVariant.Price, 'Variant price should not be reverted.');\n+ LibraryAssert.AreEqual(250, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should not be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ShopifyVariant.Get(VariantIds.Get(2));\n+ LibraryAssert.AreEqual(100, ShopifyVariant.Price, 'Variant price should be reverted.');\n+ LibraryAssert.AreEqual(150, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ShopifyVariant.Get(VariantIds.Get(3));\n+ LibraryAssert.AreEqual(100, ShopifyVariant.Price, 'Variant price should be reverted.');\n+ LibraryAssert.AreEqual(150, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ShopifyVariant.Get(VariantIds.Get(4));\n+ LibraryAssert.AreEqual(200, ShopifyVariant.Price, 'Variant price should not be reverted.');\n+ LibraryAssert.AreEqual(250, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should not be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ClearSetup();\n+ end;\n+\n [Test]\n procedure TestBulkUpdateProductPriceClearsCompareAtPriceAsNull()\n var\n@@ -495,6 +559,26 @@ codeunit 139633 \"Shpfy Bulk Operations Test\"\n exit(RequestData);\n end;\n \n+ local procedure GenerateLegacyRequestDataWithoutUnitCost(VariantIds: List of [BigInteger]; Price: Decimal; CompareAtPrice: Decimal): JsonArray\n+ var\n+ RequestData: JsonArray;\n+ VariantId: BigInteger;\n+ Data: JsonObject;\n+ begin\n+ // Simulates the request-data layout written by the connector before the unitCost key\n+ // was added to the bulk-operation rollback bookkeeping. Used to test that the revert\n+ // tolerates legacy blobs persisted before the upgrade.\n+ foreach VariantId in VariantIds do begin\n+ Clear(Data);\n+ Data.Add('id', VariantId);\n+ Data.Add('price', Price);\n+ Data.Add('compareAtPrice', CompareAtPrice);\n+ Data.Add('updatedAt', '2025-02-25T13:40:15.6530000Z');\n+ RequestData.Add(Data);\n+ end;\n+ exit(RequestData);\n+ end;\n+\n local procedure EnqueueGraphQLResponsesForSendBulkMutation()\n begin\n GraphQLResponses.Enqueue('StagedUpload');\n"} diff --git a/dataset/problemstatement/microsoft__BCApps-8386/README.md b/dataset/problemstatement/microsoft__BCApps-8386/README.md new file mode 100644 index 000000000..189d4292a --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8386/README.md @@ -0,0 +1,39 @@ +# [Shopify] Tolerate legacy bulk-operation request data missing unitCost key + +## Summary +Bulk variant price updates persist a JSON `Request Data` blob on `Shpfy Bulk Operation` so the rollback path can restore the previous Price / Compare-at-Price / Updated At / Unit Cost values when Shopify's async callback reports failure. + +PR #6155 added a new `unitCost` key to that blob and a matching reader on the rollback path, but the reader uses `JsonObject.GetDecimal` which throws if the key is missing. Any bulk operation queued **before** the upgrade (no `unitCost` in the blob) and reverted **after** the upgrade crashes with: + +> There are no properties with the key 'unitCost' on the JSON object + +The same stale rows can keep retrying, so the error surfaces repeatedly even though the upgrade happened once. + +The Shopify API payload itself is unaffected — it still correctly sends `inventoryItem.cost`. The crash is purely on the BC-side rollback reader. + +## Changes + +**Production code** +- `ShpfyBulkUpdateProductPrice.RevertRequests` and `ShpfyProductExport.RevertVariantChanges`: guard the `unitCost` read with `JsonObject.Contains('unitCost')`. If absent (legacy blob), Unit Cost is left untouched, matching the pre-PR-#6155 behaviour. + +**Test code** +- `TestBulkOperationRevertFailedWithLegacyRequestDataMissingUnitCost`: new regression test that builds a request-data blob without the `unitCost` key (via a `GenerateLegacyRequestDataWithoutUnitCost` helper) and asserts that the rollback completes without throwing, reverts Price / Compare-at-Price correctly, and leaves Unit Cost untouched. + +## Why only `unitCost` is gated, not every field +The other keys (`id`, `price`, `compareAtPrice`, `updatedAt`) have been written by `ShpfyVariantAPI.UpdateProductPrice` since the connector was first migrated to BCApps — there is no version that ever persisted a `Request Data` blob without them. A missing `price`/`compareAtPrice`/`updatedAt`/`id` is therefore not a legitimate "legacy blob" scenario; it would be a real upstream bug (regressed writer, corrupted blob, forgotten `JRequest.Add`). `GetDecimal`'s throw is the correct behaviour there — surfacing the bug loudly is better than silently skipping a rollback (which would leave variants showing the wrong price in BC, or no-op the revert with zero diagnostic). + +`unitCost` is the one and only key that was added later, so it's the one key where a key-missing scenario has both a legitimate root cause (legacy persisted blob) and a safe fallback (leave the field untouched). + +## Customer mitigation (no patch required) +Customers hitting this on the current BC28 build can self-mitigate by opening the **Shopify Bulk Operations** page and running **Delete Entries Older Than 7 Days**. The deletion bypasses the rollback trigger, removing the stale pre-upgrade rows without re-throwing. Bulk operations queued after the upgrade are written in the new layout and are unaffected. + +## Scope +Main only — rare upgrade-window race condition with a self-service mitigation available. Not backported. + +#### Work Item(s) +Fixes [AB#637250](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/637250) + + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-8600/README.md b/dataset/problemstatement/microsoft__BCApps-8600/README.md new file mode 100644 index 000000000..adb7e440e --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8600/README.md @@ -0,0 +1,24 @@ +# [Subcontracting] Block changing Prod Order Routing and Components when Subcontracting Transfers exist + +## What & why + +Prevent unsafe changes when subcontracting transfers are in progress + +When a production order has active transfer orders sending components to a subcontractor, users could previously change or delete the related components and routing lines — potentially causing data mismatches between the transfer orders and the production order. + +This PR blocks modifications to key fields (item, quantity, supply method, location, etc.) on Prod. Order Components and Prod. Order Routing Lines when transfer orders or stock at the subcontractor location exist. + +## Linked work + +Fixes [AB#634269](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634269) + + + + + + + + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-8612/README.md b/dataset/problemstatement/microsoft__BCApps-8612/README.md new file mode 100644 index 000000000..20c211e75 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8612/README.md @@ -0,0 +1,54 @@ +# Bug 637777: Handle rerun after subcontracting receipt + +Treat routing lines with no remaining quantity as a no-op so rerunning Create Subcontracting Order after full receipt shows existing purchase lines instead of surfacing a raw error. + + + +## What & why + + + +## Linked work + + + +Fixes [AB#637777](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/637777) + +## How I validated this + +- [ ] I read the full diff and it contains only changes I intended. +- [ ] I built the affected app(s) locally with no new analyzer warnings. +- [ ] I ran the change in Business Central and confirmed it behaves as expected. +- [ ] I added or updated tests for the new behavior, or explained below why none are needed. + +**What I tested and the outcome** *(required — be specific: scenarios, commands, screenshots for UI changes)* + + + +## Risk & compatibility + + + +Fixes [AB#637777](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/637777) + + + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-8616/README.md b/dataset/problemstatement/microsoft__BCApps-8616/README.md new file mode 100644 index 000000000..38ad1e372 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8616/README.md @@ -0,0 +1,21 @@ +# Bug 638458: Disable subcontracting actions on Item Ledger Entries when not applicable + +## Summary +- **Bug:** Item Ledger Entries subcontracting actions (Production Order, Production Order Routing, Production Order Components, Subcontracting Purchase Order) are always enabled and silently do nothing when clicked on non-subcontracting entries. +- **Root cause:** The four actions in `SubcILEntries.PageExt.al` had no `Enabled` property, so they were always clickable regardless of whether the entry was subcontracting-related. +- **Fix:** Added inline `Enabled` expressions: + - `Enabled = Rec."Subc. Prod. Order No." <> ''` on Production Order, Production Order Routing, and Production Order Components actions + - `Enabled = Rec."Subc. Purch. Order No." <> ''` on Subcontracting Purchase Order action + +## Test +Added `ItemLedgerEntriesSubcActionsDisabledWhenNotSubcontracting` and `ItemLedgerEntriesSubcActionsEnabledWhenSubcontracting` in `SubcSubcontractingUITest` (codeunit 139990) — [SCENARIO 638458]. + +Fixes [AB#638458](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/638458) + +:robot: Generated with GitHub Copilot + + + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-8632/README.md b/dataset/problemstatement/microsoft__BCApps-8632/README.md new file mode 100644 index 000000000..d67cb6c3d --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8632/README.md @@ -0,0 +1,15 @@ +# [Subcontracting] Add action to view subcontracting transfer orders from production orders + +Fixes [AB#638532](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/638532) + + + + + + + + + + + + From 3a3fbbdabad8d8d21cf476334478f46beab7dc3c Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Tue, 23 Jun 2026 10:20:27 +0200 Subject: [PATCH 12/14] Recover collected dataset entries (BCApps-8313/8380/8423/8524/8555/8564) after failed week-26 autostash --- dataset/bcbench.jsonl | 6 ++++ .../microsoft__BCApps-8287/README.md | 14 ++++---- .../microsoft__BCApps-8313/README.md | 32 +++++++++++++++++++ .../microsoft__BCApps-8380/README.md | 16 ++++++++++ .../microsoft__BCApps-8423/README.md | 24 ++++++++++++++ .../microsoft__BCApps-8524/README.md | 21 ++++++++++++ .../microsoft__BCApps-8555/README.md | 16 ++++++++++ .../microsoft__BCApps-8564/README.md | 12 +++++++ 8 files changed, 134 insertions(+), 7 deletions(-) create mode 100644 dataset/problemstatement/microsoft__BCApps-8313/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8380/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8423/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8524/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8555/README.md create mode 100644 dataset/problemstatement/microsoft__BCApps-8564/README.md diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index c568b9299..092789262 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -103,3 +103,9 @@ {"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8293", "base_commit": "01e67dc5ff263b26101f7f2db6caa1b346f090a6", "created_at": "2026-05-25T21:31:15Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\nindex 8d5c75124c..056de67a1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcProdOFactboxMgmt.Codeunit.al\n@@ -15,12 +15,13 @@ using System.Reflection;\n codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n {\n /// \n- /// Opens the Released Production Order page for the production order linked to the given variant record.\n+ /// Opens the appropriate Production Order page (Released or Finished) for the production order linked to the given variant record.\n /// \n /// A record variant of a purchase or transfer document line.\n procedure ShowProductionOrder(RecRelatedVariant: Variant)\n var\n ProductionOrder: Record \"Production Order\";\n+ FinishedProductionOrder: Page \"Finished Production Order\";\n ReleasedProductionOrder: Page \"Released Production Order\";\n OperationNo: Code[10];\n ProdOrderNo: Code[20];\n@@ -29,11 +30,26 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n begin\n if not SetProdOrderInformationByVariant(RecRelatedVariant, ProdOrderNo, ProdOrderLineNo, RoutingNo, OperationNo) then\n exit;\n- ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ProductionOrder.SetFilter(Status, '>=%1', ProductionOrder.Status::Released);\n ProductionOrder.SetRange(\"No.\", ProdOrderNo);\n- ReleasedProductionOrder.SetTableView(ProductionOrder);\n- ReleasedProductionOrder.Editable := false;\n- ReleasedProductionOrder.Run();\n+ if not ProductionOrder.FindFirst() then\n+ exit;\n+ case ProductionOrder.Status of\n+ ProductionOrder.Status::Released:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Released);\n+ ReleasedProductionOrder.SetTableView(ProductionOrder);\n+ ReleasedProductionOrder.Editable := false;\n+ ReleasedProductionOrder.Run();\n+ end;\n+ ProductionOrder.Status::Finished:\n+ begin\n+ ProductionOrder.SetRange(Status, ProductionOrder.Status::Finished);\n+ FinishedProductionOrder.SetTableView(ProductionOrder);\n+ FinishedProductionOrder.Editable := false;\n+ FinishedProductionOrder.Run();\n+ end;\n+ end;\n end;\n \n /// \n@@ -77,9 +93,9 @@ codeunit 99001559 \"Subc. ProdO. Factbox Mgmt.\"\n exit(ProdOrderRoutingLine.Count());\n end;\n \n-local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n+ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])\n begin\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -130,7 +146,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n begin\n ProdOrderRoutingLine.SetLoadFields(\"Routing Link Code\");\n- ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetFilter(Status, '>=%1', ProdOrderRoutingLine.Status::Released);\n ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLineNo);\n ProdOrderRoutingLine.SetRange(\"Routing No.\", RoutingNo);\n@@ -138,7 +154,7 @@ local procedure SetFilterProductionOrderRouting(var ProdOrderRoutingLine: Record\n if ProdOrderRoutingLine.FindFirst() then\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n \n- ProdOrderComponent.SetRange(Status, ProdOrderComponent.Status::Released);\n+ ProdOrderComponent.SetFilter(Status, '>=%1', ProdOrderComponent.Status::Released);\n ProdOrderComponent.SetRange(\"Prod. Order No.\", ProdOrderNo);\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", ProdOrderLineNo);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ProdOFactboxMgmtShowsDataAfterProdOrderFinished"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 68c7fff2af..c6c56da2b8 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -1875,6 +1875,57 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n 'CalcNoOfProductionOrderComponents should return a positive count for an Item Ledger Entry from a subcontracting receipt.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmArchiveOrderHandler,HandlePurchaseOrderPage')]\n+ procedure ProdOFactboxMgmtShowsDataAfterProdOrderFinished()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ SubcWorkCenter: Record \"Work Center\";\n+ SubcProdOFactboxMgmt: Codeunit \"Subc. ProdO. Factbox Mgmt.\";\n+ begin\n+ // [SCENARIO 634953] Subcontracting factbox drilldowns should work after production order is finished.\n+ Initialize();\n+\n+ // [GIVEN] A released production order with a subcontracting routing operation and a subcontracting purchase order\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+\n+ CreateItemWithSingleSubcontractingOperation(Item, SubcWorkCenter);\n+ SubcontractingMgmtLibrary.UpdateVendorWithSubcontractingLocationCode(SubcWorkCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", SubcWorkCenter.\"No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", SubcWorkCenter.\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [GIVEN] The production order is changed to Finished status\n+ LibraryManufacturing.ChangeProdOrderStatus(ProductionOrder, \"Production Order Status\"::Finished, WorkDate(), true);\n+\n+ // Re-read purchase line (the order still exists because only receipt was posted)\n+ PurchaseLine.FindFirst();\n+\n+ // [WHEN] CalcNoOfProductionOrderRoutings / CalcNoOfProductionOrderComponents are called with the Purchase Line\n+ // [THEN] Both return a positive count even though the production order is now Finished\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderRoutings(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderRoutings should return a positive count after the production order is finished.');\n+ Assert.IsTrue(\n+ SubcProdOFactboxMgmt.CalcNoOfProductionOrderComponents(PurchaseLine) > 0,\n+ 'CalcNoOfProductionOrderComponents should return a positive count after the production order is finished.');\n+ end;\n+\n [Test]\n [HandlerFunctions('ConfirmHandler')]\n procedure RoutingFactboxMgmtFiltersPurchOrderQtyByRoutingReferenceNo()\n@@ -3430,6 +3481,7 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n \n SubSetupLibrary.InitSetupFields();\n LibraryERMCountryData.CreateVATData();\n+ LibraryERMCountryData.UpdateGeneralPostingSetup();\n SubSetupLibrary.InitialSetupForGenProdPostingGroup();\n \n IsInitialized := true;\n"} {"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8287", "base_commit": "ad39c988e2565d1ea1a8cb538a5b9a6ec4107eb4", "created_at": "2026-05-22T17:02:35Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\nindex b8a5c1d869..c1b2942c55 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Result/QltyResultEvaluation.Codeunit.al\n@@ -22,6 +22,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n IsDefaultTextTok: Label '<>''''', Locked = true;\n InvalidDataTypeErr: Label 'The value \"%1\" is not allowed for %2, it is not a %3.', Comment = '%1=the value, %2=field name,%3=field type.';\n NotInAllowableValuesErr: Label 'The value \"%1\" is not allowed for %2, it must be in the range of \"%3\".', Comment = '%1=the value, %2=field name,%3=field type.';\n+ InvalidAllowableValuesFormatErr: Label 'The allowable values \"%1\" are not a valid filter expression for %2 of type %3.', Comment = '%1=the allowable values, %2=field name, %3=field type.';\n \n trigger OnRun()\n var\n@@ -324,6 +325,110 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n ValidateAllowableValuesOnText(TestNameForError, QltyTest.\"Default Value\", QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\", TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// The test whose allowable values expression should be validated.\n+ internal procedure ValidateAllowableValuesFormat(var QltyTest: Record \"Qlty. Test\")\n+ var\n+ TestNameForError: Text;\n+ begin\n+ if QltyTest.Description <> '' then\n+ TestNameForError := QltyTest.Description\n+ else\n+ TestNameForError := QltyTest.Code;\n+\n+ ValidateAllowableValuesFormat(TestNameForError, QltyTest.\"Allowable Values\", QltyTest.\"Test Value Type\");\n+ end;\n+\n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the given test value type.\n+ /// \n+ /// Friendly identifier used in error messages.\n+ /// The allowable values filter expression to validate.\n+ /// The test value type that the filter expression must match.\n+ local procedure ValidateAllowableValuesFormat(NumberOrNameOfTestNameForError: Text; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\")\n+ var\n+ IsValid: Boolean;\n+ begin\n+ if AllowableValues = '' then\n+ exit;\n+\n+ if IsBlankOrEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ if IsAnythingExceptEmptyCondition(AllowableValues) then\n+ exit;\n+\n+ // Allowable values may contain inline expressions like [Field] that are resolved at evaluation time.\n+ // Defer validation until resolution.\n+ if AllowableValues.Contains('[') then\n+ exit;\n+\n+ IsValid := true;\n+ case QltyTestValueType of\n+ QltyTestValueType::\"Value Type Decimal\":\n+ IsValid := TryApplyDecimalFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Integer\":\n+ IsValid := TryApplyIntegerFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Boolean\":\n+ IsValid := TryApplyBooleanFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type Date\":\n+ IsValid := TryApplyDateFilter(AllowableValues);\n+ QltyTestValueType::\"Value Type DateTime\":\n+ IsValid := TryApplyDateTimeFilter(AllowableValues);\n+ end;\n+\n+ if not IsValid then\n+ Error(InvalidAllowableValuesFormatErr, AllowableValues, NumberOrNameOfTestNameForError, QltyTestValueType);\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDecimalFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionLine: Record \"Qlty. Inspection Line\" temporary;\n+ begin\n+ TempQltyInspectionLine.SetFilter(\"Derived Numeric Value\", FilterExpression);\n+ if TempQltyInspectionLine.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyIntegerFilter(FilterExpression: Text)\n+ var\n+ TempInteger: Record \"Integer\" temporary;\n+ begin\n+ TempInteger.SetFilter(Number, FilterExpression);\n+ if TempInteger.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyBooleanFilter(FilterExpression: Text)\n+ var\n+ QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n+ begin\n+ // Valid boolean allowable values are: Yes, No, True, False, 1, 0, On, Off (and variations)\n+ if not QltyBooleanParsing.CanTextBeInterpretedAsBooleanIsh(FilterExpression) then\n+ Error(InvalidAllowableValuesFormatErr, FilterExpression, '', 'Boolean');\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateFilter(FilterExpression: Text)\n+ var\n+ TempDateLookupBuffer: Record \"Date Lookup Buffer\" temporary;\n+ begin\n+ TempDateLookupBuffer.SetFilter(\"Period Start\", FilterExpression);\n+ if TempDateLookupBuffer.IsEmpty() then;\n+ end;\n+\n+ [TryFunction]\n+ local procedure TryApplyDateTimeFilter(FilterExpression: Text)\n+ var\n+ TempQltyInspectionHeader: Record \"Qlty. Inspection Header\" temporary;\n+ begin\n+ TempQltyInspectionHeader.SetFilter(\"Finished Date\", FilterExpression);\n+ if TempQltyInspectionHeader.IsEmpty() then;\n+ end;\n+\n local procedure ValidateAllowableValuesOnText(NumberOrNameOfTestNameForError: Text; var TextToValidate: Text[250]; AllowableValues: Text; QltyTestValueType: Enum \"Qlty. Test Value Type\"; var TempBufferQltyTestLookupValue: Record \"Qlty. Test Lookup Value\" temporary; QltyCaseSensitivity: Enum \"Qlty. Case Sensitivity\")\n var\n QltyBooleanParsing: Codeunit \"Qlty. Boolean Parsing\";\n@@ -393,9 +498,8 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n if not (IsBlankOrEmptyCondition(AllowableValues) and (TextToValidate = '')) then\n if not QltyResultEvaluation.CheckIfValueIsString(TextToValidate, ConvertStr(AllowableValues, ',', '|'), QltyCaseSensitivity) then\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n-\n QltyTestValueType::\"Value Type Option\",\n- QltyTestValueType::\"Value Type Table Lookup\":\n+ QltyTestValueType::\"Value Type Table Lookup\":\n begin\n TextToValidate := CopyStr(TextToValidate.Trim(), 1, MaxStrLen(TextToValidate));\n \n@@ -419,6 +523,7 @@ codeunit 20410 \"Qlty. Result Evaluation\"\n Error(NotInAllowableValuesErr, TextToValidate, NumberOrNameOfTestNameForError, AllowableValues);\n end;\n end;\n+\n OnAfterValidateAllowableValuesOnText(NumberOrNameOfTestNameForError, TextToValidate, AllowableValues, QltyTestValueType, TempBufferQltyTestLookupValue, QltyCaseSensitivity);\n end;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139963, "functionName": ["ValidateAllowableValuesFormat_Boolean_ValidFormats", "ValidateAllowableValuesFormat_NonValidatedTypes", "ValidateAllowableValuesFormat_Boolean_InvalidFormats", "ValidateAllowableValuesFormat_DateTime_InvalidFormats", "ValidateAllowableValuesFormat_Integer_ValidFormats", "ValidateAllowableValuesFormat_Integer_InvalidFormats", "ValidateAllowableValuesFormat_Date_InvalidFormats", "ValidateAllowableValuesFormat_Decimal_ValidFormats", "ValidateAllowableValuesFormat_Date_ValidFormats", "ValidateAllowableValuesFormat_DateTime_ValidFormats", "ValidateAllowableValuesFormat_Decimal_InvalidFormats"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\nindex 9f4cbf3006..66e4c203fc 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n@@ -54,8 +54,11 @@ table 20401 \"Qlty. Test\"\n {\n Caption = 'Allowable Values';\n ToolTip = 'Specifies an expression for the range of values you can enter or select for the Test. Depending on the Test Value Type, the expression format varies. For example if you want a measurement such as a percentage that collects between 0 and 100 you would enter 0..100. This is not the pass or acceptable condition, these are just the technically possible values that the inspector can enter. You would then enter a passing condition in your result conditions. If you had a result of Pass being 80 to 100, you would then configure 80..100 for that result.';\n+\n trigger OnValidate()\n begin\n+ Rec.ValidateAllowableValuesFormat();\n+\n if Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Option\", Rec.\"Test Value Type\"::\"Value Type Table Lookup\"] then\n Rec.\"Allowable Values\" := CopyStr(Rec.\"Allowable Values\".Replace(', ', ','), 1, MaxStrLen(Rec.\"Allowable Values\"));\n end;\n@@ -472,6 +475,16 @@ table 20401 \"Qlty. Test\"\n QltyResultEvaluation.ValidateAllowableValuesOnTest(Rec);\n end;\n \n+ /// \n+ /// Validates that the allowable values expression is a valid filter for the test value type.\n+ /// \n+ procedure ValidateAllowableValuesFormat()\n+ var\n+ QltyResultEvaluation: Codeunit \"Qlty. Result Evaluation\";\n+ begin\n+ QltyResultEvaluation.ValidateAllowableValuesFormat(Rec);\n+ end;\n+\n /// \n /// Code = the unique code\n /// Description = raw description.\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\nindex 91159fca6e..05f7d8a17a 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsResultEval.Codeunit.al\n@@ -2071,6 +2071,440 @@ codeunit 139963 \"Qlty. Tests - Result Eval.\"\n LibraryAssert.ExpectedError(StrSubstNo(Expected4Err, OptionListQltyInspectionLine.\"Test Code\"));\n end;\n \n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_ValidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC';\n+ DecimalQltyTest.Description := 'Test Decimal';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ DecimalQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ DecimalQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25.5\"\n+ DecimalQltyTest.\"Allowable Values\" := '25.5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"10|20|30\"\n+ DecimalQltyTest.\"Allowable Values\" := '10|20|30';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DecimalQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DecimalQltyTest.\"Allowable Values\" := '0..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to not empty condition \"<>''\"\n+ DecimalQltyTest.\"Allowable Values\" := '<>''''';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Decimal_InvalidFormats()\n+ var\n+ DecimalQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid decimal filter expressions\n+\n+ // [GIVEN] A quality test with decimal type is created\n+ DecimalQltyTest.Init();\n+ DecimalQltyTest.Code := 'TESTDEC2';\n+ DecimalQltyTest.Description := 'Test Decimal Invalid';\n+ DecimalQltyTest.\"Test Value Type\" := DecimalQltyTest.\"Test Value Type\"::\"Value Type Decimal\";\n+ DecimalQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a number\"\n+ DecimalQltyTest.\"Allowable Values\" := 'not a number';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid operator \"==5\"\n+ DecimalQltyTest.\"Allowable Values\" := '==5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DecimalQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_ValidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT';\n+ IntegerQltyTest.Description := 'Test Integer';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to range expression \"0..100\"\n+ IntegerQltyTest.\"Allowable Values\" := '0..100';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than expression \">0\"\n+ IntegerQltyTest.\"Allowable Values\" := '>0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to less than or equal expression \"<=50\"\n+ IntegerQltyTest.\"Allowable Values\" := '<=50';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to exact value \"25\"\n+ IntegerQltyTest.\"Allowable Values\" := '25';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to list of values \"1|2|3|4|5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1|2|3|4|5';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ IntegerQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ IntegerQltyTest.\"Allowable Values\" := '1..[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Integer_InvalidFormats()\n+ var\n+ IntegerQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid integer filter expressions\n+\n+ // [GIVEN] A quality test with integer type is created\n+ IntegerQltyTest.Init();\n+ IntegerQltyTest.Code := 'TESTINT2';\n+ IntegerQltyTest.Description := 'Test Integer Invalid';\n+ IntegerQltyTest.\"Test Value Type\" := IntegerQltyTest.\"Test Value Type\"::\"Value Type Integer\";\n+ IntegerQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to decimal value \"1.5\"\n+ IntegerQltyTest.\"Allowable Values\" := '1.5';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not an integer\"\n+ IntegerQltyTest.\"Allowable Values\" := 'not an integer';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror IntegerQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_ValidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE';\n+ DateQltyTest.Description := 'Test Date';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact date \"2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to date range \"2024-01-01..2024-12-31\"\n+ DateQltyTest.\"Allowable Values\" := '2024-01-01..2024-12-31';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than date \">2024-01-01\"\n+ DateQltyTest.\"Allowable Values\" := '>2024-01-01';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateQltyTest.\"Allowable Values\" := '>[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Date_InvalidFormats()\n+ var\n+ DateQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid date filter expressions\n+\n+ // [GIVEN] A quality test with date type is created\n+ DateQltyTest.Init();\n+ DateQltyTest.Code := 'TESTDATE2';\n+ DateQltyTest.Description := 'Test Date Invalid';\n+ DateQltyTest.\"Test Value Type\" := DateQltyTest.\"Test Value Type\"::\"Value Type Date\";\n+ DateQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid date \"99/99/9999\"\n+ DateQltyTest.\"Allowable Values\" := '99/99/9999';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a date\"\n+ DateQltyTest.\"Allowable Values\" := 'not a date';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_ValidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT';\n+ DateTimeQltyTest.Description := 'Test DateTime';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to exact datetime \"2024-01-01 10:30:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 10:30:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to datetime range \"2024-01-01 00:00:00..2024-12-31 23:59:59\"\n+ DateTimeQltyTest.\"Allowable Values\" := '2024-01-01 00:00:00..2024-12-31 23:59:59';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to greater than datetime \">2024-01-01 10:00:00\"\n+ DateTimeQltyTest.\"Allowable Values\" := '>2024-01-01 10:00:00';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ DateTimeQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ DateTimeQltyTest.\"Allowable Values\" := '<[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_DateTime_InvalidFormats()\n+ var\n+ DateTimeQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid datetime filter expressions\n+\n+ // [GIVEN] A quality test with datetime type is created\n+ DateTimeQltyTest.Init();\n+ DateTimeQltyTest.Code := 'TESTDT2';\n+ DateTimeQltyTest.Description := 'Test DateTime Invalid';\n+ DateTimeQltyTest.\"Test Value Type\" := DateTimeQltyTest.\"Test Value Type\"::\"Value Type DateTime\";\n+ DateTimeQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid datetime \"99/99/9999 99:99:99\"\n+ DateTimeQltyTest.\"Allowable Values\" := '99/99/9999 99:99:99';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a datetime\"\n+ DateTimeQltyTest.\"Allowable Values\" := 'not a datetime';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror DateTimeQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_ValidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat accepts valid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL';\n+ BooleanQltyTest.Description := 'Test Boolean';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to \"Yes\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Yes';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"No\"\n+ BooleanQltyTest.\"Allowable Values\" := 'No';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"True\"\n+ BooleanQltyTest.\"Allowable Values\" := 'True';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"False\"\n+ BooleanQltyTest.\"Allowable Values\" := 'False';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"1\"\n+ BooleanQltyTest.\"Allowable Values\" := '1';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"0\"\n+ BooleanQltyTest.\"Allowable Values\" := '0';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"On\"\n+ BooleanQltyTest.\"Allowable Values\" := 'On';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to \"Off\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Off';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"Y\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Y';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to single-letter \"N\"\n+ BooleanQltyTest.\"Allowable Values\" := 'N';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are blank\n+ BooleanQltyTest.\"Allowable Values\" := '';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values contain expression with brackets \"[Field]\"\n+ BooleanQltyTest.\"Allowable Values\" := '[Field]';\n+ // [THEN] ValidateAllowableValuesFormat is deferred and passes without error\n+ BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_Boolean_InvalidFormats()\n+ var\n+ BooleanQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat rejects invalid boolean values\n+\n+ // [GIVEN] A quality test with boolean type is created\n+ BooleanQltyTest.Init();\n+ BooleanQltyTest.Code := 'TESTBOOL2';\n+ BooleanQltyTest.Description := 'Test Boolean Invalid';\n+ BooleanQltyTest.\"Test Value Type\" := BooleanQltyTest.\"Test Value Type\"::\"Value Type Boolean\";\n+ BooleanQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to invalid text \"Maybe\"\n+ BooleanQltyTest.\"Allowable Values\" := 'Maybe';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid number \"2\"\n+ BooleanQltyTest.\"Allowable Values\" := '2';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"not a boolean\"\n+ BooleanQltyTest.\"Allowable Values\" := 'not a boolean';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to invalid text \"abc\"\n+ BooleanQltyTest.\"Allowable Values\" := 'abc';\n+ // [THEN] ValidateAllowableValuesFormat raises an error\n+ asserterror BooleanQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+ [Test]\n+ procedure ValidateAllowableValuesFormat_NonValidatedTypes()\n+ var\n+ TextQltyTest: Record \"Qlty. Test\";\n+ OptionQltyTest: Record \"Qlty. Test\";\n+ begin\n+ // [SCENARIO] Validate that ValidateAllowableValuesFormat does not validate non-numeric/non-date types\n+\n+ // [GIVEN] A quality test with text type is created\n+ TextQltyTest.Init();\n+ TextQltyTest.Code := 'TESTTEXT';\n+ TextQltyTest.Description := 'Test Text';\n+ TextQltyTest.\"Test Value Type\" := TextQltyTest.\"Test Value Type\"::\"Value Type Text\";\n+ TextQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to any text value \"A|B|C\"\n+ TextQltyTest.\"Allowable Values\" := 'A|B|C';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for text type)\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [WHEN] Allowable values are set to any arbitrary text\n+ TextQltyTest.\"Allowable Values\" := 'any text value';\n+ // [THEN] ValidateAllowableValuesFormat passes without error\n+ TextQltyTest.ValidateAllowableValuesFormat();\n+\n+ // [GIVEN] A quality test with option type is created\n+ OptionQltyTest.Init();\n+ OptionQltyTest.Code := 'TESTOPT';\n+ OptionQltyTest.Description := 'Test Option';\n+ OptionQltyTest.\"Test Value Type\" := OptionQltyTest.\"Test Value Type\"::\"Value Type Option\";\n+ OptionQltyTest.Insert();\n+\n+ // [WHEN] Allowable values are set to comma-separated options \"Option1,Option2,Option3\"\n+ OptionQltyTest.\"Allowable Values\" := 'Option1,Option2,Option3';\n+ // [THEN] ValidateAllowableValuesFormat passes without error (no validation for option type)\n+ OptionQltyTest.ValidateAllowableValuesFormat();\n+ end;\n+\n+\n local procedure GetTemplateLineConfigFilters(var QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\"; var OutTemplateLineQltyIResultConditConf: Record \"Qlty. I. Result Condit. Conf.\")\n begin\n OutTemplateLineQltyIResultConditConf.SetRange(\"Condition Type\", OutTemplateLineQltyIResultConditConf.\"Condition Type\"::Template);\n"} {"metadata": {"area": null, "image_count": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8286", "base_commit": "70fd0246a0a4dbc72cb183ca719106722c03be4d", "created_at": "2026-05-22T13:07:41Z", "environment_setup_version": "28.1", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\nindex dfb07f0502..a005fa7b7c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPriceManagement.Codeunit.al\n@@ -436,7 +436,7 @@ codeunit 99001508 \"Subc. Price Management\"\n \n GetPriceByUOM(SubcontractorPrice, PriceListQty, PriceListCost);\n if PriceListCost <> 0 then begin\n- ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityBase(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n+ ConvertPriceToUOM(RequisitionLine.\"Unit of Measure Code\", RequisitionLine.GetQuantityForUOM(), PriceListUOM, PriceListQtyPerUOM, PriceListCost, DirectCost);\n ConvertPriceToCurrency(RequisitionLine.\"Currency Code\", SubcontractorPrice.\"Currency Code\", PriceListCost, DirectCost);\n end;\n RequisitionLine.\"Direct Unit Cost\" := DirectCost;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 51ef985d36..73e138fe61 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -3401,6 +3401,77 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.AreEqual('', ToPurchaseHeader.\"Subc. Location Code\", 'Subc. Location Code should not be copied from archive by Copy Document');\n end;\n \n+ [Test]\n+ procedure WorksheetDirectUnitCostUsesQtyPerUoMNotBaseQtyForUoMConversion()\n+ var\n+ Item: Record Item;\n+ ItemUOM: Record \"Item Unit of Measure\";\n+ Vendor: Record Vendor;\n+ WorkCenter: Record \"Work Center\";\n+ SubcontractorPrice: Record \"Subcontractor Price\";\n+ RequisitionLine: Record \"Requisition Line\";\n+ SubcPriceManagement: Codeunit \"Subc. Price Management\";\n+ QtyPerSet: Integer;\n+ PriceListUnitCost: Decimal;\n+ begin\n+ // [SCENARIO 636078] Calculate Subcontracts must compute Direct Unit Cost on the Subcontracting\n+ // Worksheet using the per-UoM conversion factor (GetQuantityForUOM()), not the total base\n+ // quantity (GetQuantityBase()) of the order.\n+\n+ // [GIVEN] Item with PCS base UoM and a SET alternative UoM (10 PCS per SET).\n+ Initialize();\n+ LibraryInventory.CreateItem(Item);\n+ QtyPerSet := 10;\n+ LibraryInventory.CreateItemUnitOfMeasureCode(ItemUOM, Item.\"No.\", QtyPerSet);\n+\n+ // [GIVEN] Vendor and Work Center with the vendor as its subcontractor.\n+ LibraryPurchase.CreateVendor(Vendor);\n+ LibraryManufacturing.CreateWorkCenter(WorkCenter);\n+ WorkCenter.Validate(\"Subcontractor No.\", Vendor.\"No.\");\n+ WorkCenter.Modify(true);\n+\n+ // [GIVEN] A subcontractor price in PCS with Minimum Quantity 1 and Direct Unit Cost 1000.\n+ PriceListUnitCost := 1000;\n+ SubcontractingMgmtLibrary.CreateSubContractingPrice(\n+ SubcontractorPrice, WorkCenter.\"No.\", Vendor.\"No.\", Item.\"No.\", '', '', WorkDate(), Item.\"Base Unit of Measure\", 1, '');\n+ SubcontractorPrice.Validate(\"Direct Unit Cost\", PriceListUnitCost);\n+ SubcontractorPrice.Modify(true);\n+\n+ // [GIVEN] A staged Requisition Line for 3 SET (= 30 PCS in base UoM).\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := ItemUOM.Code;\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 3;\n+\n+ // [WHEN] The subcontractor price is applied to the requisition line.\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost = price-list cost * Qty-per-UoM (1000 * 10 = 10000),\n+ // not price-list cost * total base quantity (1000 * 30 = 30000 — the pre-fix behavior).\n+ Assert.AreEqual(\n+ PriceListUnitCost * QtyPerSet, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost on the Subcontracting Worksheet must be derived from Qty. per Unit of Measure, not from total base quantity.');\n+\n+ // [WHEN] The same price is applied to a Requisition Line using the base UoM (no conversion needed).\n+ Clear(RequisitionLine);\n+ RequisitionLine.Init();\n+ RequisitionLine.\"No.\" := Item.\"No.\";\n+ RequisitionLine.\"Unit of Measure Code\" := Item.\"Base Unit of Measure\";\n+ RequisitionLine.\"Vendor No.\" := Vendor.\"No.\";\n+ RequisitionLine.\"Work Center No.\" := WorkCenter.\"No.\";\n+ RequisitionLine.\"Order Date\" := WorkDate();\n+ RequisitionLine.Quantity := 30;\n+ SubcPriceManagement.GetSubcPriceForReqLine(RequisitionLine, '');\n+\n+ // [THEN] Direct Unit Cost equals the price-list cost (the same-UoM path is unchanged by the fix).\n+ Assert.AreEqual(\n+ PriceListUnitCost, RequisitionLine.\"Direct Unit Cost\",\n+ 'Direct Unit Cost must equal the price-list cost when the worksheet UoM matches the price-list UoM.');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. Subcontracting Test\");\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8313", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-05-26T11:20:20Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\EDocument\\App", "src\\Apps\\W1\\EDocument\\Test"], "patch": "diff --git a/src/Apps/W1/EDocument/App/src/Processing/EDocImport.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/EDocImport.Codeunit.al\nindex ffcc3aedf5..c2d3853933 100644\n--- a/src/Apps/W1/EDocument/App/src/Processing/EDocImport.Codeunit.al\n+++ b/src/Apps/W1/EDocument/App/src/Processing/EDocImport.Codeunit.al\n@@ -840,7 +840,7 @@ codeunit 6140 \"E-Doc. Import\"\n EDocumentPurchaseLine.Quantity := PurchaseLine.Quantity;\n EDocumentPurchaseLine.\"Unit Price\" := PurchaseLine.\"Direct Unit Cost\";\n EDocumentPurchaseLine.\"Unit of Measure\" := PurchaseLine.\"Unit of Measure Code\";\n- EDocumentPurchaseLine.\"Sub Total\" := PurchaseLine.\"Direct Unit Cost\" * PurchaseLine.Quantity;\n+ EDocumentPurchaseLine.\"Sub Total\" := PurchaseLine.Amount;\n EDocumentPurchaseLine.\"Total Discount\" := PurchaseLine.\"Line Discount Amount\";\n EDocumentPurchaseLine.\"VAT Rate\" := PurchaseLine.\"VAT %\";\n EDocumentPurchaseLine.\"Currency Code\" := PurchaseLine.\"Currency Code\";\n", "FAIL_TO_PASS": [{"codeunitID": 139628, "functionName": ["ReceivePeppolInvoice_LineSubTotalFromXml"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/EDocument/Test/.resources/peppol/PEPPOL_LineRounding.xml b/src/Apps/W1/EDocument/Test/.resources/peppol/PEPPOL_LineRounding.xml\nnew file mode 100644\nindex 0000000000..6857d05fdd\n--- /dev/null\n+++ b/src/Apps/W1/EDocument/Test/.resources/peppol/PEPPOL_LineRounding.xml\n@@ -0,0 +1,89 @@\n+\n+\n+ urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0\n+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0\n+ INV-ROUNDING-001\n+ 2026-01-22\n+ 2026-02-22\n+ 380\n+ GBP\n+ \n+ \n+ GB123456789\n+ \n+ Test Supplier\n+ \n+ \n+ 1 Test Street\n+ London\n+ England\n+ \n+ GB\n+ \n+ \n+ \n+ GB123456789\n+ \n+ VAT\n+ \n+ \n+ \n+ Test Supplier Ltd\n+ 12345678\n+ \n+ \n+ \n+ \n+ \n+ \n+ Test Customer\n+ \n+ \n+ \n+ \n+ 2.35\n+ \n+ 11.20\n+ 2.35\n+ \n+ S\n+ 21.00\n+ \n+ VAT\n+ \n+ \n+ \n+ \n+ \n+ 11.20\n+ 11.20\n+ 13.55\n+ 0.00\n+ 13.55\n+ \n+ \n+ 1\n+ 1.65000\n+ 11.20\n+ \n+ RECDN2550\n+ REMOVAL SERVICE\n+ \n+ RECDN2550\n+ \n+ \n+ S\n+ 21.00\n+ \n+ VAT\n+ \n+ \n+ \n+ \n+ 6.79000\n+ 1\n+ \n+ \n+\ndiff --git a/src/Apps/W1/EDocument/Test/src/Receive/EDocReceiveFiles.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Receive/EDocReceiveFiles.Codeunit.al\nindex ae2782ed87..a264f22f25 100644\n--- a/src/Apps/W1/EDocument/Test/src/Receive/EDocReceiveFiles.Codeunit.al\n+++ b/src/Apps/W1/EDocument/Test/src/Receive/EDocReceiveFiles.Codeunit.al\n@@ -11,4 +11,9 @@ codeunit 139635 \"E-Doc. Receive Files\"\n exit(NavApp.GetResourceAsText('peppol/PEPPOL1.xml'));\n end;\n \n+ procedure GetLineRoundingDocument(): Text\n+ begin\n+ exit(NavApp.GetResourceAsText('peppol/PEPPOL_LineRounding.xml'));\n+ end;\n+\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/EDocument/Test/src/Receive/EDocReceiveTest.Codeunit.al b/src/Apps/W1/EDocument/Test/src/Receive/EDocReceiveTest.Codeunit.al\nindex 0469586d2e..d7326c28d5 100644\n--- a/src/Apps/W1/EDocument/Test/src/Receive/EDocReceiveTest.Codeunit.al\n+++ b/src/Apps/W1/EDocument/Test/src/Receive/EDocReceiveTest.Codeunit.al\n@@ -7,6 +7,7 @@ namespace Microsoft.eServices.EDocument.Test;\n using Microsoft.eServices.EDocument;\n using Microsoft.eServices.EDocument.Integration;\n using Microsoft.eServices.EDocument.IO.Peppol;\n+using Microsoft.eServices.EDocument.Processing.Import.Purchase;\n using Microsoft.Finance.GeneralLedger.Journal;\n using Microsoft.Finance.VAT.Setup;\n using Microsoft.Foundation.Address;\n@@ -60,6 +61,7 @@ codeunit 139628 \"E-Doc. Receive Test\"\n VATRegistrationLbl: Label 'GB123456789';\n ImportDataExchDefLbl: Label 'EDOCPEPPOLINVIMP';\n EndpointPathLbl: label '/Invoice/cac:AccountingSupplierParty/cac:Party/cbc:EndpointID';\n+ SubTotalMismatchErr: Label 'Sub Total should be %1 from XML LineExtensionAmount, not %2 (Qty*Price)', Comment = '%1 = expected Sub Total, %2 = actual Qty*Price', Locked = true;\n \n [Test]\n procedure ReceiveSinglePurchaseInvoice()\n@@ -258,6 +260,64 @@ codeunit 139628 \"E-Doc. Receive Test\"\n Assert.RecordCount(DocumentAttachment, 2);\n end;\n \n+ [Test]\n+ procedure ReceivePeppolInvoice_LineSubTotalFromXml()\n+ var\n+ EDocService: Record \"E-Document Service\";\n+ EDocument: Record \"E-Document\";\n+ EDocumentPurchaseLine: Record \"E-Document Purchase Line\";\n+ VATPostingSetup: Record \"VAT Posting Setup\";\n+ EDocServicePage: TestPage \"E-Document Service\";\n+ ExpectedSubTotal: Decimal;\n+ begin\n+ // [SCENARIO] V1 PEPPOL import stores LineExtensionAmount as Sub Total, not recalculated Qty*Price\n+ // Regression for: Qty=1.65, Price=6.79, LineExtensionAmount=11.20 -> was stored as 1.65*6.79=11.2035\n+ Initialize();\n+ BindSubscription(EDocImplState);\n+\n+ // [GIVEN] E-Document service with PEPPOL BIS 3.0 format and V1 import, all item lookups disabled\n+ LibraryEDoc.CreateTestReceiveServiceForEDoc(EDocService, Enum::\"Service Integration\"::\"Mock\");\n+ EDocService.\"Document Format\" := \"E-Document Format\"::\"PEPPOL BIS 3.0\";\n+ EDocService.\"Lookup Account Mapping\" := false;\n+ EDocService.\"Lookup Item GTIN\" := false;\n+ EDocService.\"Lookup Item Reference\" := false;\n+ EDocService.\"Resolve Unit Of Measure\" := false;\n+ EDocService.\"Validate Line Discount\" := false;\n+ EDocService.\"Verify Totals\" := false;\n+ EDocService.\"Validate Receiving Company\" := false;\n+ EDocService.\"Use Batch Processing\" := false;\n+ EDocService.Modify();\n+\n+ // [GIVEN] Vendor matching the XML supplier VAT registration\n+ LibraryPurchase.CreateVendorWithVATRegNo(Vendor);\n+ LibraryERM.CreateVATPostingSetupWithAccounts(VATPostingSetup, Enum::\"Tax Calculation Type\"::\"Normal VAT\", 1);\n+ Vendor.\"VAT Bus. Posting Group\" := VATPostingSetup.\"VAT Bus. Posting Group\";\n+ Vendor.\"VAT Registration No.\" := VATRegistrationLbl;\n+ Vendor.\"Receive E-Document To\" := Vendor.\"Receive E-Document To\"::\"Purchase Invoice\";\n+ Vendor.\"Country/Region Code\" := CountryRegion.Code;\n+ Vendor.Modify();\n+\n+ // [GIVEN] PEPPOL XML: Qty=1.65, PriceAmount=6.79, LineExtensionAmount=11.20 (vendor-rounded value)\n+ LibraryVariableStorage.Clear();\n+ LibraryVariableStorage.Enqueue(EDocReceiveFiles.GetLineRoundingDocument());\n+ LibraryVariableStorage.Enqueue(1);\n+ EDocImplState.SetVariableStorage(LibraryVariableStorage);\n+\n+ // [WHEN] Receive is invoked\n+ EDocServicePage.OpenView();\n+ EDocServicePage.Filter.SetFilter(Code, EDocService.Code);\n+ EDocServicePage.Receive.Invoke();\n+\n+ // [THEN] EDocumentPurchaseLine.\"Sub Total\" = 11.20 (from XML LineExtensionAmount), not 11.2035 (Qty*Price)\n+ EDocument.FindLast();\n+ EDocumentPurchaseLine.SetRange(\"E-Document Entry No.\", EDocument.\"Entry No\");\n+ Assert.IsTrue(EDocumentPurchaseLine.FindFirst(), 'Expected at least one E-Document purchase line');\n+ ExpectedSubTotal := 11.20;\n+ Assert.AreEqual(ExpectedSubTotal, EDocumentPurchaseLine.\"Sub Total\",\n+ StrSubstNo(SubTotalMismatchErr,\n+ ExpectedSubTotal, EDocumentPurchaseLine.Quantity * EDocumentPurchaseLine.\"Unit Price\"));\n+ end;\n+\n [Test]\n procedure ReceiveSinglePurchaseInvoice_PEPPOLDataExch_WithAttachment()\n var\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8380", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-05-29T16:14:31Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Workflow/QltyWorkflowSetup.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Workflow/QltyWorkflowSetup.Codeunit.al\nindex 0c1462d3a5..537b996632 100644\n--- a/src/Apps/W1/Quality Management/app/src/Workflow/QltyWorkflowSetup.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Workflow/QltyWorkflowSetup.Codeunit.al\n@@ -319,8 +319,8 @@ codeunit 20423 \"Qlty. Workflow Setup\"\n WorkflowSetup: Codeunit \"Workflow Setup\";\n begin\n WorkflowSetup.InsertTableRelation(Database::\"User\", User.FieldNo(\"User Name\"), Database::\"Qlty. Inspection Header\", QltyInspectionHeader.FieldNo(\"Assigned User ID\"));\n- WorkflowSetup.InsertTableRelation(Database::\"Qlty. Inspection Header\", QltyInspectionHeader.FieldNo(\"No.\"), database::\"Approval Entry\", ApprovalEntry.FieldNo(\"Document No.\"));\n- WorkflowSetup.InsertTableRelation(Database::\"Qlty. Inspection Line\", QltyInspectionLine.FieldNo(\"Inspection No.\"), database::\"Approval Entry\", ApprovalEntry.FieldNo(\"Document No.\"));\n+ WorkflowSetup.InsertTableRelation(Database::\"Qlty. Inspection Header\", QltyInspectionHeader.FieldNo(\"No.\"), Database::\"Approval Entry\", ApprovalEntry.FieldNo(\"Document No.\"));\n+ WorkflowSetup.InsertTableRelation(Database::\"Qlty. Inspection Line\", QltyInspectionLine.FieldNo(\"Inspection No.\"), Database::\"Approval Entry\", ApprovalEntry.FieldNo(\"Document No.\"));\n end;\n \n [EventSubscriber(ObjectType::Codeunit, Codeunit::\"Workflow Event Handling\", 'OnAddWorkflowEventsToLibrary', '', true, true)]\n@@ -397,12 +397,8 @@ codeunit 20423 \"Qlty. Workflow Setup\"\n OptionalSuffix: Text;\n begin\n WorkflowResponse.SetFilter(\"Function Name\", QltyPrefixTok + '*');\n- if WorkflowResponse.FindSet() then\n- repeat\n- WorkflowResponse.MakeDependentOnAllEvents();\n- until WorkflowResponse.Next() = 0;\n-\n WorkflowResponse.DeleteAll(false);\n+\n WorkflowResponse.Reset();\n WorkflowResponse.SetRange(Description, QMWorkflowResponseDescriptionCreateAQltyInspectionLbl);\n if not WorkflowResponse.IsEmpty() then\n@@ -413,43 +409,109 @@ codeunit 20423 \"Qlty. Workflow Setup\"\n QualityEventIds.Add(GetInspectionHasChangedEvent());\n QualityEventIds.Add(GetInspectionReopenedEvent());\n \n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseCreateInspection(), 1, 128), 0, QMWorkflowResponseDescriptionCreateAQltyInspectionLbl + OptionalSuffix, CopyStr(GetWorkflowResponseCreateInspection(), 1, 20));\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseCreateInspection(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionCreateAQltyInspectionLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseCreateInspection(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseCreateInspection(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseFinishInspection(), 1, 128), 0, QMWorkflowResponseDescriptionFinishTheQltyInspectionLbl + OptionalSuffix, CopyStr(GetWorkflowResponseFinishInspection(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseFinishInspection(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionFinishTheQltyInspectionLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseFinishInspection(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseFinishInspection(), 1, 128));\n \n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseReopenInspection(), 1, 128), 0, QMWorkflowResponseDescriptionReopenTheQltyInspectionLbl + OptionalSuffix, CopyStr(GetWorkflowResponseReopenInspection(), 1, 20));\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseReopenInspection(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionReopenTheQltyInspectionLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseReopenInspection(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseReopenInspection(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseCreateReinspection(), 1, 128), 0, QMWorkflowResponseDescriptionCreateReinspectionLbl + OptionalSuffix, CopyStr(GetWorkflowResponseCreateReinspection(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseCreateReinspection(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionCreateReinspectionLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseCreateReinspection(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseCreateReinspection(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseBlockLot(), 1, 128), 0, QMWorkflowResponseDescriptionBlockLotLbl + OptionalSuffix, CopyStr(GetWorkflowResponseBlockLot(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseBlockLot(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionBlockLotLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseBlockLot(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseBlockLot(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseBlockSerial(), 1, 128), 0, QMWorkflowResponseDescriptionBlockSerialLbl + OptionalSuffix, CopyStr(GetWorkflowResponseBlockSerial(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseBlockSerial(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionBlockSerialLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseBlockSerial(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseBlockSerial(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseUnblockLot(), 1, 128), 0, QMWorkflowResponseDescriptionUnblockLotLbl + OptionalSuffix, CopyStr(GetWorkflowResponseUnblockLot(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseUnblockLot(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionUnblockLotLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseUnblockLot(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseUnblockLot(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseUnblockSerial(), 1, 128), 0, QMWorkflowResponseDescriptionUnblockSerialLbl + OptionalSuffix, CopyStr(GetWorkflowResponseUnblockSerial(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseUnblockSerial(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionUnblockSerialLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseUnblockSerial(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseUnblockSerial(), 1, 128));\n \n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseMoveInventory(), 1, 128), 0, QMWorkflowResponseDescriptionMoveInventoryLbl + OptionalSuffix, CopyStr(GetWorkflowResponseMoveInventory(), 1, 20));\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseMoveInventory(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionMoveInventoryLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseMoveInventory(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseMoveInventory(), 1, 128));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseUnQuarantineLicensePlate(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseInternalPutAway(), 1, 128), 0, QMWorkflowResponseDescriptionCreateInternalPutAwayLbl + OptionalSuffix, CopyStr(GetWorkflowResponseInternalPutAway(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseInternalPutAway(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionCreateInternalPutAwayLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseInternalPutAway(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseInternalPutAway(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseSetDatabaseValue(), 1, 128), 0, QMWorkflowResponseDescriptionSetDatabaseValueLbl + OptionalSuffix, CopyStr(GetWorkflowResponseSetDatabaseValue(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseSetDatabaseValue(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionSetDatabaseValueLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseSetDatabaseValue(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseSetDatabaseValue(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseInventoryAdjustment(), 1, 128), 0, QMWorkflowResponseDescriptionCreateNegativeAdjustmentLbl + OptionalSuffix, CopyStr(GetWorkflowResponseInventoryAdjustment(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseInventoryAdjustment(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionCreateNegativeAdjustmentLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseInventoryAdjustment(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseInventoryAdjustment(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseChangeItemTracking(), 1, 128), 0, QMWorkflowResponseDescriptionChangeItemTrackingInformationLbl + OptionalSuffix, CopyStr(GetWorkflowResponseChangeItemTracking(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseChangeItemTracking(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionChangeItemTrackingInformationLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseChangeItemTracking(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseChangeItemTracking(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseCreateTransfer(), 1, 128), 0, QMWorkflowResponseDescriptionCreateTransferOrderLbl + OptionalSuffix, CopyStr(GetWorkflowResponseCreateTransfer(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseCreateTransfer(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionCreateTransferOrderLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseCreateTransfer(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseCreateTransfer(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseCreatePurchaseReturn(), 1, 128), 0, QMWorkflowResponseDescriptionCreatePurchaseReturnOrderLbl + OptionalSuffix, CopyStr(GetWorkflowResponseCreatePurchaseReturn(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseCreatePurchaseReturn(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionCreatePurchaseReturnOrderLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseCreatePurchaseReturn(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseCreatePurchaseReturn(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseBlockPackage(), 1, 128), 0, QMWorkflowResponseDescriptionBlockPackageLbl + OptionalSuffix, CopyStr(GetWorkflowResponseBlockPackage(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseBlockPackage(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionBlockPackageLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseBlockPackage(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseBlockPackage(), 1, 128));\n- WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseUnblockPackage(), 1, 128), 0, QMWorkflowResponseDescriptionUnblockPackageLbl + OptionalSuffix, CopyStr(GetWorkflowResponseUnblockPackage(), 1, 20));\n+\n+ WorkflowResponseHandling.AddResponseToLibrary(CopyStr(GetWorkflowResponseUnblockPackage(), 1, 128),\n+ 0,\n+ CopyStr(QMWorkflowResponseDescriptionUnblockPackageLbl + OptionalSuffix, 1, 250),\n+ CopyStr(GetWorkflowResponseUnblockPackage(), 1, 20));\n QualityResponseIdsToAdd.Add(CopyStr(GetWorkflowResponseUnblockPackage(), 1, 128));\n+\n foreach QualityResponse in QualityResponseIdsToAdd do\n foreach QualityEvent in QualityEventIds do\n WorkflowResponseHandling.AddResponsePredecessor(CopyStr(QualityResponse, 1, 128), CopyStr(QualityEvent, 1, 128));\n", "FAIL_TO_PASS": [{"codeunitID": 139969, "functionName": ["QltyResponsesAreNotPredecessorsOfNonQltyEvents"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsWorkflows.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsWorkflows.Codeunit.al\nindex fcbdfbf3de..0d99bb2332 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsWorkflows.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsWorkflows.Codeunit.al\n@@ -53,8 +53,42 @@ codeunit 139969 \"Qlty. Tests - Workflows\"\n EventFilterTok: Label 'Where(\"Result Code\"=Filter(%1))', Comment = '%1=result code.';\n DefaultResult1FailCodeTok: Label 'FAIL', Locked = true;\n DefaultResult2PassCodeTok: Label 'PASS', Locked = true;\n+ QMResponseNotPredecessorOfNonQMEventErr: Label 'QM response %1 should not be a predecessor of non-QM event %2.', Comment = '%1=response function name, %2=predecessor function name.';\n IsInitialized: Boolean;\n \n+ [Test]\n+ procedure QltyResponsesAreNotPredecessorsOfNonQltyEvents()\n+ var\n+ WFEventResponseCombination: Record \"WF Event/Response Combination\";\n+ WorkflowEventHandling: Codeunit \"Workflow Event Handling\";\n+ WorkflowResponseHandling: Codeunit \"Workflow Response Handling\";\n+ QltyPrefix: Text;\n+ begin\n+ // [SCENARIO] QM workflow responses should only be predecessors of QM events, not of any unrelated event\n+ Initialize();\n+\n+ // [GIVEN] The workflow events and responses libraries are initialized\n+ WorkflowEventHandling.CreateEventsLibrary();\n+ WorkflowResponseHandling.CreateResponsesLibrary();\n+\n+ // [WHEN] We look at all event/response combinations where the response is a QM response\n+ QltyPrefix := 'QLTY-*';\n+ WFEventResponseCombination.SetFilter(\"Function Name\", QltyPrefix);\n+ WFEventResponseCombination.FindSet();\n+\n+ // [THEN] Every linked predecessor event must also be a QM event\n+ repeat\n+ LibraryAssert.IsTrue(\n+ WFEventResponseCombination.\"Predecessor Type\" = WFEventResponseCombination.\"Predecessor Type\"::\"Event\",\n+ 'Expected predecessor type to be Event.');\n+ LibraryAssert.IsTrue(\n+ CopyStr(WFEventResponseCombination.\"Predecessor Function Name\", 1, 5) = 'QLTY-',\n+ StrSubstNo(QMResponseNotPredecessorOfNonQMEventErr,\n+ WFEventResponseCombination.\"Function Name\",\n+ WFEventResponseCombination.\"Predecessor Function Name\"));\n+ until WFEventResponseCombination.Next() = 0;\n+ end;\n+\n [Test]\n procedure PurchaseReturnWorkflow_OnInspectionFinished()\n var\n@@ -1780,11 +1814,7 @@ codeunit 139969 \"Qlty. Tests - Workflows\"\n var\n Workflow: Record Workflow;\n begin\n- Workflow.FindSet();\n- repeat\n- Workflow.Enabled := false;\n- Workflow.Modify();\n- until Workflow.Next() = 0;\n+ Workflow.ModifyAll(Enabled, false);\n Workflow.DeleteAll();\n end;\n \n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8564", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-06-10T10:49:42Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchPostExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchPostExt.Codeunit.al\nindex 6af5392a0f..fbca120f85 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchPostExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchPostExt.Codeunit.al\n@@ -17,6 +17,22 @@ using Microsoft.Purchases.History;\n using Microsoft.Purchases.Posting;\n codeunit 99001535 \"Subc. Purch. Post Ext\"\n {\n+ var\n+ CancelNotSupportedErr: Label 'You cannot cancel or correct posted purchase invoice %1 because it contains item charges assigned to a subcontracting order receipt.\\Create a purchase credit memo manually and assign the item charge to the posted subcontracting receipt line.', Comment = '%1 = Posted Purchase Invoice No.';\n+\n+ [EventSubscriber(ObjectType::Codeunit, Codeunit::\"Correct Posted Purch. Invoice\", OnAfterTestCorrectInvoiceIsAllowed, '', false, false)]\n+ local procedure BlockCancelIfHasSubcontractingItemChargeValueEntry(var PurchInvHeader: Record \"Purch. Inv. Header\"; Cancelling: Boolean)\n+ var\n+ ValueEntry: Record \"Value Entry\";\n+ begin\n+ ValueEntry.SetRange(\"Document Type\", ValueEntry.\"Document Type\"::\"Purchase Invoice\");\n+ ValueEntry.SetRange(\"Document No.\", PurchInvHeader.\"No.\");\n+ ValueEntry.SetFilter(\"Item Charge No.\", '<>%1', '');\n+ ValueEntry.SetFilter(\"Capacity Ledger Entry No.\", '<>%1', 0);\n+ if not ValueEntry.IsEmpty() then\n+ Error(CancelNotSupportedErr, PurchInvHeader.\"No.\");\n+ end;\n+\n [EventSubscriber(ObjectType::Codeunit, Codeunit::\"Purch.-Post\", OnBeforeItemJnlPostLine, '', false, false)]\n local procedure \"Purch.-Post_OnBeforeItemJnlPostLine\"(var ItemJournalLine: Record \"Item Journal Line\"; TempItemChargeAssignmentPurch: Record \"Item Charge Assignment (Purch)\" temporary)\n begin\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/SubcItemJnlPostLineExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/SubcItemJnlPostLineExt.Codeunit.al\nindex ab66a998e9..1e4c5d17ba 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/SubcItemJnlPostLineExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/SubcItemJnlPostLineExt.Codeunit.al\n@@ -41,6 +41,7 @@ codeunit 99001515 \"Subc. ItemJnlPostLine Ext\"\n local procedure \"Item Jnl.-Post Line_OnBeforeInsertCapValueEntry\"(var ValueEntry: Record \"Value Entry\"; ItemJnlLine: Record \"Item Journal Line\")\n begin\n ClearInvoicedQuantityForItemChargeSubAssign(ValueEntry, ItemJnlLine);\n+ CopyItemChargeNoForItemChargeSubAssign(ValueEntry, ItemJnlLine);\n end;\n \n local procedure UpdateProdOrderRoutingLine(var ProdOrderLine: Record \"Prod. Order Line\"; var ItemJournalLine: Record \"Item Journal Line\")\n@@ -90,4 +91,10 @@ codeunit 99001515 \"Subc. ItemJnlPostLine Ext\"\n if ItemJournalLine.\"Subc. Item Charge Assign.\" and (ValueEntry.\"Entry Type\" = \"Cost Entry Type\"::\"Direct Cost\") then\n ValueEntry.\"Invoiced Quantity\" := 0;\n end;\n+\n+ local procedure CopyItemChargeNoForItemChargeSubAssign(var ValueEntry: Record \"Value Entry\"; ItemJournalLine: Record \"Item Journal Line\")\n+ begin\n+ if ItemJournalLine.\"Subc. Item Charge Assign.\" and (ItemJournalLine.\"Item Charge No.\" <> '') then\n+ ValueEntry.\"Item Charge No.\" := ItemJournalLine.\"Item Charge No.\";\n+ end;\n }\n\\ No newline at end of file\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["CancelInvoiceWithSubcontractingItemChargeIsBlocked"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 4a5ff0f97b..f6a4093535 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -28,6 +28,7 @@ using Microsoft.Manufacturing.WorkCenter;\n using Microsoft.Purchases.Archive;\n using Microsoft.Purchases.Comment;\n using Microsoft.Purchases.Document;\n+using Microsoft.Purchases.History;\n using Microsoft.Purchases.Vendor;\n using Microsoft.Sales.Customer;\n using Microsoft.Sales.Document;\n@@ -3548,6 +3549,99 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n exit(UnitOfMeasure.Code);\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmHandler')]\n+ procedure CancelInvoiceWithSubcontractingItemChargeIsBlocked()\n+ var\n+ Item: Record Item;\n+ RegularItem: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ SubcWorkCenter: Record \"Work Center\";\n+ SubcPurchaseHeader: Record \"Purchase Header\";\n+ SubcPurchaseLine: Record \"Purchase Line\";\n+ RegularPurchaseHeader: Record \"Purchase Header\";\n+ RegularPurchaseLine: Record \"Purchase Line\";\n+ SubcPurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ RegPurchRcptLine: Record \"Purch. Rcpt. Line\";\n+ ItemCharge: Record \"Item Charge\";\n+ ItemChargeInvHeader: Record \"Purchase Header\";\n+ ItemChargeInvLine: Record \"Purchase Line\";\n+ PurchInvHeader: Record \"Purch. Inv. Header\";\n+ CorrectPostedPurchInvoice: Codeunit \"Correct Posted Purch. Invoice\";\n+ PostedInvoiceNo: Code[20];\n+ SubcVendorNo: Code[20];\n+ begin\n+ // [SCENARIO 637502] Cancelling a Posted Purchase Invoice whose Item Charge is split between a regular item receipt\n+ // line and a subcontracting service receipt line must be blocked. Letting the cancel run today silently skips the\n+ // capacity portion (Value Entry has Item Ledger Entry No. = 0) and redistributes it to inventory, corrupting cost.\n+ // Until a proper reversal path exists, the Subcontracting App blocks the cancel with a clear error so the user\n+ // creates a corrective credit memo manually.\n+\n+ // [GIVEN] Subcontracting setup with a single-operation subcontracting routing on Item\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ CreateItemWithSingleSubcontractingOperation(Item, SubcWorkCenter);\n+ SubcontractingMgmtLibrary.UpdateVendorWithSubcontractingLocationCode(SubcWorkCenter);\n+\n+ // [GIVEN] Released production order and a subcontracting purchase order received in full\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandIntInRange(5, 10));\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", SubcWorkCenter.\"No.\");\n+\n+ SubcPurchaseLine.SetRange(\"Document Type\", SubcPurchaseLine.\"Document Type\"::Order);\n+ SubcPurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ SubcPurchaseLine.SetRange(\"Work Center No.\", SubcWorkCenter.\"No.\");\n+#pragma warning restore AA0210\n+ SubcPurchaseLine.FindFirst();\n+ SubcPurchaseHeader.Get(SubcPurchaseLine.\"Document Type\", SubcPurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(SubcPurchaseLine.\"Gen. Bus. Posting Group\", SubcPurchaseLine.\"Gen. Prod. Posting Group\");\n+ SubcVendorNo := SubcPurchaseHeader.\"Buy-from Vendor No.\";\n+\n+ LibraryPurchase.PostPurchaseDocument(SubcPurchaseHeader, true, false);\n+\n+ SubcPurchRcptLine.SetRange(\"Order No.\", SubcPurchaseHeader.\"No.\");\n+ SubcPurchRcptLine.SetRange(\"Order Line No.\", SubcPurchaseLine.\"Line No.\");\n+ SubcPurchRcptLine.FindFirst();\n+\n+ // [GIVEN] A separate regular purchase order for the same vendor that receives a normal inventory item\n+ LibraryInventory.CreateItem(RegularItem);\n+ LibraryPurchase.CreatePurchHeader(RegularPurchaseHeader, RegularPurchaseHeader.\"Document Type\"::Order, SubcVendorNo);\n+ LibraryPurchase.CreatePurchaseLineWithUnitCost(\n+ RegularPurchaseLine, RegularPurchaseHeader, RegularItem.\"No.\",\n+ LibraryRandom.RandDecInRange(50, 100, 2), LibraryRandom.RandIntInRange(2, 5));\n+ EnsureGeneralPostingSetupIsValid(RegularPurchaseLine.\"Gen. Bus. Posting Group\", RegularPurchaseLine.\"Gen. Prod. Posting Group\");\n+ LibraryPurchase.PostPurchaseDocument(RegularPurchaseHeader, true, false);\n+\n+ RegPurchRcptLine.SetRange(\"Order No.\", RegularPurchaseHeader.\"No.\");\n+ RegPurchRcptLine.SetRange(\"Order Line No.\", RegularPurchaseLine.\"Line No.\");\n+ RegPurchRcptLine.FindFirst();\n+\n+ // [GIVEN] A purchase invoice with a single Item Charge line of quantity 2 allocated 1:1 across both receipt lines\n+ LibraryInventory.CreateItemCharge(ItemCharge);\n+ LibraryPurchase.CreatePurchHeader(ItemChargeInvHeader, ItemChargeInvHeader.\"Document Type\"::Invoice, SubcVendorNo);\n+ LibraryPurchase.CreatePurchaseLine(ItemChargeInvLine, ItemChargeInvHeader, ItemChargeInvLine.Type::\"Charge (Item)\", ItemCharge.\"No.\", 2);\n+ ItemChargeInvLine.Validate(\"Direct Unit Cost\", LibraryRandom.RandDecInRange(100, 200, 2));\n+ ItemChargeInvLine.Modify(true);\n+ EnsureGeneralPostingSetupIsValid(ItemChargeInvLine.\"Gen. Bus. Posting Group\", ItemChargeInvLine.\"Gen. Prod. Posting Group\");\n+\n+ AssignItemChargeToReceiptLine(ItemChargeInvLine, RegPurchRcptLine, 1);\n+ AssignItemChargeToReceiptLine(ItemChargeInvLine, SubcPurchRcptLine, 1);\n+\n+ // [GIVEN] The invoice is posted\n+ PostedInvoiceNo := LibraryPurchase.PostPurchaseDocument(ItemChargeInvHeader, false, true);\n+ PurchInvHeader.Get(PostedInvoiceNo);\n+ Commit();\n+\n+ // [WHEN] The user tries to cancel the posted invoice\n+ asserterror CorrectPostedPurchInvoice.CancelPostedInvoice(PurchInvHeader);\n+\n+ // [THEN] The Subcontracting App blocks the cancel with the dedicated error\n+ Assert.ExpectedError('contains item charges assigned to a subcontracting order receipt');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. Subcontracting Test\");\n@@ -3640,6 +3734,18 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n exit(ReqWkshTemplate.Name);\n end;\n \n+ local procedure AssignItemChargeToReceiptLine(ItemChargeInvLine: Record \"Purchase Line\"; PurchRcptLine: Record \"Purch. Rcpt. Line\"; QtyToAssign: Decimal)\n+ var\n+ ItemChargeAssignmentPurch: Record \"Item Charge Assignment (Purch)\";\n+ begin\n+ LibraryInventory.CreateItemChargeAssignPurchase(\n+ ItemChargeAssignmentPurch, ItemChargeInvLine,\n+ ItemChargeAssignmentPurch.\"Applies-to Doc. Type\"::Receipt,\n+ PurchRcptLine.\"Document No.\", PurchRcptLine.\"Line No.\", PurchRcptLine.\"No.\");\n+ ItemChargeAssignmentPurch.Validate(\"Qty. to Assign\", QtyToAssign);\n+ ItemChargeAssignmentPurch.Modify(true);\n+ end;\n+\n procedure UpdateProdOrderComponentWithComponentSupplyMethod(ProductionOrder: Record \"Production Order\"; ComponentSupplyMethod: Enum \"Component Supply Method\")\n var\n ProdOrderComp: Record \"Prod. Order Component\";\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8555", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-06-09T19:29:14Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/API/QltyInspectionsAPI.Page.al b/src/Apps/W1/Quality Management/app/src/API/QltyInspectionsAPI.Page.al\nindex 40d41f573e..05fd363c58 100644\n--- a/src/Apps/W1/Quality Management/app/src/API/QltyInspectionsAPI.Page.al\n+++ b/src/Apps/W1/Quality Management/app/src/API/QltyInspectionsAPI.Page.al\n@@ -470,7 +470,7 @@ page 20414 \"Qlty. Inspections API\"\n /// When left blank this assumes the same location as the from location.\n /// The target bin to move to.\n /// Quantity to move, if updating a specific quantity\n- /// When set to TRUE this will post journals immediately or create the warehouse movement. Verify you have sufficient licensing to use this flag.\n+ /// When set to TRUE this will post journals immediately or create the warehouse movement. Verify you have sufficient licensing to use this flag.\n /// Optionally restrict the locations to move from. \n /// Optionally restrict the specific bins to move from.\n /// When set to TRUE, will use the Movement Worksheet instead of a reclassification journal.\ndiff --git a/src/Apps/W1/Quality Management/app/src/Configuration/GenerationRule/JobQueue/QltyScheduleInspection.Report.al b/src/Apps/W1/Quality Management/app/src/Configuration/GenerationRule/JobQueue/QltyScheduleInspection.Report.al\nindex 4d477e53c9..810d8e7390 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/GenerationRule/JobQueue/QltyScheduleInspection.Report.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/GenerationRule/JobQueue/QltyScheduleInspection.Report.al\n@@ -70,9 +70,11 @@ report 20412 \"Qlty. Schedule Inspection\"\n QltyManagementSetup: Record \"Qlty. Management Setup\";\n QltyInspectionCreate: Codeunit \"Qlty. Inspection - Create\";\n ShowWarningIfCreateInspection: Boolean;\n- CreatedQltyInspectionIds: List of [Code[20]];\n- ZeroInspectionsCreatedMsg: Label 'No inspections were created.';\n- SomeInspectionsWereCreatedQst: Label '%1 inspections were created. Do you want to see them?', Comment = '%1=the count of inspections that were created.';\n+ NewlyCreatedQltyInspectionIds, AllResolvedQltyInspectionIds : List of [Code[20]];\n+ ZeroInspectionsCreatedOrMatchedMsg: Label 'No inspections were created or existing inspections matched.';\n+ SomeInspectionsCreatedQst: Label '%1 inspections were created. Do you want to see them?', Comment = '%1=the count of inspections that were newly created.';\n+ SomeInspectionsMatchedQst: Label 'No new inspections were created, but %1 existing inspections matched. Do you want to see them?', Comment = '%1=the count of existing inspections that were matched (reused).';\n+ SomeInspectionsCreatedOrMatchedQst: Label '%1 inspections were created and %2 existing inspections matched. Do you want to see all of them?', Comment = '%1=the count of newly created inspections, %2=the count of existing inspections that were matched (reused).';\n NoSourceConfigForScheduleErr: Label 'Cannot schedule inspections because no enabled source configuration with a table filter exists for source table %1. Navigate to the Quality Inspection Source Configuration page and ensure at least one enabled configuration exists for this table with a From Table Filter defined.', Comment = '%1=the source table number';\n \n trigger OnInitReport()\n@@ -85,17 +87,39 @@ report 20412 \"Qlty. Schedule Inspection\"\n trigger OnPreReport()\n begin\n Clear(QltyInspectionCreate);\n- Clear(CreatedQltyInspectionIds);\n+ Clear(NewlyCreatedQltyInspectionIds);\n+ Clear(AllResolvedQltyInspectionIds);\n end;\n \n trigger OnPostReport()\n+ var\n+ NewlyCreatedCount, ExistingMatchedCount : Integer;\n+ ShouldDisplay: Boolean;\n begin\n- if GuiAllowed() then\n- if CreatedQltyInspectionIds.Count() = 0 then\n- Message(ZeroInspectionsCreatedMsg)\n+ if not GuiAllowed() then\n+ exit;\n+\n+ if AllResolvedQltyInspectionIds.Count() = 0 then begin\n+ Message(ZeroInspectionsCreatedOrMatchedMsg);\n+ exit;\n+ end;\n+\n+ NewlyCreatedCount := NewlyCreatedQltyInspectionIds.Count();\n+ ExistingMatchedCount := AllResolvedQltyInspectionIds.Count() - NewlyCreatedCount;\n+ if ExistingMatchedCount < 0 then\n+ ExistingMatchedCount := 0;\n+\n+ case true of\n+ (NewlyCreatedCount > 0) and (ExistingMatchedCount > 0):\n+ ShouldDisplay := Confirm(StrSubstNo(SomeInspectionsCreatedOrMatchedQst, NewlyCreatedCount, ExistingMatchedCount), true);\n+ NewlyCreatedCount > 0:\n+ ShouldDisplay := Confirm(StrSubstNo(SomeInspectionsCreatedQst, NewlyCreatedCount), true);\n else\n- if Confirm(StrSubstNo(SomeInspectionsWereCreatedQst, CreatedQltyInspectionIds.Count())) then\n- QltyInspectionCreate.DisplayInspectionsIfConfigured(true, CreatedQltyInspectionIds);\n+ ShouldDisplay := Confirm(StrSubstNo(SomeInspectionsMatchedQst, ExistingMatchedCount), true);\n+ end;\n+\n+ if ShouldDisplay then\n+ QltyInspectionCreate.DisplayInspectionsIfConfigured(true, AllResolvedQltyInspectionIds);\n end;\n \n /// \n@@ -140,7 +164,7 @@ report 20412 \"Qlty. Schedule Inspection\"\n SourceRecordRef.SetView(QltyInspectSourceConfig.\"From Table Filter\");\n SourceRecordRef.FilterGroup(0);\n if SourceRecordRef.FindSet() then\n- QltyInspectionCreate.CreateMultipleInspectionsWithoutDisplaying(SourceRecordRef, GuiAllowed(), QltyInspectionGenRule, CreatedQltyInspectionIds);\n+ QltyInspectionCreate.CreateMultipleInspectionsWithoutDisplaying(SourceRecordRef, GuiAllowed(), QltyInspectionGenRule, NewlyCreatedQltyInspectionIds, AllResolvedQltyInspectionIds);\n until QltyInspectSourceConfig.Next() = 0;\n end;\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Quality Management/app/src/Dispositions/Move/QltyDispMoveAutoChoose.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Dispositions/Move/QltyDispMoveAutoChoose.Codeunit.al\nindex ea364e569a..c887da3c28 100644\n--- a/src/Apps/W1/Quality Management/app/src/Dispositions/Move/QltyDispMoveAutoChoose.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Dispositions/Move/QltyDispMoveAutoChoose.Codeunit.al\n@@ -84,7 +84,7 @@ codeunit 20442 \"Qlty. Disp. Move Auto Choose\" implements \"Qlty. Disposition\"\n end;\n \n /// \n- /// Do not use directly for net new code. This method is an interim shim to help with obsoletions and refactoring for dispositions.\n+ /// Do not use directly for net new code. This method is an interim shim to help with obsoletions and refactoring for dispositions.\n /// Instead use the new dispositions directly.\n /// \n /// \ndiff --git a/src/Apps/W1/Quality Management/app/src/Dispositions/PutAway/QltyDispWarehousePutAway.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Dispositions/PutAway/QltyDispWarehousePutAway.Codeunit.al\nindex 531f392913..c5d721633f 100644\n--- a/src/Apps/W1/Quality Management/app/src/Dispositions/PutAway/QltyDispWarehousePutAway.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Dispositions/PutAway/QltyDispWarehousePutAway.Codeunit.al\n@@ -30,7 +30,7 @@ codeunit 20453 \"Qlty. Disp. Warehouse Put-away\" implements \"Qlty. Disposition\"\n /// You must be in a directed pick and put location, and you must be using lot warehouse tracking to use this feature.\n /// \n /// The inspection to create the internal put-away from\n- /// Optional quantity. Leave blank to use the entire lot or the quantity from the inspection.\n+ /// Optional quantity. Leave blank to use the entire lot or the quantity from the inspection.\n /// Optional limitations on the source location.\n /// Optional limitations on the source bin.\n /// The quantity behavior\ndiff --git a/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionCreate.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionCreate.Codeunit.al\nindex 17b0f93181..7361a83742 100644\n--- a/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionCreate.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionCreate.Codeunit.al\n@@ -36,6 +36,7 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n LastQltyInspectionCreateStatus: Enum \"Qlty. Inspection Create Status\";\n PreventShowingGeneratedInspectionEvenIfConfigured: Boolean;\n AvoidThrowingErrorWhenPossible: Boolean;\n+ LastInspectionIsNewlyCreated: Boolean;\n ProgrammerErrNotARecordRefErr: Label 'Cannot find inspections with %1. Please supply a \"Record\" or \"RecordRef\".', Comment = '%1=the variant being supplied that is not a RecordRef. Your system might have an extension or customization that needs to be re-configured.';\n CannotFindTemplateErr: Label 'Cannot find a Quality Inspection Template or Quality Inspection Generation Rule to match %1. Ensure there is a Quality Inspection Generation Rule that will match this record.', Comment = '%1=The record identifier';\n UnableToCreateInspectionForErr: Label 'Unable to create an inspection for the record [%1], please review the Quality Inspection Source Configuration and also the Quality Inspection Generation Rules, you likely need additional configuration to work with this record.', Comment = '%1=the record id of what is being attempted to have an inspection created for.';\n@@ -43,9 +44,10 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n MultiRecordInspectionSourceFieldErr: Label 'Inspection %1 has been created, however neither %2 nor %4 had applicable source fields to map to the inspection. Navigate to the Quality Source Configuration for table %3 and apply source field mapping.', Comment = '%1=the inspection, %2=target record, %3=the number to set configuration for,%4=triggering record';\n RegisteredLogEventIDTok: Label 'QMERR0001', Locked = true;\n DetailRecordTok: Label 'Target', Locked = true;\n- UnableToCreateInspectionForParentOrChildErr: Label 'Cannot find enough details to make an inspection for your record(s). Try making sure that there is a source configuration for your record, and then also make sure there is sufficient information in your inspection generation rules. Two tables involved are %1 and %2.', Comment = '%1=the parent table, %2=the child and original table.';\n- UnableToCreateInspectionForRecordErr: Label 'Cannot find enough details to make an inspection for your record(s). Try making sure that there is a source configuration for your record, and then also make sure there is sufficient information in your inspection generation rules. The table involved is %1.', Comment = '%1=the table involved.';\n+ UnableToCreateInspectionForParentOrChildErr: Label 'Cannot find enough details to make an inspection for your record(s). Try making sure that there is a source configuration for your record, and then also make sure there is sufficient information in your inspection generation rules. Two tables involved are %1 and %2.', Comment = '%1=the parent table, %2=the child and original table.';\n+ UnableToCreateInspectionForRecordErr: Label 'Cannot find enough details to make an inspection for your record(s). Try making sure that there is a source configuration for your record, and then also make sure there is sufficient information in your inspection generation rules. The table involved is %1.', Comment = '%1=the table involved.';\n RecordShouldBeTemporaryErr: Label 'This code is only intended to run in a temporary fashion. This error is likely occurring from an integration issue.';\n+ SomeInspectionsMatchedQst: Label 'No new inspections were created, but %1 existing inspections matched. Do you want to see them?', Comment = '%1=the count of existing inspections that were matched (reused).';\n UnknownRecordTok: Label 'Unknown record', Locked = true;\n \n /// \n@@ -280,6 +282,8 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n OriginalRecordTableNo: Integer;\n IsNewlyCreatedInspection: Boolean;\n begin\n+ LastInspectionIsNewlyCreated := false;\n+\n case true of\n TargetRecordRef.Number() = 0,\n not QltyManagementSetup.GetSetupRecord():\n@@ -354,17 +358,22 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n \n QltyInspectionHeader.SetIsCreating(false);\n LastCreatedQltyInspectionHeader := QltyInspectionHeader;\n+ LastInspectionIsNewlyCreated := IsNewlyCreatedInspection;\n \n if IsNewlyCreatedInspection then\n QltyStartWorkflow.StartWorkflowInspectionCreated(QltyInspectionHeader);\n \n- if GuiAllowed() and not PreventShowingGeneratedInspectionEvenIfConfigured\n- and (QltyInspectionHeader.\"No.\" <> '') then\n+ if GuiAllowed() and\n+ not PreventShowingGeneratedInspectionEvenIfConfigured and\n+ (QltyInspectionHeader.\"No.\" <> '')\n+ then\n if IsManualCreation then\n Page.Run(Page::\"Qlty. Inspection\", QltyInspectionHeader)\n else\n- QltyNotificationMgmt.NotifyInspectionCreated(QltyInspectionHeader);\n+ if IsNewlyCreatedInspection then\n+ QltyNotificationMgmt.NotifyInspectionCreated(QltyInspectionHeader);\n end else begin\n+ LastInspectionIsNewlyCreated := false;\n LogCreateInspectionProblem(TargetRecordRef, UnableToCreateInspectionForErr, Format(OriginalRecordId));\n if IsManualCreation and (not AvoidThrowingErrorWhenPossible) then\n Error(UnableToCreateInspectionForErr, Format(OriginalRecordId));\n@@ -775,6 +784,21 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n exit(LastQltyInspectionCreateStatus);\n end;\n \n+ /// \n+ /// Indicates whether the inspection returned by the last create call was newly inserted\n+ /// or whether an existing matching inspection was reused (e.g. when the Inspection Creation\n+ /// Option is configured to use an existing inspection if available).\n+ /// Only valid immediately after a successful CreateInspection* call on this instance.\n+ /// \n+ /// True when the last inspection was newly created; false when it was reused, no inspection was returned.\n+ internal procedure IsLastInspectionNewlyCreated(): Boolean\n+ begin\n+ if LastCreatedQltyInspectionHeader.\"No.\" = '' then\n+ exit(false);\n+\n+ exit(LastInspectionIsNewlyCreated);\n+ end;\n+\n /// \n /// Use this to log QMERR0001\n /// \n@@ -835,15 +859,25 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n \n internal procedure CreateMultipleInspectionsForMultipleRecords(var SetOfRecordsRecordRef: RecordRef; IsManualCreation: Boolean; var TempFiltersQltyInspectionGenRule: Record \"Qlty. Inspection Gen. Rule\" temporary)\n var\n- CreatedQltyInspectionIds: List of [Code[20]];\n+ NewlyCreatedQltyInspectionIds, AllResolvedQltyInspectionIds : List of [Code[20]];\n+ NewlyCreatedCount, ExistingMatchedCount : Integer;\n begin\n- CreateMultipleInspectionsWithoutDisplaying(SetOfRecordsRecordRef, IsManualCreation, TempFiltersQltyInspectionGenRule, CreatedQltyInspectionIds);\n-\n- if IsManualCreation and GuiAllowed() then\n- DisplayInspectionsIfConfigured(IsManualCreation, CreatedQltyInspectionIds);\n+ CreateMultipleInspectionsWithoutDisplaying(SetOfRecordsRecordRef, IsManualCreation, TempFiltersQltyInspectionGenRule, NewlyCreatedQltyInspectionIds, AllResolvedQltyInspectionIds);\n+\n+ if IsManualCreation and GuiAllowed() then begin\n+ NewlyCreatedCount := NewlyCreatedQltyInspectionIds.Count();\n+ if NewlyCreatedCount > 0 then\n+ DisplayInspectionsIfConfigured(IsManualCreation, NewlyCreatedQltyInspectionIds)\n+ else begin\n+ ExistingMatchedCount := AllResolvedQltyInspectionIds.Count();\n+ if ExistingMatchedCount > 0 then\n+ if Confirm(StrSubstNo(SomeInspectionsMatchedQst, ExistingMatchedCount), true) then\n+ DisplayInspectionsIfConfigured(IsManualCreation, AllResolvedQltyInspectionIds);\n+ end;\n+ end;\n end;\n \n- internal procedure DisplayInspectionsIfConfigured(IsManualCreation: Boolean; var CreatedQltyInspectionIds: List of [Code[20]])\n+ internal procedure DisplayInspectionsIfConfigured(IsManualCreation: Boolean; var ToDisplayQltyInspectionIds: List of [Code[20]])\n var\n CreatedQltyInspectionHeader: Record \"Qlty. Inspection Header\";\n QltyNotificationMgmt: Codeunit \"Qlty. Notification Mgmt.\";\n@@ -856,7 +890,7 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n MaxSafeFilterLength := 1024;\n \n if GuiAllowed() then begin\n- foreach InspectionNo in CreatedQltyInspectionIds do\n+ foreach InspectionNo in ToDisplayQltyInspectionIds do\n if InspectionNo <> '' then begin\n if StrLen(PipeSeparatedFilter) > 1 then\n PipeSeparatedFilter += '|';\n@@ -868,12 +902,12 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n end;\n \n if FilterExceedsMaxLength then begin\n- QltyNotificationMgmt.NotifyMultipleInspectionsCreatedByCount(CreatedQltyInspectionIds.Count());\n+ QltyNotificationMgmt.NotifyMultipleInspectionsCreatedByCount(ToDisplayQltyInspectionIds.Count());\n exit;\n end;\n \n CreatedQltyInspectionHeader.SetFilter(\"No.\", PipeSeparatedFilter);\n- if CreatedQltyInspectionIds.Count() = 1 then begin\n+ if ToDisplayQltyInspectionIds.Count() = 1 then begin\n CreatedQltyInspectionHeader.SetCurrentKey(\"No.\", \"Re-inspection No.\");\n CreatedQltyInspectionHeader.FindLast();\n if IsManualCreation then\n@@ -892,17 +926,18 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n \n /// \n /// Use this if you need to keep track of multiple inspections without displaying the results.\n+ /// Distinguishes inspections that were newly inserted from inspections that were reused\n+ /// (matched an existing open inspection).\n /// \n /// \n /// \n- /// \n- /// \n- internal procedure CreateMultipleInspectionsWithoutDisplaying(var SetOfRecordsRecordRef: RecordRef; IsManualCreation: Boolean; var TempFiltersQltyInspectionGenRule: Record \"Qlty. Inspection Gen. Rule\" temporary; var CreatedQltyInspectionIds: List of [Code[20]])\n+ /// \n+ /// Receives only inspections that were newly inserted by this call.\n+ /// Receives every inspection that was either newly inserted or reused (matched an existing open inspection).\n+ internal procedure CreateMultipleInspectionsWithoutDisplaying(var SetOfRecordsRecordRef: RecordRef; IsManualCreation: Boolean; var TempFiltersQltyInspectionGenRule: Record \"Qlty. Inspection Gen. Rule\" temporary; var NewlyCreatedQltyInspectionIds: List of [Code[20]]; var AllResolvedQltyInspectionIds: List of [Code[20]])\n var\n TempCopyOfSingleRecordRecordRef: RecordRef;\n ParentRecordRef: RecordRef;\n- FailedInspectionIds: List of [Text];\n- CountOfInspectionsCreatedForLine: Integer;\n begin\n QltyManagementSetup.Get();\n \n@@ -915,18 +950,18 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n \n TempCopyOfSingleRecordRecordRef.Copy(SetOfRecordsRecordRef, false);\n TempCopyOfSingleRecordRecordRef.Insert(false);\n- CountOfInspectionsCreatedForLine := CreateInspectionForSelfOrDirectParent(\n+ CreateInspectionForSelfOrDirectParent(\n TempCopyOfSingleRecordRecordRef,\n TempFiltersQltyInspectionGenRule,\n ParentRecordRef,\n- CreatedQltyInspectionIds,\n+ NewlyCreatedQltyInspectionIds,\n+ AllResolvedQltyInspectionIds,\n true,\n IsManualCreation);\n- if CountOfInspectionsCreatedForLine = 0 then\n- FailedInspectionIds.Add(Format(SetOfRecordsRecordRef.RecordId()));\n until SetOfRecordsRecordRef.Next() = 0;\n \n- if CreatedQltyInspectionIds.Count() = 0 then begin\n+ // Error only when no inspection was resolved at all (neither newly created nor matching ones reused).\n+ if AllResolvedQltyInspectionIds.Count() = 0 then begin\n if AvoidThrowingErrorWhenPossible then\n exit;\n \n@@ -937,9 +972,8 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n end;\n end;\n \n- local procedure CreateInspectionForSelfOrDirectParent(var TempSelfRecordRef: RecordRef; var TempFiltersQltyInspectionGenRule: Record \"Qlty. Inspection Gen. Rule\" temporary; var FoundParentRecordRef: RecordRef; var CreatedQltyInspectionIds: List of [Code[20]]; PreventInspectionFromDisplayingEvenIfConfigured: Boolean; IsManualCreation: Boolean) InspectionCreatedCount: Integer\n+ local procedure CreateInspectionForSelfOrDirectParent(var TempSelfRecordRef: RecordRef; var TempFiltersQltyInspectionGenRule: Record \"Qlty. Inspection Gen. Rule\" temporary; var FoundParentRecordRef: RecordRef; var NewlyCreatedQltyInspectionIds: List of [Code[20]]; var AllResolvedQltyInspectionIds: List of [Code[20]]; PreventInspectionFromDisplayingEvenIfConfigured: Boolean; IsManualCreation: Boolean)\n var\n- LastCreatedQltyInspectionHeader2: Record \"Qlty. Inspection Header\";\n Item: Record Item;\n TempTrackingSpecification: Record \"Tracking Specification\" temporary;\n LocalQltyInspectionCreate: Codeunit \"Qlty. Inspection - Create\";\n@@ -949,8 +983,6 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n VariantEmptyOrTrackingSpecification: Variant;\n Dummy4Variant: Variant;\n begin\n- InspectionCreatedCount := 0;\n-\n LocalQltyInspectionCreate.SetPreventDisplayingInspectionEvenIfConfigured(PreventInspectionFromDisplayingEvenIfConfigured);\n \n Clear(FoundParentRecordRef);\n@@ -1013,11 +1045,7 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n end;\n \n if LocalQltyInspectionCreate.CreateInspectionWithMultiVariants(ParentRecordRef, TempSelfRecordRef, VariantEmptyOrTrackingSpecification, Dummy4Variant, IsManualCreation, TempFiltersQltyInspectionGenRule) then\n- if LocalQltyInspectionCreate.GetCreatedInspection(LastCreatedQltyInspectionHeader2) then begin\n- InspectionCreatedCount += 1;\n- if not CreatedQltyInspectionIds.Contains(LastCreatedQltyInspectionHeader2.\"No.\") then\n- CreatedQltyInspectionIds.Add(LastCreatedQltyInspectionHeader2.\"No.\");\n- end;\n+ TrackResolvedInspection(LocalQltyInspectionCreate, NewlyCreatedQltyInspectionIds, AllResolvedQltyInspectionIds);\n until RelatedReservFilterReservationEntry.Next() = 0;\n end else begin\n if TempFiltersQltyInspectionGenRule.\"Item Filter\" <> '' then begin\n@@ -1027,21 +1055,38 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n end;\n \n if LocalQltyInspectionCreate.CreateInspectionWithMultiVariants(TempSelfRecordRef, ParentRecordRef, Dummy4Variant, Dummy4Variant, IsManualCreation, TempFiltersQltyInspectionGenRule) then\n- if LocalQltyInspectionCreate.GetCreatedInspection(LastCreatedQltyInspectionHeader2) then begin\n- InspectionCreatedCount += 1;\n- if not CreatedQltyInspectionIds.Contains(LastCreatedQltyInspectionHeader2.\"No.\") then\n- CreatedQltyInspectionIds.Add(LastCreatedQltyInspectionHeader2.\"No.\");\n- end;\n+ TrackResolvedInspection(LocalQltyInspectionCreate, NewlyCreatedQltyInspectionIds, AllResolvedQltyInspectionIds);\n end;\n end;\n \n+ /// \n+ /// Records the inspection returned by the last create call on in the\n+ /// supplied tracking lists, deduplicating by inspection \"No.\". The all-resolved list captures both newly created\n+ /// and reused matching inspections so callers can detect reuse; the newly-created list only captures inspections that were\n+ /// actually inserted and is used to drive \"created inspections\" notifications and display.\n+ /// \n+ local procedure TrackResolvedInspection(var LocalQltyInspectionCreate: Codeunit \"Qlty. Inspection - Create\"; var NewlyCreatedQltyInspectionIds: List of [Code[20]]; var AllResolvedQltyInspectionIds: List of [Code[20]])\n+ var\n+ LastResolvedQltyInspectionHeader: Record \"Qlty. Inspection Header\";\n+ begin\n+ if not LocalQltyInspectionCreate.GetCreatedInspection(LastResolvedQltyInspectionHeader) then\n+ exit;\n+\n+ if not AllResolvedQltyInspectionIds.Contains(LastResolvedQltyInspectionHeader.\"No.\") then\n+ AllResolvedQltyInspectionIds.Add(LastResolvedQltyInspectionHeader.\"No.\");\n+\n+ if LocalQltyInspectionCreate.IsLastInspectionNewlyCreated() then\n+ if not NewlyCreatedQltyInspectionIds.Contains(LastResolvedQltyInspectionHeader.\"No.\") then\n+ NewlyCreatedQltyInspectionIds.Add(LastResolvedQltyInspectionHeader.\"No.\");\n+ end;\n+\n internal procedure SetPreventDisplayingInspectionEvenIfConfigured(PreventDisplayingInspectionEvenIfConfigured: Boolean)\n begin\n PreventShowingGeneratedInspectionEvenIfConfigured := PreventDisplayingInspectionEvenIfConfigured;\n end;\n \n /// \n- /// Stubs in and filles the source config fields.\n+ /// Stubs in and fills the source config fields.\n /// \n /// \n /// \n@@ -1189,9 +1234,9 @@ codeunit 20404 \"Qlty. Inspection - Create\"\n /// OnBeforeFindExistingInspection provides an opportunity to override how an existing inspection is found.\n /// \n /// The main target record that the inspection will be created against\n- /// Optional. Some events, typically automatic events, will have multiple records to assist with setting source details.\n- /// Optional. Some events, typically automatic events, will have multiple records to assist with setting source details.\n- /// Optional. Some events, typically automatic events, will have multiple records to assist with setting source details.\n+ /// Optional. Some events, typically automatic events, will have multiple records to assist with setting source details.\n+ /// Optional. Some events, typically automatic events, will have multiple records to assist with setting source details.\n+ /// Optional. Some events, typically automatic events, will have multiple records to assist with setting source details.\n /// The found inspection\n /// Set to true if you found the record. If you set to true you must also supply QltyInspectionHeader\n /// Set to true to replace the default behavior\ndiff --git a/src/Apps/W1/Quality Management/app/src/Integration/Assembly/QltyAssemblyIntegration.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Integration/Assembly/QltyAssemblyIntegration.Codeunit.al\nindex d0e09fcd50..f1a04da682 100644\n--- a/src/Apps/W1/Quality Management/app/src/Integration/Assembly/QltyAssemblyIntegration.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Integration/Assembly/QltyAssemblyIntegration.Codeunit.al\n@@ -56,7 +56,7 @@ codeunit 20412 \"Qlty. Assembly Integration\"\n if QltyInspectionHeader.\"No.\" <> '' then begin\n QltyInspectionHeader.\"Source Quantity (Base)\" := TempSpecTrackingSpecification.\"Quantity (Base)\";\n QltyInspectionHeader.Modify(false);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n end;\n OnAfterAttemptCreateInspectionFromPostedAssembly(AssemblyHeader, PostedAssemblyHeader, TempSpecTrackingSpecification, QltyInspectionHeader);\n@@ -69,7 +69,7 @@ codeunit 20412 \"Qlty. Assembly Integration\"\n HasInspection := QltyInspectionCreate.CreateInspectionWithMultiVariants(PostedAssemblyHeader, AssemblyHeader, UnusedVariant1, UnusedVariant2, false, TempQltyInspectionGenRule);\n if HasInspection then begin\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n OnAfterAttemptCreateInspectionFromPostedAssembly(AssemblyHeader, PostedAssemblyHeader, TempSpecTrackingSpecification, QltyInspectionHeader);\n end;\ndiff --git a/src/Apps/W1/Quality Management/app/src/Integration/Inventory/QltyInventoryAvailability.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Integration/Inventory/QltyInventoryAvailability.Codeunit.al\nindex e3f2663337..ee7b0421c7 100644\n--- a/src/Apps/W1/Quality Management/app/src/Integration/Inventory/QltyInventoryAvailability.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Integration/Inventory/QltyInventoryAvailability.Codeunit.al\n@@ -43,7 +43,7 @@ codeunit 20445 \"Qlty. Inventory Availability\"\n /// If multiple locations/bins are determined then those multiple locations/bins are supplied in TempBinContent\n /// \n /// Record \"Qlty. Inspection Header\".\n- /// Temporary var Record \"Bin Content\". Multiple bin locations could be available.\n+ /// Temporary var Record \"Bin Content\". Multiple bin locations could be available.\n /// Return variable of type Boolean.\n internal procedure GetCurrentLocationOfTrackedInventory(QltyInspectionHeader: Record \"Qlty. Inspection Header\"; var TempBinContent: Record \"Bin Content\" temporary): Boolean\n begin\ndiff --git a/src/Apps/W1/Quality Management/app/src/Integration/Inventory/QltyItemTrackingMgmt.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Integration/Inventory/QltyItemTrackingMgmt.Codeunit.al\nindex 2ba99aee7c..7a55bd4499 100644\n--- a/src/Apps/W1/Quality Management/app/src/Integration/Inventory/QltyItemTrackingMgmt.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Integration/Inventory/QltyItemTrackingMgmt.Codeunit.al\n@@ -465,7 +465,7 @@ codeunit 20439 \"Qlty. Item Tracking Mgmt.\"\n end;\n \n /// \n- /// Adds/Removes Purchase Return Line item tracking entries. When used with serial numbers only one serial number can be created at a time.\n+ /// Adds/Removes Purchase Return Line item tracking entries. When used with serial numbers only one serial number can be created at a time.\n /// \n /// \n /// \ndiff --git a/src/Apps/W1/Quality Management/app/src/Integration/Manufacturing/QltyManufacturIntegration.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Integration/Manufacturing/QltyManufacturIntegration.Codeunit.al\nindex fbd26b1822..8343732866 100644\n--- a/src/Apps/W1/Quality Management/app/src/Integration/Manufacturing/QltyManufacturIntegration.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Integration/Manufacturing/QltyManufacturIntegration.Codeunit.al\n@@ -390,7 +390,7 @@ codeunit 20407 \"Qlty. Manufactur. Integration\"\n if MadeInspection then begin\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n ListOfInspectionIds.Add(QltyInspectionHeader.RecordId());\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n CreatedAtLeastOneInspectionForRoutingLine := true;\n end;\n until ReservationEntry.Next() = 0;\n@@ -400,7 +400,7 @@ codeunit 20407 \"Qlty. Manufactur. Integration\"\n if MadeInspection then begin\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n ListOfInspectionIds.Add(QltyInspectionHeader.RecordId());\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n CreatedAtLeastOneInspectionForRoutingLine := true;\n end;\n end;\n@@ -421,7 +421,7 @@ codeunit 20407 \"Qlty. Manufactur. Integration\"\n if MadeInspection then begin\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n ListOfInspectionIds.Add(QltyInspectionHeader.RecordId());\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n CreatedAtLeastOneInspectionForOrderLine := true;\n end;\n \n@@ -431,7 +431,7 @@ codeunit 20407 \"Qlty. Manufactur. Integration\"\n if MadeInspection then begin\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n ListOfInspectionIds.Add(QltyInspectionHeader.RecordId());\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n CreatedAtLeastOneInspectionForOrderLine := true;\n end;\n end;\n@@ -442,7 +442,7 @@ codeunit 20407 \"Qlty. Manufactur. Integration\"\n if MadeInspection then begin\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n ListOfInspectionIds.Add(QltyInspectionHeader.RecordId());\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n CreatedInspectionForProdOrder := MadeInspection;\n end;\n end;\n@@ -492,7 +492,7 @@ codeunit 20407 \"Qlty. Manufactur. Integration\"\n /// Typically the 'main' record the inspections are associated against.\n /// The item ledger entry related to this sequence of events\n /// The production order line involved in this sequence of events\n- /// The item journal line record involved in this transaction. Important: this record may no longer exist, and should not be altered.\n+ /// The item journal line record involved in this transaction. Important: this record may no longer exist, and should not be altered.\n /// Set to true to replace the default behavior\n [IntegrationEvent(false, false)]\n local procedure OnBeforeProductionAttemptCreatePostAutomaticInspection(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ItemLedgerEntry: Record \"Item Ledger Entry\"; var ProdOrderLine: Record \"Prod. Order Line\"; var ItemJournalLine: Record \"Item Journal Line\"; var IsHandled: Boolean)\n@@ -505,7 +505,7 @@ codeunit 20407 \"Qlty. Manufactur. Integration\"\n /// Typically the 'main' record the inspections are associated against.\n /// The item ledger entry related to this sequence of events\n /// The production order line involved in this sequence of events\n- /// The item journal line record involved in this transaction. Important: this record may no longer exist, and should not be altered.\n+ /// The item journal line record involved in this transaction. Important: this record may no longer exist, and should not be altered.\n [IntegrationEvent(false, false)]\n local procedure OnAfterProductionAttemptCreateAutomaticInspection(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ItemLedgerEntry: Record \"Item Ledger Entry\"; var ProdOrderLine: Record \"Prod. Order Line\"; var ItemJournalLine: Record \"Item Journal Line\")\n begin\n@@ -541,7 +541,7 @@ codeunit 20407 \"Qlty. Manufactur. Integration\"\n /// \n /// The item ledger entry related to this sequence of events\n /// The production order line involved in this sequence of events\n- /// The item journal line record involved in this transaction. Important: this record may no longer exist, and should not be altered.\n+ /// The item journal line record involved in this transaction. Important: this record may no longer exist, and should not be altered.\n /// Set to true to replace the default behavior\n [IntegrationEvent(false, false)]\n local procedure OnBeforeProductionHandleOnAfterPostOutput(var ItemLedgerEntry: Record \"Item Ledger Entry\"; var ProdOrderLine: Record \"Prod. Order Line\"; var ItemJournalLine: Record \"Item Journal Line\"; var IsHandled: Boolean)\ndiff --git a/src/Apps/W1/Quality Management/app/src/Integration/Receiving/QltyReceivingIntegration.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Integration/Receiving/QltyReceivingIntegration.Codeunit.al\nindex 4fb106bf37..1c4dbef6cd 100644\n--- a/src/Apps/W1/Quality Management/app/src/Integration/Receiving/QltyReceivingIntegration.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Integration/Receiving/QltyReceivingIntegration.Codeunit.al\n@@ -170,14 +170,14 @@ codeunit 20411 \"Qlty. Receiving Integration\"\n if QltyInspectionCreate.CreateInspectionWithMultiVariants(SalesLine, TempTrackingSpecification, DummyVariant, DummyVariant, false, QltyInspectionGenRule) then begin\n HasInspection := true;\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n until TempTrackingSpecification.Next() = 0\n else\n if QltyInspectionCreate.CreateInspectionWithMultiVariants(SalesLine, DummyVariant, DummyVariant, DummyVariant, false, QltyInspectionGenRule) then begin\n HasInspection := true;\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n QltyBatchNotifHelper.EndBatch();\n end;\n@@ -306,7 +306,7 @@ codeunit 20411 \"Qlty. Receiving Integration\"\n if QltyInspectionCreate.CreateInspectionWithMultiVariants(WarehouseReceiptLine, OptionalSourceLineVariant, WarehouseReceiptHeader, TempTrackingSpecification, false, TempQltyInspectionGenRule) then begin\n HasInspection := true;\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n until TempTrackingSpecification.Next() = 0\n else begin\n@@ -314,7 +314,7 @@ codeunit 20411 \"Qlty. Receiving Integration\"\n if QltyInspectionCreate.CreateInspectionWithMultiVariants(WarehouseReceiptLine, OptionalSourceLineVariant, WarehouseReceiptHeader, DummyVariant, false, TempQltyInspectionGenRule) then begin\n HasInspection := true;\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n end;\n \n@@ -350,7 +350,7 @@ codeunit 20411 \"Qlty. Receiving Integration\"\n if QltyInspectionCreate.CreateInspectionWithMultiVariants(WarehouseJournalLine, OptionalSourceRecordVariant, PostedWhseReceiptHeader, TempTrackingSpecification, false, TempQltyInspectionGenRule) then begin\n HasInspection := true;\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n until TempTrackingSpecification.Next() = 0\n else begin\n@@ -358,7 +358,7 @@ codeunit 20411 \"Qlty. Receiving Integration\"\n if QltyInspectionCreate.CreateInspectionWithMultiVariants(WarehouseJournalLine, OptionalSourceRecordVariant, PostedWhseReceiptHeader, DummyVariant, false, TempQltyInspectionGenRule) then begin\n HasInspection := true;\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n end;\n \n@@ -384,7 +384,7 @@ codeunit 20411 \"Qlty. Receiving Integration\"\n HasInspection := QltyInspectionCreate.CreateInspectionWithMultiVariants(PurchaseLine, PurchaseHeader, TempTrackingSpecification, DummyVariant, false, TempQltyInspectionGenRule);\n if HasInspection then begin\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n \n OnAfterPurchaseAttemptCreateInspectionWithPurchaseLine(HasInspection, QltyInspectionHeader, PurchaseLine, PurchaseHeader, TempTrackingSpecification);\n@@ -423,7 +423,7 @@ codeunit 20411 \"Qlty. Receiving Integration\"\n \n if HasInspection then begin\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n until TempTrackingSpecification.Next() = 0\n else begin\n@@ -436,7 +436,7 @@ codeunit 20411 \"Qlty. Receiving Integration\"\n \n if HasInspection then begin\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n end;\n OnAfterTransferAttemptCreateInspectionWithInboundTransferLine(TransTransferLine, OptionalTransferReceiptHeader, OptionalDirectTransHeader, TempTrackingSpecification, QltyInspectionHeader, HasInspection);\ndiff --git a/src/Apps/W1/Quality Management/app/src/Integration/Warehouse/QltyWarehouseIntegration.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Integration/Warehouse/QltyWarehouseIntegration.Codeunit.al\nindex df7071bab4..61111f4e45 100644\n--- a/src/Apps/W1/Quality Management/app/src/Integration/Warehouse/QltyWarehouseIntegration.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Integration/Warehouse/QltyWarehouseIntegration.Codeunit.al\n@@ -70,14 +70,14 @@ codeunit 20438 \"Qlty. Warehouse Integration\"\n if QltyInspectionCreate.CreateInspectionWithMultiVariants(WarehouseEntry, WarehouseJournalLine, TempTrackingSpecification, DummyVariant, false, QltyInspectionGenRule) then begin\n HasInspection := true;\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n until TempTrackingSpecification.Next() = 0\n else\n if QltyInspectionCreate.CreateInspectionWithMultiVariants(WarehouseEntry, WarehouseJournalLine, DummyVariant, DummyVariant, false, QltyInspectionGenRule) then begin\n HasInspection := true;\n QltyInspectionCreate.GetCreatedInspection(QltyInspectionHeader);\n- QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\");\n+ QltyBatchNotifHelper.TrackCreatedInspection(QltyInspectionHeader.\"No.\", QltyInspectionCreate.IsLastInspectionNewlyCreated());\n end;\n QltyBatchNotifHelper.EndBatch();\n \ndiff --git a/src/Apps/W1/Quality Management/app/src/Utilities/QltyBatchNotifHelper.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Utilities/QltyBatchNotifHelper.Codeunit.al\nindex 4269b2b85b..573549f905 100644\n--- a/src/Apps/W1/Quality Management/app/src/Utilities/QltyBatchNotifHelper.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Utilities/QltyBatchNotifHelper.Codeunit.al\n@@ -9,12 +9,12 @@ using Microsoft.QualityManagement.Document;\n codeunit 20456 \"Qlty. Batch Notif. Helper\"\n {\n var\n- BatchCreatedInspectionIds: List of [Code[20]];\n+ BatchCreatedQltyInspectionIds: List of [Code[20]];\n IsBatchActive: Boolean;\n \n internal procedure BeginBatch()\n begin\n- Clear(BatchCreatedInspectionIds);\n+ Clear(BatchCreatedQltyInspectionIds);\n IsBatchActive := true;\n end;\n \n@@ -26,23 +26,26 @@ codeunit 20456 \"Qlty. Batch Notif. Helper\"\n exit;\n \n IsBatchActive := false;\n- if BatchCreatedInspectionIds.Count() = 0 then\n+ if BatchCreatedQltyInspectionIds.Count() = 0 then\n exit;\n \n- QltyInspectionCreate.DisplayInspectionsIfConfigured(false, BatchCreatedInspectionIds);\n- Clear(BatchCreatedInspectionIds);\n+ QltyInspectionCreate.DisplayInspectionsIfConfigured(false, BatchCreatedQltyInspectionIds);\n+ Clear(BatchCreatedQltyInspectionIds);\n end;\n \n- internal procedure TrackCreatedInspection(InspectionNo: Code[20])\n+ internal procedure TrackCreatedInspection(InspectionNo: Code[20]; IsNewlyCreated: Boolean)\n begin\n if not IsBatchActive then\n exit;\n \n+ if not IsNewlyCreated then\n+ exit;\n+\n if InspectionNo = '' then\n exit;\n \n- if not BatchCreatedInspectionIds.Contains(InspectionNo) then\n- BatchCreatedInspectionIds.Add(InspectionNo);\n+ if not BatchCreatedQltyInspectionIds.Contains(InspectionNo) then\n+ BatchCreatedQltyInspectionIds.Add(InspectionNo);\n end;\n \n internal procedure ConfigureForBatch(var QltyInspectionCreate: Codeunit \"Qlty. Inspection - Create\")\ndiff --git a/src/Apps/W1/Quality Management/app/src/Utilities/QltyMiscHelpers.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Utilities/QltyMiscHelpers.Codeunit.al\nindex fffa286fab..87a723a23c 100644\n--- a/src/Apps/W1/Quality Management/app/src/Utilities/QltyMiscHelpers.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Utilities/QltyMiscHelpers.Codeunit.al\n@@ -80,7 +80,7 @@ codeunit 20599 \"Qlty. Misc Helpers\"\n /// This will evaluate expressions!\n /// \n /// \n- /// Optional. Leave empty if you do not want search/replace fields. Supply an inspection context if you want the lookup table filter to have square bracket [FIELDNAME] replacements \n+ /// Optional. Leave empty if you do not want search/replace fields. Supply an inspection context if you want the lookup table filter to have square bracket [FIELDNAME] replacements \n /// \n internal procedure GetRecordsForTableField(var QltyTest: Record \"Qlty. Test\"; var OptionalContextQltyInspectionHeader: Record \"Qlty. Inspection Header\"; var TempBufferQltyTestLookupValue: Record \"Qlty. Test Lookup Value\" temporary)\n var\n", "FAIL_TO_PASS": [{"codeunitID": 139959, "functionName": ["CreateInspection_ReusedExisting_NotReportedAsNewlyCreated", "CreateInspection_NewInsertion_ReportedAsNewlyCreated", "CreateMultipleInspections_ReusedExisting_ExcludedFromCreatedIdsList"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/Test Library/src/QltyInspectionUtility.Codeunit.al b/src/Apps/W1/Quality Management/Test Library/src/QltyInspectionUtility.Codeunit.al\nindex 3385ee112c..14c1d2a042 100644\n--- a/src/Apps/W1/Quality Management/Test Library/src/QltyInspectionUtility.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/Test Library/src/QltyInspectionUtility.Codeunit.al\n@@ -1336,6 +1336,47 @@ codeunit 139940 \"Qlty. Inspection Utility\"\n exit(Result);\n end;\n \n+ /// \n+ /// Wrapper for QltyInspectionCreate.CreateInspection that also reports whether the returned inspection was newly created or reused.\n+ /// Use this in tests that verify the \"newly created vs reused\" distinction (e.g., to assert the inspection-created notification\n+ /// is only raised for newly created inspections).\n+ /// \n+ /// The source record to create an inspection from.\n+ /// True when user manually creates inspection; False for automatic/triggered creation.\n+ /// Output: the created or reused inspection header.\n+ /// Output: true when the inspection was newly inserted; false when an existing inspection was reused.\n+ /// True if an inspection was created or found/reused.\n+ internal procedure CreateInspectionAndReportIfNewlyCreated(TargetRecordRef: RecordRef; IsManualCreation: Boolean; var OutQltyInspectionHeader: Record \"Qlty. Inspection Header\"; var OutIsNewlyCreated: Boolean): Boolean\n+ var\n+ QltyInspectionCreate: Codeunit \"Qlty. Inspection - Create\";\n+ Result: Boolean;\n+ begin\n+ Result := QltyInspectionCreate.CreateInspection(TargetRecordRef, IsManualCreation);\n+ OutIsNewlyCreated := false;\n+ if Result then begin\n+ QltyInspectionCreate.GetCreatedInspection(OutQltyInspectionHeader);\n+ OutIsNewlyCreated := QltyInspectionCreate.IsLastInspectionNewlyCreated();\n+ end;\n+ exit(Result);\n+ end;\n+\n+ /// \n+ /// Wrapper for internal QltyInspectionCreate.CreateMultipleInspectionsWithoutDisplaying.\n+ /// Returns both the inspections that were newly created and the full set of inspections that were resolved\n+ /// (new + reused).\n+ /// \n+ /// RecordRef containing the records to create inspections for.\n+ /// Whether this is a manual creation (affects display behavior).\n+ /// Temporary record with filters that constrain which generation rules apply.\n+ /// Output: list of inspection \"No.\" values for inspections that were newly inserted.\n+ /// Output: list of inspection \"No.\" values for every inspection that was newly inserted or reused.\n+ internal procedure CreateMultipleInspectionsWithoutDisplaying(var SetOfRecordsRecordRef: RecordRef; IsManualCreation: Boolean; var TempFiltersQltyInspectionGenRule: Record \"Qlty. Inspection Gen. Rule\" temporary; var OutNewlyCreatedQltyInspectionIds: List of [Code[20]]; var OutAllResolvedQltyInspectionIds: List of [Code[20]])\n+ var\n+ QltyInspectionCreate: Codeunit \"Qlty. Inspection - Create\";\n+ begin\n+ QltyInspectionCreate.CreateMultipleInspectionsWithoutDisplaying(SetOfRecordsRecordRef, IsManualCreation, TempFiltersQltyInspectionGenRule, OutNewlyCreatedQltyInspectionIds, OutAllResolvedQltyInspectionIds);\n+ end;\n+\n /// \n /// Wrapper for QltyInspectionCreate.CreateInspectionWithVariant.\n /// Creates a quality inspection from a variant using generation rule configuration.\n@@ -1527,7 +1568,7 @@ codeunit 139940 \"Qlty. Inspection Utility\"\n exit(QltyInspectionCreate.FindExistingInspectionWithVariant(TargetRecordRef, OptionalVariant2, OptionalVariant3, OptionalVariant4, TempQltyInspectionGenRule, OutQltyInspectionHeader, FindAll));\n end;\n \n- #endregion Qlty. Inspection - Create Wrappers\n+ #endregion Qlty. Inspection - Create Wrappers \n \n #region Qlty. Disposition Wrappers\n \n@@ -1536,10 +1577,10 @@ codeunit 139940 \"Qlty. Inspection Utility\"\n /// Performs disposition and returns the created purchase return buffer.\n /// \n internal procedure PerformPurchaseReturnDisposition(var QltyInspectionHeader: Record \"Qlty. Inspection Header\"; QltyQuantityBehavior: Enum \"Qlty. Quantity Behavior\"; OptionalSpecificQuantity: Decimal;\n- OptionalSourceLocationFilter: Text;\n- OptionalSourceBinFilter: Text;\n- ReasonCode: Code[10];\n- ExternalDocumentNo: Code[35]; var TempCreatedBufferPurchaseHeader: Record \"Purchase Header\" temporary): Boolean\n+ OptionalSourceLocationFilter: Text;\n+ OptionalSourceBinFilter: Text;\n+ ReasonCode: Code[10];\n+ ExternalDocumentNo: Code[35]; var TempCreatedBufferPurchaseHeader: Record \"Purchase Header\" temporary): Boolean\n var\n QltyDispPurchaseReturn: Codeunit \"Qlty. Disp. Purchase Return\";\n Result: Boolean;\n@@ -1553,9 +1594,9 @@ codeunit 139940 \"Qlty. Inspection Utility\"\n /// Wrapper for internal QltyDispNegAdjustInv.PerformDisposition (7-argument version).\n /// \n internal procedure PerformNegAdjustInvDisposition(var QltyInspectionHeader: Record \"Qlty. Inspection Header\"; OptionalSpecificQuantity: Decimal; QltyQuantityBehavior: Enum \"Qlty. Quantity Behavior\"; OptionalSourceLocationFilter: Text;\n- OptionalSourceBinFilter: Text;\n- PostingBehavior: Enum \"Qlty. Item Adj. Post Behavior\";\n- Reason: Code[10]): Boolean\n+ OptionalSourceBinFilter: Text;\n+ PostingBehavior: Enum \"Qlty. Item Adj. Post Behavior\";\n+ Reason: Code[10]): Boolean\n var\n QltyDispNegAdjustInv: Codeunit \"Qlty. Disp. Neg. Adjust Inv.\";\n begin\n@@ -1566,9 +1607,9 @@ codeunit 139940 \"Qlty. Inspection Utility\"\n /// Wrapper for internal QltyDispTransfer.PerformDisposition (7-argument version).\n /// \n internal procedure PerformTransferDisposition(QltyInspectionHeader: Record \"Qlty. Inspection Header\"; OptionalSpecificQuantity: Decimal; QltyQuantityBehavior: Enum \"Qlty. Quantity Behavior\"; OptionalSourceLocationFilter: Text;\n- OptionalSourceBinFilter: Text;\n- DestinationLocationCode: Code[10];\n- OptionalInTransitLocationCode: Code[10]): Boolean\n+ OptionalSourceBinFilter: Text;\n+ DestinationLocationCode: Code[10];\n+ OptionalInTransitLocationCode: Code[10]): Boolean\n var\n QltyDispTransfer: Codeunit \"Qlty. Disp. Transfer\";\n begin\n@@ -3102,7 +3143,8 @@ codeunit 139940 \"Qlty. Inspection Utility\"\n /// \n /// Wrapper for QltyResultEvaluation.EvaluateResult\n /// \n- internal procedure EvaluateResult(var OptionalQltyInspectionHeader: Record \"Qlty. Inspection Header\"; var OptionalQltyInspectionLine: Record \"Qlty. Inspection Line\"; var QltyIResultConditConf: Record \"Qlty. I. Result Condit. Conf.\"; QltyTestValueType: Enum \"Qlty. Test Value Type\"; TestValue: Text; QltyCaseSensitivity: Enum \"Qlty. Case Sensitivity\"): Code[20]\n+ internal procedure EvaluateResult(var OptionalQltyInspectionHeader: Record \"Qlty. Inspection Header\"; var OptionalQltyInspectionLine: Record \"Qlty. Inspection Line\"; var QltyIResultConditConf: Record \"Qlty. I. Result Condit. Conf.\"; QltyTestValueType: Enum \"Qlty. Test Value Type\"; TestValue: Text;\n+ QltyCaseSensitivity: Enum \"Qlty. Case Sensitivity\"): Code[20]\n var\n QltyResultEvaluation: Codeunit \"Qlty. Result Evaluation\";\n begin\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsCreateInspect.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsCreateInspect.Codeunit.al\nindex cedf4c0eef..e7cb04f0e7 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsCreateInspect.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsCreateInspect.Codeunit.al\n@@ -33,8 +33,8 @@ codeunit 139959 \"Qlty. Tests - Create Inspect.\"\n QltyInspectionUtility: Codeunit \"Qlty. Inspection Utility\";\n CannotFindTemplateErr: Label 'Cannot find a Quality Inspection Template or Quality Inspection Generation Rule to match %1. Ensure there is a Quality Inspection Generation Rule that will match this record.', Comment = '%1=The record identifier';\n ProgrammerErrNotARecordRefErr: Label 'Cannot find inspections with %1. Please supply a \"Record\" or \"RecordRef\".', Comment = '%1=the variant being supplied that is not a RecordRef. Your system might have an extension or customization that needs to be re-configured.';\n- UnableToCreateInspectionForRecordErr: Label 'Cannot find enough details to make an inspection for your record(s). Try making sure that there is a source configuration for your record, and then also make sure there is sufficient information in your inspection generation rules. The table involved is %1.', Comment = '%1=the table involved.';\n- UnableToCreateInspectionForParentOrChildErr: Label 'Cannot find enough details to make an inspection for your record(s). Try making sure that there is a source configuration for your record, and then also make sure there is sufficient information in your inspection generation rules. Two tables involved are %1 and %2.', Comment = '%1=the parent table, %2=the child and original table.';\n+ UnableToCreateInspectionForRecordErr: Label 'Cannot find enough details to make an inspection for your record(s). Try making sure that there is a source configuration for your record, and then also make sure there is sufficient information in your inspection generation rules. The table involved is %1.', Comment = '%1=the table involved.';\n+ UnableToCreateInspectionForParentOrChildErr: Label 'Cannot find enough details to make an inspection for your record(s). Try making sure that there is a source configuration for your record, and then also make sure there is sufficient information in your inspection generation rules. Two tables involved are %1 and %2.', Comment = '%1=the parent table, %2=the child and original table.';\n IsInitialized: Boolean;\n \n [Test]\n@@ -2485,6 +2485,174 @@ codeunit 139959 \"Qlty. Tests - Create Inspect.\"\n LibraryAssert.ExpectedError(StrSubstNo(UnableToCreateInspectionForParentOrChildErr, ProdOrderLine.TableName, ProdOrderRoutingLineRecordRef.Name));\n end;\n \n+ [Test]\n+ procedure CreateInspection_NewInsertion_ReportedAsNewlyCreated()\n+ var\n+ QltyInspectionTemplateHdr: Record \"Qlty. Inspection Template Hdr.\";\n+ QltyInspectionGenRule: Record \"Qlty. Inspection Gen. Rule\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ ProdProductionOrder: Record \"Production Order\";\n+ Item: Record Item;\n+ CreatedQltyInspectionHeader: Record \"Qlty. Inspection Header\";\n+ ProdOrderRoutingLineRecordRef: RecordRef;\n+ ClaimedInspectionWasFoundOrCreated: Boolean;\n+ IsNewlyCreated: Boolean;\n+ begin\n+ // [SCENARIO] When CreateInspection inserts a new inspection, IsLastInspectionNewlyCreated must report true (so the inspection-created notification is raised).\n+\n+ Initialize();\n+\n+ // [GIVEN] A quality inspection template, generation rule, item, and production order with routing line are set up\n+ SetupCreateInspectionProductionOrder(QltyInspectionTemplateHdr, QltyInspectionGenRule, Item, ProdProductionOrder, ProdOrderRoutingLine);\n+\n+ ProdOrderRoutingLineRecordRef.GetTable(ProdOrderRoutingLine);\n+\n+ // [WHEN] CreateInspection is called for the routing line for the first time\n+ ClaimedInspectionWasFoundOrCreated := QltyInspectionUtility.CreateInspectionAndReportIfNewlyCreated(ProdOrderRoutingLineRecordRef, false, CreatedQltyInspectionHeader, IsNewlyCreated);\n+\n+ QltyInspectionGenRule.Delete();\n+\n+ // [THEN] The inspection is created and reported as newly created so the \"Quality Inspection created\" notification is raised\n+ LibraryAssert.IsTrue(ClaimedInspectionWasFoundOrCreated, 'Should claim an inspection has been found/created.');\n+ LibraryAssert.IsTrue(IsNewlyCreated, 'A newly inserted inspection must be reported as newly created so the inspection-created notification is raised.');\n+ end;\n+\n+ [Test]\n+ procedure CreateInspection_ReusedExisting_NotReportedAsNewlyCreated()\n+ var\n+ QltyManagementSetup: Record \"Qlty. Management Setup\";\n+ QltyInspectionTemplateHdr: Record \"Qlty. Inspection Template Hdr.\";\n+ QltyInspectionGenRule: Record \"Qlty. Inspection Gen. Rule\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ ProdProductionOrder: Record \"Production Order\";\n+ Item: Record Item;\n+ QltyInspectionHeader: Record \"Qlty. Inspection Header\";\n+ FirstCreatedQltyInspectionHeader: Record \"Qlty. Inspection Header\";\n+ SecondQltyInspectionHeader: Record \"Qlty. Inspection Header\";\n+ ProdOrderRoutingLineRecordRef: RecordRef;\n+ PreviousQltyCreateInspectBehavior: Enum \"Qlty. Inspect. Creation Option\";\n+ ClaimedInspectionWasFoundOrCreated: Boolean;\n+ IsNewlyCreated: Boolean;\n+ BeforeCount: Integer;\n+ AfterCount: Integer;\n+ begin\n+ // [SCENARIO] When CreateInspection reuses an existing inspection (Inspection Creation Option = \"Use existing open inspection if available\"),\n+ // IsLastInspectionNewlyCreated must report false so the inspection-created notification is suppressed.\n+\n+ Initialize();\n+\n+ // [GIVEN] A quality inspection template, generation rule, item, and production order with routing line are set up\n+ SetupCreateInspectionProductionOrder(QltyInspectionTemplateHdr, QltyInspectionGenRule, Item, ProdProductionOrder, ProdOrderRoutingLine);\n+\n+ // [GIVEN] A first inspection is created and left open\n+ ProdOrderRoutingLineRecordRef.GetTable(ProdOrderRoutingLine);\n+ QltyInspectionUtility.CreateInspection(ProdOrderRoutingLineRecordRef, false, FirstCreatedQltyInspectionHeader);\n+\n+ // [GIVEN] The Inspection Creation Option is set to \"Use existing open inspection if available\"\n+ QltyManagementSetup.Get();\n+ PreviousQltyCreateInspectBehavior := QltyManagementSetup.\"Inspection Creation Option\";\n+ QltyManagementSetup.\"Inspection Creation Option\" := QltyManagementSetup.\"Inspection Creation Option\"::\"Use existing open inspection if available\";\n+ QltyManagementSetup.Modify();\n+\n+ QltyInspectionHeader.Reset();\n+ BeforeCount := QltyInspectionHeader.Count();\n+\n+ // [WHEN] CreateInspection is called again for the same routing line while the first inspection is still open\n+ ClaimedInspectionWasFoundOrCreated := QltyInspectionUtility.CreateInspectionAndReportIfNewlyCreated(ProdOrderRoutingLineRecordRef, false, SecondQltyInspectionHeader, IsNewlyCreated);\n+\n+ QltyManagementSetup.\"Inspection Creation Option\" := PreviousQltyCreateInspectBehavior;\n+ QltyManagementSetup.Modify();\n+ QltyInspectionGenRule.Delete();\n+\n+ QltyInspectionHeader.Reset();\n+ AfterCount := QltyInspectionHeader.Count();\n+\n+ // [THEN] No new inspection is inserted, the existing inspection is returned, and the call is reported as a reuse so the inspection-created notification is suppressed\n+ LibraryAssert.IsTrue(ClaimedInspectionWasFoundOrCreated, 'Should claim an inspection has been found/created.');\n+ LibraryAssert.AreEqual(BeforeCount, AfterCount, 'No new inspection should have been inserted when reusing.');\n+ LibraryAssert.AreEqual(FirstCreatedQltyInspectionHeader.\"No.\", SecondQltyInspectionHeader.\"No.\", 'Should have returned the existing inspection.');\n+ LibraryAssert.IsFalse(IsNewlyCreated, 'A reused inspection must not be reported as newly created so the inspection-created notification is suppressed.');\n+ end;\n+\n+ [Test]\n+ procedure CreateMultipleInspections_ReusedExisting_ExcludedFromCreatedIdsList()\n+ var\n+ QltyManagementSetup: Record \"Qlty. Management Setup\";\n+ QltyInspectionTemplateHdr: Record \"Qlty. Inspection Template Hdr.\";\n+ QltyInspectionGenRule: Record \"Qlty. Inspection Gen. Rule\";\n+ TempFilterQltyInspectionGenRule: Record \"Qlty. Inspection Gen. Rule\" temporary;\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ QltyInspectionHeader: Record \"Qlty. Inspection Header\";\n+ FirstCreatedQltyInspectionHeader: Record \"Qlty. Inspection Header\";\n+ QltyProdOrderGenerator: Codeunit \"Qlty. Prod. Order Generator\";\n+ FirstRoutingLineRecordRef: RecordRef;\n+ AllRoutingLinesRecordRef: RecordRef;\n+ CreatedQltyInspectionIds, AllResolvedQltyInspectionIds : List of [Code[20]];\n+ OrdersList: List of [Code[20]];\n+ ProductionOrder: Code[20];\n+ PreviousQltyCreateInspectBehavior: Enum \"Qlty. Inspect. Creation Option\";\n+ BeforeCount: Integer;\n+ AfterCount: Integer;\n+ begin\n+ // [SCENARIO] CreateMultipleInspectionsWithoutDisplaying should only include newly inserted inspection numbers in the returned list of created inspection ids;\n+ // inspections that were merely reused must not inflate the \"created\" list that drives the inspection-created notifications/display.\n+\n+ Initialize();\n+ QltyInspectionUtility.EnsureSetupExists();\n+ QltyInspectionUtility.CreateTemplate(QltyInspectionTemplateHdr, 3);\n+ QltyInspectionUtility.CreatePrioritizedRule(QltyInspectionTemplateHdr, Database::\"Prod. Order Routing Line\", QltyInspectionGenRule);\n+\n+ // [GIVEN] 3 production orders, each with a routing line\n+ QltyProdOrderGenerator.Init(100);\n+ QltyProdOrderGenerator.ToggleAllSources(false);\n+ QltyProdOrderGenerator.ToggleSourceType(\"Prod. Order Source Type\"::Item, true);\n+ QltyProdOrderGenerator.Generate(3, OrdersList);\n+\n+ // [GIVEN] An inspection is pre-created for the first production order so it will be reused on the next call\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrderRoutingLine.Status::Released);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", OrdersList.Get(1));\n+ ProdOrderRoutingLine.FindLast();\n+ FirstRoutingLineRecordRef.GetTable(ProdOrderRoutingLine);\n+ QltyInspectionUtility.CreateInspection(FirstRoutingLineRecordRef, false, FirstCreatedQltyInspectionHeader);\n+\n+ // [GIVEN] The Inspection Creation Option is set to \"Use existing open inspection if available\" so the first routing line reuses, the other two create new\n+ QltyManagementSetup.Get();\n+ PreviousQltyCreateInspectBehavior := QltyManagementSetup.\"Inspection Creation Option\";\n+ QltyManagementSetup.\"Inspection Creation Option\" := QltyManagementSetup.\"Inspection Creation Option\"::\"Use existing open inspection if available\";\n+ QltyManagementSetup.Modify();\n+\n+ // [GIVEN] A RecordRef containing the routing lines of all three production orders\n+ AllRoutingLinesRecordRef.Open(Database::\"Prod. Order Routing Line\", true);\n+ foreach ProductionOrder in OrdersList do begin\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder);\n+ ProdOrderRoutingLine.FindLast();\n+ AllRoutingLinesRecordRef.Copy(ProdOrderRoutingLine, false);\n+ AllRoutingLinesRecordRef.Insert();\n+ end;\n+\n+ QltyInspectionHeader.Reset();\n+ BeforeCount := QltyInspectionHeader.Count();\n+\n+ // [WHEN] CreateMultipleInspectionsWithoutDisplaying is called for all three routing lines\n+ QltyInspectionUtility.CreateMultipleInspectionsWithoutDisplaying(AllRoutingLinesRecordRef, false, TempFilterQltyInspectionGenRule, CreatedQltyInspectionIds, AllResolvedQltyInspectionIds);\n+\n+ QltyManagementSetup.\"Inspection Creation Option\" := PreviousQltyCreateInspectBehavior;\n+ QltyManagementSetup.Modify();\n+ QltyInspectionGenRule.Delete();\n+\n+ QltyInspectionHeader.Reset();\n+ AfterCount := QltyInspectionHeader.Count();\n+\n+ // [THEN] Only 2 new inspections were inserted (for production orders 2 and 3)\n+ LibraryAssert.AreEqual((BeforeCount + 2), AfterCount, 'Only the two non-reused routing lines should have inserted new inspections.');\n+ // [THEN] The returned list of created inspection ids excludes the reused inspection so the \"created inspections\" notification is not falsely inflated\n+ LibraryAssert.AreEqual(2, CreatedQltyInspectionIds.Count(), 'The created inspection ids list must exclude reused inspections.');\n+ LibraryAssert.IsFalse(CreatedQltyInspectionIds.Contains(FirstCreatedQltyInspectionHeader.\"No.\"), 'A reused inspection must not appear in the created inspection ids list.');\n+ // [THEN] The all-resolved list includes both the 2 newly created inspections and the 1 reused inspection\n+ LibraryAssert.AreEqual(3, AllResolvedQltyInspectionIds.Count(), 'The all-resolved list must include every inspection that was newly created or reused.');\n+ LibraryAssert.IsTrue(AllResolvedQltyInspectionIds.Contains(FirstCreatedQltyInspectionHeader.\"No.\"), 'The all-resolved list must include the reused inspection.');\n+ end;\n+\n local procedure CreateInspectionWithTracking(var PurOrdPurchaseLine: Record \"Purchase Line\"; var TempSpecTrackingSpecification: Record \"Tracking Specification\" temporary; var OutQltyInspectionHeader: Record \"Qlty. Inspection Header\")\n var\n PurchaseLineRecordRef: RecordRef;\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsDispositions.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsDispositions.Codeunit.al\nindex 22897ed285..866d0afe64 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsDispositions.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsDispositions.Codeunit.al\n@@ -49,7 +49,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n QltyPurOrderGenerator: Codeunit \"Qlty. Pur. Order Generator\";\n LibraryWarehouse: Codeunit \"Library - Warehouse\";\n QltyInspectionUtility: Codeunit \"Qlty. Inspection Utility\";\n- ReUsedLibraryItemTracking: Codeunit \"Library - Item Tracking\";\n+ LibraryItemTracking: Codeunit \"Library - Item Tracking\";\n NoPurchRcptLineErr: Label 'Could not find a related purchase receipt line with sufficient quantity for %1 from Quality Inspection %2,%3. Confirm the inspection source is a Purchase Line and that it has been received prior to creating a return.', Comment = '%1=item,%2=inspection,%3=re-inspection';\n WriteOffEntireItemTrackingErr: Label 'Reducing inventory using the item tracked quantity for inspection %1 was requested, however the item associated with this inspection does not require tracking.', Comment = '%1=the inspection';\n MissingAdjBatchErr: Label 'There is missing setup on the Quality Management Setup Card defining the adjustment batch.';\n@@ -304,7 +304,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n ReclassWarehouseJournalLine.\"New Lot No.\" := ReclassWarehouseJournalLine.\"Lot No.\";\n ReclassWarehouseJournalLine.Modify();\n // [GIVEN] Item tracking is created for the reclassification journal line\n- ReUsedLibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', PurOrdReservationEntry.\"Lot No.\", 50);\n+ LibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', PurOrdReservationEntry.\"Lot No.\", 50);\n ReclassWarehouseJournalWhseItemTrackingLine.\"New Lot No.\" := ReclassWarehouseJournalWhseItemTrackingLine.\"Lot No.\";\n ReclassWarehouseJournalWhseItemTrackingLine.Modify();\n // [GIVEN] The warehouse journal is registered to complete the movement\n@@ -765,7 +765,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryAssert.AreEqual(1, NegativeAdjustmentItemJournalLine.Count(), 'test setup failed, should be only 1 line after a modify');\n \n // [GIVEN] Item tracking with lot number is assigned to the journal line\n- ReUsedLibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, '', OriginalLotNo, InitialInspectionInventoryJnlItemJournalLine.Quantity);\n+ LibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, '', OriginalLotNo, InitialInspectionInventoryJnlItemJournalLine.Quantity);\n \n // [GIVEN] Item ledger entry filters are set up for validation\n ItemLedgerEntry.SetRange(\"Item No.\", InitialInspectionInventoryJnlItemJournalLine.\"Item No.\");\n@@ -888,7 +888,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryUtility.CreateNoSeries(LotNoSeries, true, true, false);\n LibraryUtility.CreateNoSeriesLine(LotNoSeriesLine, LotNoSeries.Code, PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '0'), PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '9'));\n \n- ReUsedLibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n+ LibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n LibraryInventory.CreateTrackedItem(Item, LotNoSeries.Code, '', LotItemTrackingCode.Code);\n \n // [GIVEN] Bin contents are created for all bins in the location\n@@ -1218,7 +1218,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n ReclassWarehouseJournalLine.\"New Lot No.\" := ReclassWarehouseJournalLine.\"Lot No.\";\n ReclassWarehouseJournalLine.Modify();\n \n- ReUsedLibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', PurOrdReservationEntry.\"Lot No.\", 50);\n+ LibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', PurOrdReservationEntry.\"Lot No.\", 50);\n ReclassWarehouseJournalWhseItemTrackingLine.\"New Lot No.\" := ReclassWarehouseJournalWhseItemTrackingLine.\"Lot No.\";\n ReclassWarehouseJournalWhseItemTrackingLine.Modify();\n \n@@ -1822,7 +1822,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryUtility.CreateNoSeries(LotNoSeries, true, true, false);\n LibraryUtility.CreateNoSeriesLine(LotNoSeriesLine, LotNoSeries.Code, PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '0'), PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '9'));\n \n- ReUsedLibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n+ LibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n LibraryInventory.CreateTrackedItem(Item, LotNoSeries.Code, '', LotItemTrackingCode.Code);\n \n // [GIVEN] Non-directed pick location with bins is created\n@@ -1857,7 +1857,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryAssert.AreEqual(1, InitialInventoryItemJournalLine.Count(), 'test setup failed, should be only 1 line after a modify');\n \n // [GIVEN] Item tracking with original lot number is assigned to the journal line\n- ReUsedLibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, '', OriginalLotNo, InitialInspectionInventoryJnlItemJournalLine.Quantity);\n+ LibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, '', OriginalLotNo, InitialInspectionInventoryJnlItemJournalLine.Quantity);\n \n // [GIVEN] Item ledger entry filters are set up and journal is posted\n ItemLedgerEntry.SetRange(\"Item No.\", InitialInspectionInventoryJnlItemJournalLine.\"Item No.\");\n@@ -1973,7 +1973,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryUtility.CreateNoSeries(LotNoSeries, true, true, false);\n LibraryUtility.CreateNoSeriesLine(LotNoSeriesLine, LotNoSeries.Code, PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '0'), PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '9'));\n \n- ReUsedLibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n+ LibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n LibraryInventory.CreateTrackedItem(Item, LotNoSeries.Code, '', LotItemTrackingCode.Code);\n \n // [GIVEN] Full WMS location is created with bins and bin content for the item\n@@ -2136,7 +2136,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryUtility.CreateNoSeries(SerialNoSeries, true, true, false);\n LibraryUtility.CreateNoSeriesLine(SerialNoSeriesLine, SerialNoSeries.Code, PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '0'), PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '9'));\n \n- ReUsedLibraryItemTracking.CreateItemTrackingCode(SerialItemTrackingCode, true, false, false);\n+ LibraryItemTracking.CreateItemTrackingCode(SerialItemTrackingCode, true, false, false);\n LibraryInventory.CreateTrackedItem(Item, '', SerialNoSeries.Code, SerialItemTrackingCode.Code);\n \n // [GIVEN] Non-directed pick location with bins is created\n@@ -2172,7 +2172,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryAssert.AreEqual(1, InitialInventoryItemJournalLine.Count(), 'test setup failed, should be only 1 line after a modify');\n \n // [GIVEN] Item tracking with original serial number is assigned to the journal line\n- ReUsedLibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, OriginalSerialNo, '', InitialInspectionInventoryJnlItemJournalLine.Quantity);\n+ LibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, OriginalSerialNo, '', InitialInspectionInventoryJnlItemJournalLine.Quantity);\n \n // [GIVEN] Item ledger entry filters are set up and journal is posted\n ItemLedgerEntry.SetRange(\"Item No.\", InitialInspectionInventoryJnlItemJournalLine.\"Item No.\");\n@@ -2292,7 +2292,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryUtility.CreateNoSeriesLine(SerialNoSeriesLine, SerialNoSeries.Code, PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '0'), PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '9'));\n \n // [GIVEN] Item tracking code is created for serial tracking\n- ReUsedLibraryItemTracking.CreateItemTrackingCode(SerialItemTrackingCode, true, false, false);\n+ LibraryItemTracking.CreateItemTrackingCode(SerialItemTrackingCode, true, false, false);\n \n // [GIVEN] Serial-tracked item is created with item tracking code\n LibraryInventory.CreateTrackedItem(Item, '', SerialNoSeries.Code, SerialItemTrackingCode.Code);\n@@ -2484,7 +2484,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryUtility.CreateNoSeries(PackageNoSeries, true, true, false);\n LibraryUtility.CreateNoSeriesLine(PackageNoSeriesLine, PackageNoSeries.Code, PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '0'), PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '9'));\n \n- ReUsedLibraryItemTracking.CreateItemTrackingCode(PackageItemTrackingCode, false, false, true);\n+ LibraryItemTracking.CreateItemTrackingCode(PackageItemTrackingCode, false, false, true);\n InventorySetup.Get();\n InventorySetup.Validate(\"Package Nos.\", PackageNoSeries.Code);\n InventorySetup.Modify(true);\n@@ -2523,7 +2523,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryAssert.AreEqual(1, InitialInventoryItemJournalLine.Count(), 'test setup failed, should be only 1 line after a modify');\n \n // [GIVEN] Item tracking with original package number is assigned to the journal line\n- ReUsedLibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, '', '', InitialInspectionInventoryJnlItemJournalLine.Quantity);\n+ LibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, '', '', InitialInspectionInventoryJnlItemJournalLine.Quantity);\n ReservationEntry.Validate(\"Package No.\", OriginalPackageNo);\n ReservationEntry.Validate(\"New Package No.\", OriginalPackageNo);\n ReservationEntry.Modify();\n@@ -2638,7 +2638,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryUtility.CreateNoSeries(PackageNoSeries, true, true, false);\n LibraryUtility.CreateNoSeriesLine(PackageNoSeriesLine, PackageNoSeries.Code, PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '0'), PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '9'));\n \n- ReUsedLibraryItemTracking.CreateItemTrackingCode(PackageItemTrackingCode, false, false, true);\n+ LibraryItemTracking.CreateItemTrackingCode(PackageItemTrackingCode, false, false, true);\n InventorySetup.Get();\n InventorySetup.Validate(\"Package Nos.\", PackageNoSeries.Code);\n InventorySetup.Modify(true);\n@@ -2814,7 +2814,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryUtility.CreateNoSeriesLine(LotNoSeriesLine, LotNoSeries.Code, PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '0'), PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '9'));\n \n // [GIVEN] Item tracking code is created for lot tracking\n- ReUsedLibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n+ LibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n \n // [GIVEN] Item tracking code is configured to use expiration dates\n LotItemTrackingCode.\"Use Expiration Dates\" := true;\n@@ -2868,7 +2868,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryAssert.AreEqual(1, InitialInventoryItemJournalLine.Count(), 'test setup failed, should be only 1 line after a modify');\n \n // [GIVEN] Item tracking with lot number is assigned to the journal line\n- ReUsedLibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, '', OriginalLotNo, InitialInspectionInventoryJnlItemJournalLine.Quantity);\n+ LibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, '', OriginalLotNo, InitialInspectionInventoryJnlItemJournalLine.Quantity);\n \n // [GIVEN] Expiration date is set to work date for the reservation entry\n ReservationEntry.\"Expiration Date\" := WorkDate();\n@@ -3012,7 +3012,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryUtility.CreateNoSeries(LotNoSeries, true, true, false);\n LibraryUtility.CreateNoSeriesLine(LotNoSeriesLine, LotNoSeries.Code, PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '0'), PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '9'));\n \n- ReUsedLibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n+ LibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n LotItemTrackingCode.\"Use Expiration Dates\" := true;\n LotItemTrackingCode.Modify();\n \n@@ -3168,7 +3168,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryUtility.CreateNoSeriesLine(LotNoSeriesLine, LotNoSeries.Code, PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '0'), PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '9'));\n \n // [GIVEN] Lot-tracked item tracking code and item are created\n- ReUsedLibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n+ LibraryItemTracking.CreateItemTrackingCode(LotItemTrackingCode, false, true, false);\n LibraryInventory.CreateTrackedItem(Item, LotNoSeries.Code, '', LotItemTrackingCode.Code);\n \n // [GIVEN] A full WMS location with bins and bin content is created\n@@ -3373,7 +3373,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n ReclassWarehouseJournalLine.Modify();\n \n // [GIVEN] Warehouse item tracking line is created with lot and expiration information\n- ReUsedLibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n+ LibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n ReclassWarehouseJournalWhseItemTrackingLine.\"New Lot No.\" := ReclassWarehouseJournalWhseItemTrackingLine.\"Lot No.\";\n ReclassWarehouseJournalWhseItemTrackingLine.\"Expiration Date\" := ReservationEntry.\"Expiration Date\";\n ReclassWarehouseJournalWhseItemTrackingLine.\"New Expiration Date\" := ReservationEntry.\"Expiration Date\";\n@@ -3489,7 +3489,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryUtility.CreateNoSeries(PackageNoSeries, true, true, false);\n LibraryUtility.CreateNoSeriesLine(PackageNoSeriesLine, PackageNoSeries.Code, PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '0'), PadStr(Format(CurrentDateTime(), 0, 'A'), 19, '9'));\n \n- ReUsedLibraryItemTracking.CreateItemTrackingCode(PackageItemTrackingCode, false, false, true);\n+ LibraryItemTracking.CreateItemTrackingCode(PackageItemTrackingCode, false, false, true);\n InventorySetup.Get();\n InventorySetup.Validate(\"Package Nos.\", PackageNoSeries.Code);\n InventorySetup.Modify(true);\n@@ -3530,7 +3530,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n LibraryAssert.AreEqual(1, InitialInventoryItemJournalLine.Count(), 'test setup failed, should be only 1 line after a modify');\n \n // [GIVEN] Item tracking with original package number is assigned to the journal line\n- ReUsedLibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, '', '', InitialInspectionInventoryJnlItemJournalLine.Quantity);\n+ LibraryItemTracking.CreateItemJournalLineItemTracking(ReservationEntry, InitialInspectionInventoryJnlItemJournalLine, '', '', InitialInspectionInventoryJnlItemJournalLine.Quantity);\n ReservationEntry.Validate(\"Package No.\", OriginalPackageNo);\n ReservationEntry.Validate(\"New Package No.\", OriginalPackageNo);\n ReservationEntry.Modify();\n@@ -4304,7 +4304,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n ReclassWarehouseJournalLine.\"Lot No.\" := ReservationEntry.\"Lot No.\";\n ReclassWarehouseJournalLine.\"New Lot No.\" := ReclassWarehouseJournalLine.\"Lot No.\";\n ReclassWarehouseJournalLine.Modify();\n- ReUsedLibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n+ LibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n ReclassWarehouseJournalWhseItemTrackingLine.\"New Lot No.\" := ReclassWarehouseJournalWhseItemTrackingLine.\"Lot No.\";\n ReclassWarehouseJournalWhseItemTrackingLine.Modify();\n LibraryWarehouse.RegisterWhseJournalLine(ReclassWhseItemWarehouseJournalTemplate.Name, ReclassWarehouseJournalBatch.Name, Location.Code, true);\n@@ -4909,7 +4909,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n ReclassWarehouseJournalLine.\"Lot No.\" := ReservationEntry.\"Lot No.\";\n ReclassWarehouseJournalLine.\"New Lot No.\" := ReclassWarehouseJournalLine.\"Lot No.\";\n ReclassWarehouseJournalLine.Modify();\n- ReUsedLibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n+ LibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n ReclassWarehouseJournalWhseItemTrackingLine.\"New Lot No.\" := ReclassWarehouseJournalWhseItemTrackingLine.\"Lot No.\";\n ReclassWarehouseJournalWhseItemTrackingLine.Modify();\n LibraryWarehouse.RegisterWhseJournalLine(ReclassWhseItemWarehouseJournalTemplate.Name, ReclassWarehouseJournalBatch.Name, Location.Code, true);\n@@ -5521,7 +5521,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n ReclassItemJournalLine.\"New Bin Code\" := InitialChangeBin;\n ReclassItemJournalLine.Modify();\n \n- ReUsedLibraryItemTracking.CreateItemReclassJnLineItemTracking(ReclassReservationEntry, ReclassItemJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n+ LibraryItemTracking.CreateItemReclassJnLineItemTracking(ReclassReservationEntry, ReclassItemJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n ReclassReservationEntry.\"New Lot No.\" := ReclassReservationEntry.\"Lot No.\";\n ReclassReservationEntry.Modify();\n LibraryInventory.PostItemJournalBatch(ReclassItemJournalBatch);\n@@ -6043,7 +6043,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n ReclassWarehouseJournalLine.\"Lot No.\" := ReservationEntry.\"Lot No.\";\n ReclassWarehouseJournalLine.\"New Lot No.\" := ReclassWarehouseJournalLine.\"Lot No.\";\n ReclassWarehouseJournalLine.Modify();\n- ReUsedLibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n+ LibraryItemTracking.CreateWhseJournalLineItemTracking(ReclassWarehouseJournalWhseItemTrackingLine, ReclassWarehouseJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n ReclassWarehouseJournalWhseItemTrackingLine.\"New Lot No.\" := ReclassWarehouseJournalWhseItemTrackingLine.\"Lot No.\";\n ReclassWarehouseJournalWhseItemTrackingLine.Modify();\n LibraryWarehouse.RegisterWhseJournalLine(ReclassWhseItemWarehouseJournalTemplate.Name, ReclassWarehouseJournalBatch.Name, Location.Code, true);\n@@ -6316,7 +6316,7 @@ codeunit 139960 \"Qlty. Tests - Dispositions\"\n ReclassItemJournalLine.\"New Bin Code\" := InitialChangeBin;\n ReclassItemJournalLine.Modify();\n \n- ReUsedLibraryItemTracking.CreateItemReclassJnLineItemTracking(ReclassReservationEntry, ReclassItemJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n+ LibraryItemTracking.CreateItemReclassJnLineItemTracking(ReclassReservationEntry, ReclassItemJournalLine, '', ReservationEntry.\"Lot No.\", 50);\n ReclassReservationEntry.\"New Lot No.\" := ReclassReservationEntry.\"Lot No.\";\n ReclassReservationEntry.Modify();\n LibraryInventory.PostItemJournalBatch(ReclassItemJournalBatch);\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8524", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-06-08T21:42:31Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateLine.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateLine.Table.al\nindex d868fbf50a..e19e4d3dfb 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateLine.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateLine.Table.al\n@@ -48,6 +48,7 @@ table 20403 \"Qlty. Inspection Template Line\"\n if QltyTest.Get(\"Test Code\") then begin\n Rec.Description := QltyTest.Description;\n Rec.\"Unit of Measure Code\" := QltyTest.\"Unit of Measure Code\";\n+ Rec.\"Expression Formula\" := QltyTest.\"Expression Formula\";\n end;\n \n EnsureResultsExist(Rec.\"Test Code\" <> xRec.\"Test Code\");\n@@ -97,7 +98,7 @@ table 20403 \"Qlty. Inspection Template Line\"\n Rec.CalcFields(\"Test Value Type\");\n if Rec.\"Expression Formula\" <> '' then begin\n if not (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Text Expression\"]) then\n- Error(OnlyFieldExpressionErr);\n+ Error(ExpressionFormulaOnlyForTextExpressionErr);\n \n ValidateExpressionFormula();\n end;\n@@ -123,7 +124,7 @@ table 20403 \"Qlty. Inspection Template Line\"\n }\n \n var\n- OnlyFieldExpressionErr: Label 'The Expression Formula can only be used with fields that are a type of Expression';\n+ ExpressionFormulaOnlyForTextExpressionErr: Label 'The Expression Formula can only be used with tests that are a type of Text Expression';\n \n trigger OnInsert()\n begin\ndiff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateSubf.Page.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateSubf.Page.al\nindex 672e18ea4c..2ee3bad573 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateSubf.Page.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateSubf.Page.al\n@@ -65,6 +65,12 @@ page 20403 \"Qlty. Inspection Template Subf\"\n {\n StyleExpr = RowStyleText;\n }\n+ field(\"Expression Formula\"; Rec.\"Expression Formula\")\n+ {\n+ StyleExpr = RowStyleText;\n+ Editable = IsExpressionFormulaEditable;\n+ Visible = false;\n+ }\n field(\"Unit of Measure Code\"; Rec.\"Unit of Measure Code\")\n {\n StyleExpr = RowStyleText;\n@@ -503,6 +509,7 @@ page 20403 \"Qlty. Inspection Template Subf\"\n MatrixArrayCaptionSet: array[10] of Text;\n Visible1, Visible2, Visible3, Visible4, Visible5, Visible6, Visible7, Visible8, Visible9, Visible10 : Boolean;\n Editable1, Editable2, Editable3, Editable4, Editable5, Editable6, Editable7, Editable8, Editable9, Editable10 : Boolean;\n+ IsExpressionFormulaEditable: Boolean;\n DescriptionLbl: Label '%1 Description', Comment = '%1 = Matrix field caption';\n ConditionLbl: Label '%1 Condition', Comment = '%1 = Matrix field caption';\n \n@@ -573,6 +580,8 @@ page 20403 \"Qlty. Inspection Template Subf\"\n Editable8 := Visible8 and not RowIsLabel;\n Editable9 := Visible9 and not RowIsLabel;\n Editable10 := Visible10 and not RowIsLabel;\n+\n+ IsExpressionFormulaEditable := Rec.\"Test Value Type\" = Rec.\"Test Value Type\"::\"Value Type Text Expression\";\n end;\n \n local procedure UpdateMatrixDataCondition(Matrix: Integer)\ndiff --git a/src/Apps/W1/Quality Management/app/src/Document/QltyInspection.Page.al b/src/Apps/W1/Quality Management/app/src/Document/QltyInspection.Page.al\nindex f4f87e34e2..d309c3ac76 100644\n--- a/src/Apps/W1/Quality Management/app/src/Document/QltyInspection.Page.al\n+++ b/src/Apps/W1/Quality Management/app/src/Document/QltyInspection.Page.al\n@@ -27,6 +27,8 @@ page 20406 \"Qlty. Inspection\"\n {\n UsageCategory = None;\n Caption = 'Quality Inspection';\n+ AboutTitle = 'About Quality Inspection document';\n+ AboutText = 'The Quality Inspection document is used to manage quality inspections for items, including recording inspection results, taking pictures, and navigating to related documents. The header contains general information about the inspection, while the lines contain details about each quality test performed. You can also create re-inspections, print reports, and perform actions like moving inventory or changing item tracking information based on the inspection results.';\n DataCaptionExpression = GetDataCaptionExpression();\n InsertAllowed = false;\n PageType = Card;\ndiff --git a/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionLine.Table.al b/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionLine.Table.al\nindex 819ca649ca..4b86c3e549 100644\n--- a/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionLine.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionLine.Table.al\n@@ -409,6 +409,8 @@ table 20406 \"Qlty. Inspection Line\"\n if not GetInspection() then\n exit;\n \n+ EvaluateSelfIfOnlyLineIsTextExpression();\n+\n OthersInSameQltyInspectionLine.SetRange(\"Inspection No.\", Rec.\"Inspection No.\");\n OthersInSameQltyInspectionLine.SetRange(\"Re-inspection No.\", Rec.\"Re-inspection No.\");\n OthersInSameQltyInspectionLine.SetFilter(\"Test Value Type\", '%1', QltyInspectionTemplateLine.\"Test Value Type\"::\"Value Type Text Expression\");\n@@ -465,6 +467,21 @@ table 20406 \"Qlty. Inspection Line\"\n until OthersInSameQltyInspectionLine.Next() = 0;\n end;\n \n+ local procedure EvaluateSelfIfOnlyLineIsTextExpression()\n+ var\n+ OtherQltyInspectionLine: Record \"Qlty. Inspection Line\";\n+ begin\n+ Rec.CalcFields(\"Test Value Type\");\n+ if Rec.\"Test Value Type\" <> Rec.\"Test Value Type\"::\"Value Type Text Expression\" then\n+ exit;\n+\n+ OtherQltyInspectionLine.SetRange(\"Inspection No.\", Rec.\"Inspection No.\");\n+ OtherQltyInspectionLine.SetRange(\"Re-inspection No.\", Rec.\"Re-inspection No.\");\n+ OtherQltyInspectionLine.SetFilter(\"Line No.\", '<>%1', Rec.\"Line No.\");\n+ if OtherQltyInspectionLine.IsEmpty() then\n+ Rec.EvaluateTextExpression(QltyInspectionHeader);\n+ end;\n+\n internal procedure EvaluateTextExpression(var EvaluateAgainstQltyInspectionHeader: Record \"Qlty. Inspection Header\")\n var\n QltyExpressionMgmt: Codeunit \"Qlty. Expression Mgmt.\";\ndiff --git a/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionSubform.Page.al b/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionSubform.Page.al\nindex 844802977b..01dc04810b 100644\n--- a/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionSubform.Page.al\n+++ b/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionSubform.Page.al\n@@ -59,7 +59,7 @@ page 20407 \"Qlty. Inspection Subform\"\n trigger OnAssistEdit()\n begin\n Rec.CalcFields(\"Test Value Type\");\n- if Rec.\"Test Value Type\" = Rec.\"Test Value Type\"::\"Value Type Label\" then\n+ if Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Label\", Rec.\"Test Value Type\"::\"Value Type Text Expression\"] then\n exit;\n UpdateRowData();\n \n@@ -371,10 +371,10 @@ page 20407 \"Qlty. Inspection Subform\"\n begin\n OnBeforeCanEditTestValue(Rec, Result, IsHandled);\n if IsHandled then\n- exit;\n+ exit(Result);\n \n Rec.CalcFields(\"Test Value Type\");\n- exit(not (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Label\"]));\n+ exit(not (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Label\", Rec.\"Test Value Type\"::\"Value Type Text Expression\"]));\n end;\n \n /// \ndiff --git a/src/Apps/W1/Quality Management/app/src/Reports/QltyCertificateOfAnalysis.docx b/src/Apps/W1/Quality Management/app/src/Reports/QltyCertificateOfAnalysis.docx\nindex 9202b267d8..db577ad259 100644\nBinary files a/src/Apps/W1/Quality Management/app/src/Reports/QltyCertificateOfAnalysis.docx and b/src/Apps/W1/Quality Management/app/src/Reports/QltyCertificateOfAnalysis.docx differ\ndiff --git a/src/Apps/W1/Quality Management/app/src/Reports/QltyGeneralPurposeInspection.docx b/src/Apps/W1/Quality Management/app/src/Reports/QltyGeneralPurposeInspection.docx\nindex c71945827a..694a6d6621 100644\nBinary files a/src/Apps/W1/Quality Management/app/src/Reports/QltyGeneralPurposeInspection.docx and b/src/Apps/W1/Quality Management/app/src/Reports/QltyGeneralPurposeInspection.docx differ\ndiff --git a/src/Apps/W1/Quality Management/app/src/Reports/QltyNonConformance.docx b/src/Apps/W1/Quality Management/app/src/Reports/QltyNonConformance.docx\nindex c1465f0f1c..abf5c06f36 100644\nBinary files a/src/Apps/W1/Quality Management/app/src/Reports/QltyNonConformance.docx and b/src/Apps/W1/Quality Management/app/src/Reports/QltyNonConformance.docx differ\ndiff --git a/src/Apps/W1/Quality Management/app/src/Setup/QltyManagementSetup.Table.al b/src/Apps/W1/Quality Management/app/src/Setup/QltyManagementSetup.Table.al\nindex 4e8cecbbef..492e58410e 100644\n--- a/src/Apps/W1/Quality Management/app/src/Setup/QltyManagementSetup.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Setup/QltyManagementSetup.Table.al\n@@ -43,7 +43,7 @@ table 20400 \"Qlty. Management Setup\"\n field(4; \"Inspection Creation Option\"; Enum \"Qlty. Inspect. Creation Option\")\n {\n Caption = 'Inspection Creation Option';\n- ToolTip = 'Specifies how the system handles inspection creation when existing inspections exist.';\n+ ToolTip = 'Specifies handling of inspection creation when existing inspections are found.';\n InitValue = \"Use existing open inspection if available\";\n }\n field(5; \"Inspection Search Criteria\"; Enum \"Qlty. Inspect. Search Criteria\")\ndiff --git a/src/Apps/W1/Quality Management/app/src/Setup/SetupGuide/QltyGuidedExperience.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Setup/SetupGuide/QltyGuidedExperience.Codeunit.al\nindex 9395d22992..f0e5f37d38 100644\n--- a/src/Apps/W1/Quality Management/app/src/Setup/SetupGuide/QltyGuidedExperience.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Setup/SetupGuide/QltyGuidedExperience.Codeunit.al\n@@ -28,13 +28,13 @@ codeunit 20419 \"Qlty. Guided Experience\"\n DemoDataDescriptionTxt: Label 'Install or explore Contoso demo data for Quality Management with sample quality tests, templates, generation rules, and inspections. This lets you learn how quality checks work without setting up your own data.';\n QualityResultsShortTitleTxt: Label 'Inspection results';\n QualityResultsTitleTxt: Label 'Set up quality inspection results';\n- QualityResultsDescriptionTxt: Label 'Define possible outcomes for quality inspections, like Pass, Fail, or In Progress. Create custom results and set priorities to match your organization''s standards. These results control how inspections are evaluated and how items are blocked or released.';\n+ QualityResultsDescriptionTxt: Label 'Define custom grades for quality inspections, to match your organization''s standards. You can decide evaluation priorities and set conditions for allowed transactions.';\n QualityTestsShortTitleTxt: Label 'Quality tests';\n QualityTestsTitleTxt: Label 'Understand quality tests';\n QualityTestsDescriptionTxt: Label 'Quality tests define what is measured. Visit the Quality Tests list to see available tests, then open a test card to review parameters, limits, and expected values used during inspections.';\n QualityTemplatesShortTitleTxt: Label 'Quality templates';\n QualityTemplatesTitleTxt: Label 'Reuse inspection templates';\n- QualityTemplatesDescriptionTxt: Label 'With templates you can group and reuse quality tests so you can apply consistent inspection standards across items, processes, or scenarios. From the list you can create a new template card to understand its structure and purpose.';\n+ QualityTemplatesDescriptionTxt: Label 'With templates you can group and reuse quality tests to ensure consistent inspection standards. Try creating a new template card to understand its structure and purpose.';\n GenerationRulesShortTitleTxt: Label 'Generation rules';\n GenerationRulesTitleTxt: Label 'Set up inspection generation rules';\n GenerationRulesDescriptionTxt: Label 'Inspection generation rules define when quality inspections are created automatically, such as during receiving, production, or assembly.';\n", "FAIL_TO_PASS": [{"codeunitID": 139965, "functionName": ["TemplateLine_ExpressionFormulaUpdatedWhenTestCodeChanges", "TemplateLine_ExpressionFormulaEmptyWhenTestHasNoFormula", "TemplateLine_ExpressionFormulaCopiedFromTest", "TestTable_DefaultValueNotAllowedForTextExpression"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\nindex 38a8889c60..6df2e749cc 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n@@ -154,13 +154,16 @@ table 20401 \"Qlty. Test\"\n \n trigger OnValidate()\n begin\n+ if (Rec.\"Default Value\" <> '') and (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Text Expression\"]) then\n+ Error(DefaultValueNotAllowedForTextExpressionErr);\n+\n Rec.ValidateAllowableValuesOnDefault();\n end;\n }\n field(17; \"Case Sensitive\"; Enum \"Qlty. Case Sensitivity\")\n {\n Caption = 'Case Sensitivity';\n- ToolTip = 'Specifies if case sensitivity will be enabled for text-based fields.';\n+ ToolTip = 'Specifies if case sensitivity will be enabled for text-based tests.';\n }\n field(18; \"Expression Formula\"; Text[500])\n {\n@@ -170,7 +173,7 @@ table 20401 \"Qlty. Test\"\n trigger OnValidate()\n begin\n if (Rec.\"Expression Formula\" <> '') and not (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Text Expression\"]) then\n- Error(OnlyFieldExpressionErr);\n+ Error(ExpressionFormulaOnlyForTextExpressionErr);\n end;\n }\n field(22; \"Unit of Measure Code\"; Code[10])\n@@ -204,7 +207,8 @@ table 20401 \"Qlty. Test\"\n GenericTestTok: Label 'MYTEST', Locked = true;\n ThereIsNoResultErr: Label 'There is no result called \"%1\". Please add the result, or change the existing result conditions.', Comment = '%1=the result';\n ReviewResultsErr: Label 'Advanced configuration required. Please review the result configurations for test \"%1\", for result \"%2\".', Comment = '%1=the test, %2=the result';\n- OnlyFieldExpressionErr: Label 'The Expression Formula can only be used with fields that are a type of Expression';\n+ ExpressionFormulaOnlyForTextExpressionErr: Label 'The Expression Formula can only be used with tests that are a type of Text Expression';\n+ DefaultValueNotAllowedForTextExpressionErr: Label 'The Default Value cannot be set on tests that are a type of Text Expression. The value is computed from the Expression Formula.';\n BooleanChoiceListLbl: Label 'No,Yes';\n ExistingInspectionErr: Label 'The test %1 exists on %2 inspections (such as %3 with template %4). The test cannot be deleted if it is being used on a quality inspection.', Comment = '%1=the test, %2=count of inspections, %3=one example inspection, %4=example template.';\n DeleteQst: Label 'The test %3 exists on %1 Quality Inspection Template(s) (such as template %2) that will be deleted. Do you wish to proceed?', Comment = '%1 = the lines, %2= the Template Code, %3=the test';\n@@ -601,7 +605,7 @@ table 20401 \"Qlty. Test\"\n Expression: Text;\n begin\n if not (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Text Expression\"]) then\n- Error(OnlyFieldExpressionErr);\n+ Error(ExpressionFormulaOnlyForTextExpressionErr);\n \n Expression := Rec.\"Expression Formula\";\n \ndiff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTestCard.Page.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTestCard.Page.al\nindex 95c568a137..4418f7a53c 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTestCard.Page.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTestCard.Page.al\n@@ -77,6 +77,8 @@ page 20479 \"Qlty. Test Card\"\n }\n field(\"Default Value\"; Rec.\"Default Value\")\n {\n+ Editable = not IsExpressionFormulaEditable;\n+\n trigger OnAssistEdit()\n begin\n Rec.AssistEditDefaultValue();\n@@ -652,7 +654,7 @@ page 20479 \"Qlty. Test Card\"\n \n EditableResult := (Rec.Code <> '') and (CurrPage.Editable) and (Visible1) and (MatrixArrayCaptionSet[1] <> '');\n \n- IsExpressionFormulaEditable := (Rec.\"Test Value Type\" = Rec.\"Test Value Type\"::\"Value Type Text Expression\");\n+ IsExpressionFormulaEditable := Rec.\"Test Value Type\" = Rec.\"Test Value Type\"::\"Value Type Text Expression\";\n end;\n \n local procedure UpdateMatrixDataCondition(Matrix: Integer)\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsMoreTests.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsMoreTests.Codeunit.al\nindex 70e318c1ef..69d0029499 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsMoreTests.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsMoreTests.Codeunit.al\n@@ -61,7 +61,7 @@ codeunit 139965 \"Qlty. Tests - More Tests\"\n DefaultScheduleGroupTok: Label 'QM', Locked = true;\n ExpressionFormulaTok: Label '[No.]';\n TestValueTypeChangeErrInfoMsg: Label 'Consider replacing this test in the template with a new one, or deleting existing inspections (if allowed). The test was last used on Inspection %1, Re-inspection %2.', Comment = '%1 = Quality Inspection No., %2 = Re-inspection No.';\n- OnlyFieldExpressionErr: Label 'The Expression Formula can only be used with fields that are a type of Expression';\n+ ExpressionFormulaOnlyForTextExpressionErr: Label 'The Expression Formula can only be used with tests that are a type of Text Expression';\n VendorFilterCountryTok: Label 'WHERE(Country/Region Code=FILTER(CA))', Locked = true;\n VendorFilterNoTok: Label 'WHERE(No.=FILTER(%1))', Comment = '%1 = Vendor No.', Locked = true;\n ThereIsNoResultErr: Label 'There is no result called \"%1\". Please add the result, or change the existing result conditions.', Comment = '%1=the result';\n@@ -105,7 +105,7 @@ codeunit 139965 \"Qlty. Tests - More Tests\"\n asserterror ToLoadQltyTest.Validate(\"Expression Formula\", ExpressionFormulaTok);\n \n // [THEN] An error is raised indicating Expression Formula is only for Expression test value types\n- LibraryAssert.ExpectedError(OnlyFieldExpressionErr);\n+ LibraryAssert.ExpectedError(ExpressionFormulaOnlyForTextExpressionErr);\n end;\n \n [Test]\n@@ -612,7 +612,7 @@ codeunit 139965 \"Qlty. Tests - More Tests\"\n asserterror ConfigurationToLoadQltyInspectionTemplateLine.Validate(\"Expression Formula\", ExpressionFormulaTok);\n \n // [THEN] An error is raised indicating Expression Formula is only for Expression field types\n- LibraryAssert.ExpectedError(OnlyFieldExpressionErr);\n+ LibraryAssert.ExpectedError(ExpressionFormulaOnlyForTextExpressionErr);\n end;\n \n [Test]\n@@ -2271,6 +2271,139 @@ codeunit 139965 \"Qlty. Tests - More Tests\"\n LibraryAssert.AreEqual(LotNo, QltyInspectionHeader.\"Source Lot No.\", 'Inspection should have the correct lot number.');\n end;\n \n+ [Test]\n+ procedure TestTable_DefaultValueNotAllowedForTextExpression()\n+ var\n+ QltyTest: Record \"Qlty. Test\";\n+ TestCode: Text;\n+ begin\n+ // [SCENARIO] Default Value cannot be set on tests that are a type of Text Expression\n+ Initialize();\n+\n+ // [GIVEN] A random test code is generated\n+ QltyInspectionUtility.GenerateRandomCharacters(20, TestCode);\n+\n+ // [GIVEN] A new quality test with Test Value Type \"Value Type Text Expression\" is created\n+ QltyTest.Validate(Code, CopyStr(TestCode, 1, MaxStrLen(QltyTest.Code)));\n+ QltyTest.Validate(Description, LibraryUtility.GenerateRandomText(MaxStrLen(QltyTest.Description)));\n+ QltyTest.Validate(\"Test Value Type\", QltyTest.\"Test Value Type\"::\"Value Type Text Expression\");\n+ QltyTest.Insert();\n+\n+ // [WHEN] Attempting to set Default Value on a Text Expression test\n+ asserterror QltyTest.Validate(\"Default Value\", 'some text');\n+\n+ // [THEN] An error is raised indicating Default Value is not allowed for Text Expression tests\n+ LibraryAssert.ExpectedError('The Default Value cannot be set on tests that are a type of Text Expression.');\n+ end;\n+\n+ [Test]\n+ procedure TemplateLine_ExpressionFormulaCopiedFromTest()\n+ var\n+ QltyTest: Record \"Qlty. Test\";\n+ QltyInspectionTemplateHdr: Record \"Qlty. Inspection Template Hdr.\";\n+ QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\";\n+ TestCode: Text;\n+ begin\n+ // [SCENARIO] Expression Formula is copied from the test to the template line when the test is added\n+ Initialize();\n+\n+ // [GIVEN] A random test code is generated\n+ QltyInspectionUtility.GenerateRandomCharacters(20, TestCode);\n+\n+ // [GIVEN] A quality test with Test Value Type \"Value Type Text Expression\" and an Expression Formula is created\n+ QltyTest.Validate(Code, CopyStr(TestCode, 1, MaxStrLen(QltyTest.Code)));\n+ QltyTest.Validate(Description, LibraryUtility.GenerateRandomText(MaxStrLen(QltyTest.Description)));\n+ QltyTest.Validate(\"Test Value Type\", QltyTest.\"Test Value Type\"::\"Value Type Text Expression\");\n+ QltyTest.Insert();\n+ QltyTest.Validate(\"Expression Formula\", ExpressionFormulaTok);\n+ QltyTest.Modify();\n+\n+ // [GIVEN] A template is created\n+ QltyInspectionUtility.CreateTemplate(QltyInspectionTemplateHdr, 0);\n+\n+ // [WHEN] A template line is created with the test code\n+ QltyInspectionTemplateLine.Init();\n+ QltyInspectionTemplateLine.\"Template Code\" := QltyInspectionTemplateHdr.Code;\n+ QltyInspectionTemplateLine.InitLineNoIfNeeded();\n+ QltyInspectionTemplateLine.Validate(\"Test Code\", QltyTest.Code);\n+ QltyInspectionTemplateLine.Insert(true);\n+\n+ // [THEN] The Expression Formula is copied from the test to the template line\n+ LibraryAssert.AreEqual(ExpressionFormulaTok, QltyInspectionTemplateLine.\"Expression Formula\", 'Expression Formula should be copied from the test to the template line.');\n+ end;\n+\n+ [Test]\n+ procedure TemplateLine_ExpressionFormulaEmptyWhenTestHasNoFormula()\n+ var\n+ QltyTest: Record \"Qlty. Test\";\n+ QltyInspectionTemplateHdr: Record \"Qlty. Inspection Template Hdr.\";\n+ QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\";\n+ TestCode: Text;\n+ begin\n+ // [SCENARIO] Expression Formula on template line is empty when the test has no formula\n+ Initialize();\n+\n+ // [GIVEN] A random test code is generated\n+ QltyInspectionUtility.GenerateRandomCharacters(20, TestCode);\n+\n+ // [GIVEN] A quality test with Test Value Type \"Value Type Text Expression\" but no Expression Formula is created\n+ QltyTest.Validate(Code, CopyStr(TestCode, 1, MaxStrLen(QltyTest.Code)));\n+ QltyTest.Validate(Description, LibraryUtility.GenerateRandomText(MaxStrLen(QltyTest.Description)));\n+ QltyTest.Validate(\"Test Value Type\", QltyTest.\"Test Value Type\"::\"Value Type Text Expression\");\n+ QltyTest.Insert();\n+\n+ // [GIVEN] A template is created\n+ QltyInspectionUtility.CreateTemplate(QltyInspectionTemplateHdr, 0);\n+\n+ // [WHEN] A template line is created with the test code\n+ QltyInspectionTemplateLine.Init();\n+ QltyInspectionTemplateLine.\"Template Code\" := QltyInspectionTemplateHdr.Code;\n+ QltyInspectionTemplateLine.InitLineNoIfNeeded();\n+ QltyInspectionTemplateLine.Validate(\"Test Code\", QltyTest.Code);\n+ QltyInspectionTemplateLine.Insert(true);\n+\n+ // [THEN] The Expression Formula on the template line is empty\n+ LibraryAssert.AreEqual('', QltyInspectionTemplateLine.\"Expression Formula\", 'Expression Formula should be empty when the test has no formula.');\n+ end;\n+\n+ [Test]\n+ procedure TemplateLine_ExpressionFormulaUpdatedWhenTestCodeChanges()\n+ var\n+ QltyTest1: Record \"Qlty. Test\";\n+ QltyTest2: Record \"Qlty. Test\";\n+ QltyInspectionTemplateHdr: Record \"Qlty. Inspection Template Hdr.\";\n+ QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\";\n+ ExpressionFormula2Tok: Label '[Source Item No.]', Locked = true;\n+ begin\n+ // [SCENARIO] Expression Formula is updated when the Test Code on a template line is changed to a different test\n+ Initialize();\n+\n+ // [GIVEN] A first quality test with an Expression Formula is created\n+ QltyInspectionUtility.CreateTest(QltyTest1, QltyTest1.\"Test Value Type\"::\"Value Type Text Expression\");\n+ QltyTest1.Validate(\"Expression Formula\", ExpressionFormulaTok);\n+ QltyTest1.Modify();\n+\n+ // [GIVEN] A second quality test with a different Expression Formula is created\n+ QltyInspectionUtility.CreateTest(QltyTest2, QltyTest2.\"Test Value Type\"::\"Value Type Text Expression\");\n+ QltyTest2.Validate(\"Expression Formula\", ExpressionFormula2Tok);\n+ QltyTest2.Modify();\n+\n+ // [GIVEN] A template is created with the first test\n+ QltyInspectionUtility.CreateTemplate(QltyInspectionTemplateHdr, 0);\n+ QltyInspectionTemplateLine.Init();\n+ QltyInspectionTemplateLine.\"Template Code\" := QltyInspectionTemplateHdr.Code;\n+ QltyInspectionTemplateLine.InitLineNoIfNeeded();\n+ QltyInspectionTemplateLine.Validate(\"Test Code\", QltyTest1.Code);\n+ QltyInspectionTemplateLine.Insert(true);\n+\n+ // [WHEN] The Test Code on the template line is changed to the second test\n+ QltyInspectionTemplateLine.Validate(\"Test Code\", QltyTest2.Code);\n+ QltyInspectionTemplateLine.Modify(true);\n+\n+ // [THEN] The Expression Formula is updated to the second test's formula\n+ LibraryAssert.AreEqual(ExpressionFormula2Tok, QltyInspectionTemplateLine.\"Expression Formula\", 'Expression Formula should be updated when the test code is changed.');\n+ end;\n+\n local procedure Initialize()\n begin\n if IsInitialized then\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8423", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-06-02T14:24:52Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\ExcelReports\\App", "src\\Apps\\W1\\ExcelReports\\Test"], "patch": "diff --git a/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccPayableExcel.Report.al b/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccPayableExcel.Report.al\nindex a09b3759b3..7dc8662512 100644\n--- a/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccPayableExcel.Report.al\n+++ b/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccPayableExcel.Report.al\n@@ -84,8 +84,9 @@ report 4403 \"EXR Aged Acc Payable Excel\"\n {\n IncludeCaption = true;\n }\n- column(CurrencyCode; CurrencyCodeDisplayCode)\n+ column(CurrencyCode; \"Currency Code\")\n {\n+ IncludeCaption = true;\n }\n column(PostingDate; \"Posting Date\")\n {\n@@ -126,11 +127,7 @@ report 4403 \"EXR Aged Acc Payable Excel\"\n Clear(AgingData);\n AgingData.DeleteAll();\n InsertAgingData(VendorAgingData);\n-\n- if AgingData.\"Currency Code\" = '' then\n- CurrencyCodeDisplayCode := GeneralLedgerSetup.GetCurrencyCode('')\n- else\n- CurrencyCodeDisplayCode := AgingData.\"Currency Code\";\n+ CurrencyCodeDisplayCode := AgingData.\"Currency Code\";\n end;\n }\n \n@@ -271,7 +268,6 @@ report 4403 \"EXR Aged Acc Payable Excel\"\n DueByCurrencies = 'Due by Currencies', MaxLength = 31, Comment = 'Excel worksheet name.';\n OpenByFCY = 'Open by (FCY)';\n DataRetrieved = 'Data retrieved:';\n- CurrencyCodeDisplay = 'Currency Code';\n AgedAsOf = 'Aged as of:';\n AgedAccountsPayable = 'Aged Accounts Payable';\n AgedAccountsPayablePrint = 'Aged Accounts Payable (Print)', MaxLength = 31, Comment = 'Excel worksheet name.';\n@@ -322,6 +318,9 @@ report 4403 \"EXR Aged Acc Payable Excel\"\n if PeriodCount = 0 then\n PeriodCount := 5;\n \n+ if not GeneralLedgerSetup.Get() then\n+ Clear(GeneralLedgerSetup);\n+\n WorkingEndDate := EndingDate;\n WorkingStartDate := CalcDate(PeriodLength, WorkingEndDate);\n repeat\n@@ -366,7 +365,10 @@ report 4403 \"EXR Aged Acc Payable Excel\"\n AgingData.\"Document Type\" := VendorLedgerEntry.\"Document Type\";\n AgingData.\"Dimension 1 Code\" := VendorLedgerEntry.\"Global Dimension 1 Code\";\n AgingData.\"Dimension 2 Code\" := VendorLedgerEntry.\"Global Dimension 2 Code\";\n- AgingData.\"Currency Code\" := VendorLedgerEntry.\"Currency Code\";\n+ if VendorLedgerEntry.\"Currency Code\" = '' then\n+ AgingData.\"Currency Code\" := GeneralLedgerSetup.GetCurrencyCode('')\n+ else\n+ AgingData.\"Currency Code\" := VendorLedgerEntry.\"Currency Code\";\n AgingData.\"Posting Date\" := VendorLedgerEntry.\"Posting Date\";\n AgingData.\"Document Date\" := VendorLedgerEntry.\"Document Date\";\n AgingData.\"Due Date\" := VendorLedgerEntry.\"Due Date\";\ndiff --git a/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccountsRecExcel.Report.al b/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccountsRecExcel.Report.al\nindex b16e1ca692..e07ca9a845 100644\n--- a/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccountsRecExcel.Report.al\n+++ b/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccountsRecExcel.Report.al\n@@ -83,8 +83,9 @@ report 4402 \"EXR Aged Accounts Rec Excel\"\n {\n IncludeCaption = true;\n }\n- column(CurrencyCode; CurrencyCodeDisplayCode)\n+ column(CurrencyCode; \"Currency Code\")\n {\n+ IncludeCaption = true;\n }\n column(PostingDate; \"Posting Date\")\n {\n@@ -125,11 +126,7 @@ report 4402 \"EXR Aged Accounts Rec Excel\"\n Clear(AgingData);\n AgingData.DeleteAll();\n InsertAgingData(CustomerAgingData);\n-\n- if AgingData.\"Currency Code\" = '' then\n- CurrencyCodeDisplayCode := GeneralLedgerSetup.GetCurrencyCode('')\n- else\n- CurrencyCodeDisplayCode := AgingData.\"Currency Code\";\n+ CurrencyCodeDisplayCode := AgingData.\"Currency Code\";\n end;\n }\n \n@@ -270,7 +267,6 @@ report 4402 \"EXR Aged Accounts Rec Excel\"\n DueByCurrencies = 'Due by Currencies', MaxLength = 31, Comment = 'Excel worksheet name.';\n OpenByFCY = 'Open by (FCY)';\n DataRetrieved = 'Data retrieved:';\n- CurrencyCodeDisplay = 'Currency Code';\n AgedAsOf = 'Aged as of:';\n AgedAccountsReceivable = 'Aged Accounts Receivable';\n AgedAccountsReceivablePrint = 'Aged Accounts Rec. (Print)', MaxLength = 31, Comment = 'Excel worksheet name.';\n@@ -321,6 +317,9 @@ report 4402 \"EXR Aged Accounts Rec Excel\"\n if PeriodCount = 0 then\n PeriodCount := 5;\n \n+ if not GeneralLedgerSetup.Get() then\n+ Clear(GeneralLedgerSetup);\n+\n WorkingEndDate := EndingDate;\n WorkingStartDate := CalcDate(PeriodLength, WorkingEndDate);\n repeat\n@@ -365,7 +364,10 @@ report 4402 \"EXR Aged Accounts Rec Excel\"\n AgingData.\"Document Type\" := CustLedgerEntry.\"Document Type\";\n AgingData.\"Dimension 1 Code\" := CustLedgerEntry.\"Global Dimension 1 Code\";\n AgingData.\"Dimension 2 Code\" := CustLedgerEntry.\"Global Dimension 2 Code\";\n- AgingData.\"Currency Code\" := CustLedgerEntry.\"Currency Code\";\n+ if CustLedgerEntry.\"Currency Code\" = '' then\n+ AgingData.\"Currency Code\" := GeneralLedgerSetup.GetCurrencyCode('')\n+ else\n+ AgingData.\"Currency Code\" := CustLedgerEntry.\"Currency Code\";\n AgingData.\"Posting Date\" := CustLedgerEntry.\"Posting Date\";\n AgingData.\"Document Date\" := CustLedgerEntry.\"Document Date\";\n AgingData.\"Due Date\" := CustLedgerEntry.\"Due Date\";\n", "FAIL_TO_PASS": [{"codeunitID": 139555, "functionName": ["AgedAccountsPayableReportAgesByPostingDate", "AgedAccountsPayableRendersCurrencyCodePerEntry", "AgedAccountsPayableExportsDocumentTypeAndNo", "AgedAccountsRecExportsDocumentTypeAndNo", "AgedAccountsRecRendersCurrencyCodePerEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/ExcelReports/Test/app.json b/src/Apps/W1/ExcelReports/Test/app.json\nindex 826a16204e..b08abb1f27 100644\n--- a/src/Apps/W1/ExcelReports/Test/app.json\n+++ b/src/Apps/W1/ExcelReports/Test/app.json\n@@ -38,6 +38,10 @@\n {\n \"from\": 139543,\n \"to\": 139547\n+ },\n+ {\n+ \"from\": 139555,\n+ \"to\": 139555\n }\n ],\n \"resourceExposurePolicy\": {\ndiff --git a/src/Apps/W1/ExcelReports/Test/src/AgedAccountsExcelReports.Codeunit.al b/src/Apps/W1/ExcelReports/Test/src/AgedAccountsExcelReports.Codeunit.al\nnew file mode 100644\nindex 0000000000..6442d2d2a8\n--- /dev/null\n+++ b/src/Apps/W1/ExcelReports/Test/src/AgedAccountsExcelReports.Codeunit.al\n@@ -0,0 +1,391 @@\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+\n+namespace Microsoft.Finance.ExcelReports.Test;\n+\n+using Microsoft.Finance.ExcelReports;\n+using Microsoft.Finance.GeneralLedger.Journal;\n+using Microsoft.Finance.GeneralLedger.Setup;\n+using Microsoft.Purchases.Payables;\n+using Microsoft.Purchases.Vendor;\n+using Microsoft.Sales.Customer;\n+using Microsoft.Sales.Receivables;\n+\n+codeunit 139555 \"Aged Accounts Excel Reports\"\n+{\n+ Subtype = Test;\n+ RequiredTestIsolation = Disabled;\n+ TestPermissions = Disabled;\n+\n+ var\n+ LibraryRandom: Codeunit \"Library - Random\";\n+ LibraryReportDataset: Codeunit \"Library - Report Dataset\";\n+ Assert: Codeunit Assert;\n+ DocumentTypeShouldBeInvoiceErr: Label 'Document Type should be Invoice';\n+ DocumentNoShouldMatchErr: Label 'Document No should match the ledger entry';\n+\n+ [Test]\n+ [HandlerFunctions('EXRAgedAccPayableExcelHandler')]\n+ procedure AgedAccountsPayableExportsDocumentTypeAndNo()\n+ var\n+ Vendor: Record Vendor;\n+ VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ Variant: Variant;\n+ RequestPageXml: Text;\n+ ReportDocumentType: Text;\n+ ReportDocumentNo: Text;\n+ begin\n+ // [FEATURE] [AI test]\n+ // [SCENARIO 622247] Aged Accounts Payable Excel report exports Document Type and Document No fields correctly for Invoice entries\n+ InitializeAgingData();\n+\n+ // [GIVEN] Vendor \"V\" with an open vendor ledger entry of type Invoice\n+ // Create vendor directly to avoid VAT posting setup requirements in some localizations\n+ CreateMinimalVendor(Vendor);\n+ CreateVendorLedgerEntry(VendorLedgerEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n+ Commit();\n+\n+ // [WHEN] Running the Aged Accounts Payable Excel report\n+ RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Acc Payable Excel\", RequestPageXml);\n+ LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Acc Payable Excel\", Variant, RequestPageXml);\n+\n+ // [THEN] The exported data contains the Document Type \"Invoice\" and the correct Document No\n+ LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n+ Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n+ LibraryReportDataset.GetNextRow();\n+ LibraryReportDataset.FindCurrentRowValue('DocumentType', Variant);\n+ ReportDocumentType := Variant;\n+ Assert.AreEqual(Format(\"Gen. Journal Document Type\"::Invoice), ReportDocumentType, DocumentTypeShouldBeInvoiceErr);\n+ LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n+ ReportDocumentNo := Variant;\n+ Assert.AreEqual(VendorLedgerEntry.\"Document No.\", ReportDocumentNo, DocumentNoShouldMatchErr);\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('EXRAgedAccountsRecExcelHandler')]\n+ procedure AgedAccountsRecExportsDocumentTypeAndNo()\n+ var\n+ Customer: Record Customer;\n+ CustLedgerEntry: Record \"Cust. Ledger Entry\";\n+ Variant: Variant;\n+ RequestPageXml: Text;\n+ ReportDocumentType: Text;\n+ ReportDocumentNo: Text;\n+ begin\n+ // [FEATURE] [AI test]\n+ // [SCENARIO 622247] Aged Accounts Receivable Excel report exports Document Type and Document No fields correctly for Invoice entries\n+ InitializeAgingData();\n+\n+ // [GIVEN] Customer \"C\" with an open customer ledger entry of type Invoice\n+ // Create customer directly to avoid VAT posting setup requirements in some localizations\n+ CreateMinimalCustomer(Customer);\n+ CreateCustLedgerEntry(CustLedgerEntry, Customer.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n+ Commit();\n+\n+ // [WHEN] Running the Aged Accounts Receivable Excel report\n+ RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Accounts Rec Excel\", RequestPageXml);\n+ LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Accounts Rec Excel\", Variant, RequestPageXml);\n+\n+ // [THEN] The exported data contains the Document Type \"Invoice\" and the correct Document No\n+ LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n+ Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n+ LibraryReportDataset.GetNextRow();\n+ LibraryReportDataset.FindCurrentRowValue('DocumentType', Variant);\n+ ReportDocumentType := Variant;\n+ Assert.AreEqual(Format(\"Gen. Journal Document Type\"::Invoice), ReportDocumentType, DocumentTypeShouldBeInvoiceErr);\n+ LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n+ ReportDocumentNo := Variant;\n+ Assert.AreEqual(CustLedgerEntry.\"Document No.\", ReportDocumentNo, DocumentNoShouldMatchErr);\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('EXRAgedAccPayablePostingDateHandler')]\n+ procedure AgedAccountsPayableReportAgesByPostingDate()\n+ var\n+ Vendor: Record Vendor;\n+ VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ Variant: Variant;\n+ RequestPageXml: Text;\n+ ReportingDateText: Text;\n+ ReportingDate: Date;\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO] Aged Accounts Payable report uses Posting Date as Reporting Date when aging by Posting Date\n+ InitializeAgingData();\n+\n+ // [GIVEN] Vendor \"V\" with an open ledger entry where Posting Date, Document Date, and Due Date are distinct\n+ CreateMinimalVendor(Vendor);\n+ CreateVendorLedgerEntry(VendorLedgerEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n+ VendorLedgerEntry.\"Document Date\" := WorkDate() - 10;\n+ VendorLedgerEntry.Modify();\n+ Commit();\n+\n+ // [WHEN] Running the Aged Accounts Payable Excel report with Aging By = Posting Date\n+ RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Acc Payable Excel\", RequestPageXml);\n+ LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Acc Payable Excel\", Variant, RequestPageXml);\n+\n+ // [THEN] The Reporting Date matches the Posting Date of the vendor ledger entry\n+ LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n+ Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n+ LibraryReportDataset.GetNextRow();\n+ LibraryReportDataset.FindCurrentRowValue('ReportingDate', Variant);\n+ ReportingDateText := Variant;\n+ Evaluate(ReportingDate, ReportingDateText);\n+ Assert.AreEqual(VendorLedgerEntry.\"Posting Date\", ReportingDate, 'Reporting Date should match the Posting Date when aging by Posting Date');\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('EXRAgedAccountsRecExcelHandler')]\n+ procedure AgedAccountsRecRendersCurrencyCodePerEntry()\n+ var\n+ Customer: Record Customer;\n+ GeneralLedgerSetup: Record \"General Ledger Setup\";\n+ UsdEntry, LcyEntry : Record \"Cust. Ledger Entry\";\n+ Variant: Variant;\n+ RequestPageXml: Text;\n+ LcyCode: Code[10];\n+ ForeignCurrencyCode: Code[10];\n+ DocNo, CurrencyCode : Text;\n+ i: Integer;\n+ UsdRowSeen, LcyRowSeen : Boolean;\n+ begin\n+ // [SCENARIO 637444] Aged Accounts Receivable Excel renders each row's own Currency Code, not a single per-customer value\n+ InitializeAgingData();\n+\n+ // [GIVEN] G/L Setup with a distinct LCY Code\n+ LcyCode := 'LCY';\n+ ForeignCurrencyCode := 'USD';\n+ if not GeneralLedgerSetup.Get() then\n+ GeneralLedgerSetup.Insert();\n+ GeneralLedgerSetup.\"LCY Code\" := LcyCode;\n+ GeneralLedgerSetup.Modify();\n+\n+ // [GIVEN] A customer with one foreign-currency entry and one LCY (empty Currency Code) entry\n+ CreateMinimalCustomer(Customer);\n+ CreateCustLedgerEntry(UsdEntry, Customer.\"No.\", \"Gen. Journal Document Type\"::Invoice, ForeignCurrencyCode);\n+ CreateCustLedgerEntry(LcyEntry, Customer.\"No.\", \"Gen. Journal Document Type\"::Invoice, '');\n+ Commit();\n+\n+ // [WHEN] Running the Aged Accounts Receivable Excel report\n+ RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Accounts Rec Excel\", RequestPageXml);\n+ LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Accounts Rec Excel\", Variant, RequestPageXml);\n+\n+ // [THEN] The foreign-currency row shows the foreign code and the LCY row shows the LCY code\n+ LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n+ Assert.AreEqual(2, LibraryReportDataset.RowCount(), 'Two aging entries should be exported');\n+ for i := 1 to 2 do begin\n+ LibraryReportDataset.GetNextRow();\n+ LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n+ DocNo := Variant;\n+ LibraryReportDataset.FindCurrentRowValue('CurrencyCode', Variant);\n+ CurrencyCode := Variant;\n+ if DocNo = UsdEntry.\"Document No.\" then begin\n+ Assert.AreEqual(ForeignCurrencyCode, CurrencyCode, 'Foreign-currency row should show its own currency code');\n+ UsdRowSeen := true;\n+ end else\n+ if DocNo = LcyEntry.\"Document No.\" then begin\n+ Assert.AreEqual(LcyCode, CurrencyCode, 'LCY (empty Currency Code) row should fall back to G/L Setup LCY Code');\n+ LcyRowSeen := true;\n+ end;\n+ end;\n+ Assert.IsTrue(UsdRowSeen, 'Foreign-currency row should be present');\n+ Assert.IsTrue(LcyRowSeen, 'LCY row should be present');\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('EXRAgedAccPayableExcelHandler')]\n+ procedure AgedAccountsPayableRendersCurrencyCodePerEntry()\n+ var\n+ Vendor: Record Vendor;\n+ GeneralLedgerSetup: Record \"General Ledger Setup\";\n+ UsdEntry, LcyEntry : Record \"Vendor Ledger Entry\";\n+ Variant: Variant;\n+ RequestPageXml: Text;\n+ LcyCode: Code[10];\n+ ForeignCurrencyCode: Code[10];\n+ DocNo, CurrencyCode : Text;\n+ i: Integer;\n+ UsdRowSeen, LcyRowSeen : Boolean;\n+ begin\n+ // [SCENARIO 637444] Aged Accounts Payable Excel renders each row's own Currency Code, not a single per-vendor value\n+ InitializeAgingData();\n+\n+ // [GIVEN] G/L Setup with a distinct LCY Code\n+ LcyCode := 'LCY';\n+ ForeignCurrencyCode := 'USD';\n+ if not GeneralLedgerSetup.Get() then\n+ GeneralLedgerSetup.Insert();\n+ GeneralLedgerSetup.\"LCY Code\" := LcyCode;\n+ GeneralLedgerSetup.Modify();\n+\n+ // [GIVEN] A vendor with one foreign-currency entry and one LCY (empty Currency Code) entry\n+ CreateMinimalVendor(Vendor);\n+ CreateVendorLedgerEntry(UsdEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice, ForeignCurrencyCode);\n+ CreateVendorLedgerEntry(LcyEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice, '');\n+ Commit();\n+\n+ // [WHEN] Running the Aged Accounts Payable Excel report\n+ RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Acc Payable Excel\", RequestPageXml);\n+ LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Acc Payable Excel\", Variant, RequestPageXml);\n+\n+ // [THEN] The foreign-currency row shows the foreign code and the LCY row shows the LCY code\n+ LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n+ Assert.AreEqual(2, LibraryReportDataset.RowCount(), 'Two aging entries should be exported');\n+ for i := 1 to 2 do begin\n+ LibraryReportDataset.GetNextRow();\n+ LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n+ DocNo := Variant;\n+ LibraryReportDataset.FindCurrentRowValue('CurrencyCode', Variant);\n+ CurrencyCode := Variant;\n+ if DocNo = UsdEntry.\"Document No.\" then begin\n+ Assert.AreEqual(ForeignCurrencyCode, CurrencyCode, 'Foreign-currency row should show its own currency code');\n+ UsdRowSeen := true;\n+ end else\n+ if DocNo = LcyEntry.\"Document No.\" then begin\n+ Assert.AreEqual(LcyCode, CurrencyCode, 'LCY (empty Currency Code) row should fall back to G/L Setup LCY Code');\n+ LcyRowSeen := true;\n+ end;\n+ end;\n+ Assert.IsTrue(UsdRowSeen, 'Foreign-currency row should be present');\n+ Assert.IsTrue(LcyRowSeen, 'LCY row should be present');\n+ end;\n+\n+ local procedure InitializeAgingData()\n+ var\n+ Vendor: Record Vendor;\n+ Customer: Record Customer;\n+ VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ CustLedgerEntry: Record \"Cust. Ledger Entry\";\n+ DetailedVendorLedgEntry: Record \"Detailed Vendor Ledg. Entry\";\n+ DetailedCustLedgEntry: Record \"Detailed Cust. Ledg. Entry\";\n+ begin\n+ DetailedVendorLedgEntry.DeleteAll();\n+ DetailedCustLedgEntry.DeleteAll();\n+ VendorLedgerEntry.DeleteAll();\n+ CustLedgerEntry.DeleteAll();\n+ Vendor.DeleteAll();\n+ Customer.DeleteAll();\n+ end;\n+\n+ local procedure CreateMinimalVendor(var Vendor: Record Vendor)\n+ begin\n+ Vendor.Init();\n+ Vendor.\"No.\" := CopyStr(Format(CreateGuid()), 1, MaxStrLen(Vendor.\"No.\"));\n+ Vendor.Name := Vendor.\"No.\";\n+ Vendor.Insert();\n+ end;\n+\n+ local procedure CreateMinimalCustomer(var Customer: Record Customer)\n+ begin\n+ Customer.Init();\n+ Customer.\"No.\" := CopyStr(Format(CreateGuid()), 1, MaxStrLen(Customer.\"No.\"));\n+ Customer.Name := Customer.\"No.\";\n+ Customer.Insert();\n+ end;\n+\n+ local procedure CreateVendorLedgerEntry(var VendorLedgerEntry: Record \"Vendor Ledger Entry\"; VendorNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\")\n+ begin\n+ CreateVendorLedgerEntry(VendorLedgerEntry, VendorNo, DocumentType, '');\n+ end;\n+\n+ local procedure CreateVendorLedgerEntry(var VendorLedgerEntry: Record \"Vendor Ledger Entry\"; VendorNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\"; CurrencyCode: Code[10])\n+ var\n+ DetailedVendorLedgEntry: Record \"Detailed Vendor Ledg. Entry\";\n+ EntryNo: Integer;\n+ Amount: Decimal;\n+ begin\n+ if VendorLedgerEntry.FindLast() then;\n+ EntryNo := VendorLedgerEntry.\"Entry No.\" + 1;\n+\n+ VendorLedgerEntry.Init();\n+ VendorLedgerEntry.\"Entry No.\" := EntryNo;\n+ VendorLedgerEntry.\"Vendor No.\" := VendorNo;\n+ VendorLedgerEntry.\"Vendor Name\" := VendorNo;\n+ VendorLedgerEntry.\"Document Type\" := DocumentType;\n+ VendorLedgerEntry.\"Document No.\" := 'DOC' + Format(EntryNo);\n+ VendorLedgerEntry.\"Posting Date\" := WorkDate();\n+ VendorLedgerEntry.\"Document Date\" := WorkDate();\n+ VendorLedgerEntry.\"Due Date\" := WorkDate() + 30;\n+ VendorLedgerEntry.\"Currency Code\" := CurrencyCode;\n+ VendorLedgerEntry.Open := true;\n+ VendorLedgerEntry.Insert();\n+\n+ // Create detailed vendor ledger entry for remaining amount\n+ Amount := -LibraryRandom.RandDec(1000, 2);\n+ if DetailedVendorLedgEntry.FindLast() then;\n+ DetailedVendorLedgEntry.Init();\n+ DetailedVendorLedgEntry.\"Entry No.\" := DetailedVendorLedgEntry.\"Entry No.\" + 1;\n+ DetailedVendorLedgEntry.\"Vendor Ledger Entry No.\" := VendorLedgerEntry.\"Entry No.\";\n+ DetailedVendorLedgEntry.\"Vendor No.\" := VendorNo;\n+ DetailedVendorLedgEntry.\"Posting Date\" := WorkDate();\n+ DetailedVendorLedgEntry.\"Entry Type\" := DetailedVendorLedgEntry.\"Entry Type\"::\"Initial Entry\";\n+ DetailedVendorLedgEntry.Amount := Amount;\n+ DetailedVendorLedgEntry.\"Amount (LCY)\" := Amount;\n+ DetailedVendorLedgEntry.Insert();\n+ end;\n+\n+ local procedure CreateCustLedgerEntry(var CustLedgerEntry: Record \"Cust. Ledger Entry\"; CustomerNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\")\n+ begin\n+ CreateCustLedgerEntry(CustLedgerEntry, CustomerNo, DocumentType, '');\n+ end;\n+\n+ local procedure CreateCustLedgerEntry(var CustLedgerEntry: Record \"Cust. Ledger Entry\"; CustomerNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\"; CurrencyCode: Code[10])\n+ var\n+ DetailedCustLedgEntry: Record \"Detailed Cust. Ledg. Entry\";\n+ EntryNo: Integer;\n+ Amount: Decimal;\n+ begin\n+ if CustLedgerEntry.FindLast() then;\n+ EntryNo := CustLedgerEntry.\"Entry No.\" + 1;\n+\n+ CustLedgerEntry.Init();\n+ CustLedgerEntry.\"Entry No.\" := EntryNo;\n+ CustLedgerEntry.\"Customer No.\" := CustomerNo;\n+ CustLedgerEntry.\"Customer Name\" := CustomerNo;\n+ CustLedgerEntry.\"Document Type\" := DocumentType;\n+ CustLedgerEntry.\"Document No.\" := 'DOC' + Format(EntryNo);\n+ CustLedgerEntry.\"Posting Date\" := WorkDate();\n+ CustLedgerEntry.\"Document Date\" := WorkDate();\n+ CustLedgerEntry.\"Due Date\" := WorkDate() + 30;\n+ CustLedgerEntry.\"Currency Code\" := CurrencyCode;\n+ CustLedgerEntry.Open := true;\n+ CustLedgerEntry.Insert();\n+\n+ // Create detailed customer ledger entry for remaining amount\n+ Amount := LibraryRandom.RandDec(1000, 2);\n+ if DetailedCustLedgEntry.FindLast() then;\n+ DetailedCustLedgEntry.Init();\n+ DetailedCustLedgEntry.\"Entry No.\" := DetailedCustLedgEntry.\"Entry No.\" + 1;\n+ DetailedCustLedgEntry.\"Cust. Ledger Entry No.\" := CustLedgerEntry.\"Entry No.\";\n+ DetailedCustLedgEntry.\"Customer No.\" := CustomerNo;\n+ DetailedCustLedgEntry.\"Posting Date\" := WorkDate();\n+ DetailedCustLedgEntry.\"Entry Type\" := DetailedCustLedgEntry.\"Entry Type\"::\"Initial Entry\";\n+ DetailedCustLedgEntry.Amount := Amount;\n+ DetailedCustLedgEntry.\"Amount (LCY)\" := Amount;\n+ DetailedCustLedgEntry.Insert();\n+ end;\n+\n+ [RequestPageHandler]\n+ procedure EXRAgedAccPayableExcelHandler(var EXRAgedAccPayableExcel: TestRequestPage \"EXR Aged Acc Payable Excel\")\n+ begin\n+ EXRAgedAccPayableExcel.AgedAsOfOption.SetValue(WorkDate());\n+ EXRAgedAccPayableExcel.OK().Invoke();\n+ end;\n+\n+ [RequestPageHandler]\n+ procedure EXRAgedAccountsRecExcelHandler(var EXRAgedAccountsRecExcel: TestRequestPage \"EXR Aged Accounts Rec Excel\")\n+ begin\n+ EXRAgedAccountsRecExcel.AgedAsOfOption.SetValue(WorkDate());\n+ EXRAgedAccountsRecExcel.OK().Invoke();\n+ end;\n+\n+ [RequestPageHandler]\n+ procedure EXRAgedAccPayablePostingDateHandler(var EXRAgedAccPayableExcel: TestRequestPage \"EXR Aged Acc Payable Excel\")\n+ begin\n+ EXRAgedAccPayableExcel.AgedAsOfOption.SetValue(WorkDate());\n+ EXRAgedAccPayableExcel.AgingbyOption.SetValue('Posting Date');\n+ EXRAgedAccPayableExcel.OK().Invoke();\n+ end;\n+}\ndiff --git a/src/Apps/W1/ExcelReports/Test/src/TrialBalanceExcelReports.Codeunit.al b/src/Apps/W1/ExcelReports/Test/src/TrialBalanceExcelReports.Codeunit.al\nindex b7bb3a1e21..b2468f3b9a 100644\n--- a/src/Apps/W1/ExcelReports/Test/src/TrialBalanceExcelReports.Codeunit.al\n+++ b/src/Apps/W1/ExcelReports/Test/src/TrialBalanceExcelReports.Codeunit.al\n@@ -10,12 +10,7 @@ using Microsoft.Finance.Dimension;\n using Microsoft.Finance.ExcelReports;\n using Microsoft.Finance.GeneralLedger.Account;\n using Microsoft.Finance.GeneralLedger.Budget;\n-using Microsoft.Finance.GeneralLedger.Journal;\n using Microsoft.Finance.GeneralLedger.Ledger;\n-using Microsoft.Purchases.Payables;\n-using Microsoft.Purchases.Vendor;\n-using Microsoft.Sales.Customer;\n-using Microsoft.Sales.Receivables;\n \n codeunit 139544 \"Trial Balance Excel Reports\"\n {\n@@ -26,11 +21,8 @@ codeunit 139544 \"Trial Balance Excel Reports\"\n \n var\n LibraryERM: Codeunit \"Library - ERM\";\n- LibraryRandom: Codeunit \"Library - Random\";\n LibraryReportDataset: Codeunit \"Library - Report Dataset\";\n Assert: Codeunit Assert;\n- DocumentTypeShouldBeInvoiceErr: Label 'Document Type should be Invoice';\n- DocumentNoShouldMatchErr: Label 'Document No should match the ledger entry';\n \n [Test]\n [HandlerFunctions('EXRTrialBalanceExcelHandler')]\n@@ -667,116 +659,6 @@ codeunit 139544 \"Trial Balance Excel Reports\"\n Assert.AreEqual(0, TempTrialBalanceData.\"Starting Balance\", 'Starting Balance should be zero after closing entries')\n end;\n \n- [Test]\n- [HandlerFunctions('EXRAgedAccPayableExcelHandler')]\n- procedure AgedAccountsPayableExportsDocumentTypeAndNo()\n- var\n- Vendor: Record Vendor;\n- VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n- Variant: Variant;\n- RequestPageXml: Text;\n- ReportDocumentType: Text;\n- ReportDocumentNo: Text;\n- begin\n- // [FEATURE] [AI test]\n- // [SCENARIO 622247] Aged Accounts Payable Excel report exports Document Type and Document No fields correctly for Invoice entries\n- InitializeAgingData();\n-\n- // [GIVEN] Vendor \"V\" with an open vendor ledger entry of type Invoice\n- // Create vendor directly to avoid VAT posting setup requirements in some localizations\n- CreateMinimalVendor(Vendor);\n- CreateVendorLedgerEntry(VendorLedgerEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n- Commit();\n-\n- // [WHEN] Running the Aged Accounts Payable Excel report\n- RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Acc Payable Excel\", RequestPageXml);\n- LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Acc Payable Excel\", Variant, RequestPageXml);\n-\n- // [THEN] The exported data contains the Document Type \"Invoice\" and the correct Document No\n- LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n- Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n- LibraryReportDataset.GetNextRow();\n- LibraryReportDataset.FindCurrentRowValue('DocumentType', Variant);\n- ReportDocumentType := Variant;\n- Assert.AreEqual(Format(\"Gen. Journal Document Type\"::Invoice), ReportDocumentType, DocumentTypeShouldBeInvoiceErr);\n- LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n- ReportDocumentNo := Variant;\n- Assert.AreEqual(VendorLedgerEntry.\"Document No.\", ReportDocumentNo, DocumentNoShouldMatchErr);\n- end;\n-\n- [Test]\n- [HandlerFunctions('EXRAgedAccountsRecExcelHandler')]\n- procedure AgedAccountsRecExportsDocumentTypeAndNo()\n- var\n- Customer: Record Customer;\n- CustLedgerEntry: Record \"Cust. Ledger Entry\";\n- Variant: Variant;\n- RequestPageXml: Text;\n- ReportDocumentType: Text;\n- ReportDocumentNo: Text;\n- begin\n- // [FEATURE] [AI test]\n- // [SCENARIO 622247] Aged Accounts Receivable Excel report exports Document Type and Document No fields correctly for Invoice entries\n- InitializeAgingData();\n-\n- // [GIVEN] Customer \"C\" with an open customer ledger entry of type Invoice\n- // Create customer directly to avoid VAT posting setup requirements in some localizations\n- CreateMinimalCustomer(Customer);\n- CreateCustLedgerEntry(CustLedgerEntry, Customer.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n- Commit();\n-\n- // [WHEN] Running the Aged Accounts Receivable Excel report\n- RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Accounts Rec Excel\", RequestPageXml);\n- LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Accounts Rec Excel\", Variant, RequestPageXml);\n-\n- // [THEN] The exported data contains the Document Type \"Invoice\" and the correct Document No\n- LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n- Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n- LibraryReportDataset.GetNextRow();\n- LibraryReportDataset.FindCurrentRowValue('DocumentType', Variant);\n- ReportDocumentType := Variant;\n- Assert.AreEqual(Format(\"Gen. Journal Document Type\"::Invoice), ReportDocumentType, DocumentTypeShouldBeInvoiceErr);\n- LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n- ReportDocumentNo := Variant;\n- Assert.AreEqual(CustLedgerEntry.\"Document No.\", ReportDocumentNo, DocumentNoShouldMatchErr);\n- end;\n-\n- [Test]\n- [HandlerFunctions('EXRAgedAccPayablePostingDateHandler')]\n- procedure AgedAccountsPayableReportAgesByPostingDate()\n- var\n- Vendor: Record Vendor;\n- VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n- Variant: Variant;\n- RequestPageXml: Text;\n- ReportingDateText: Text;\n- ReportingDate: Date;\n- begin\n- // [FEATURE] [AI test 0.4]\n- // [SCENARIO] Aged Accounts Payable report uses Posting Date as Reporting Date when aging by Posting Date\n- InitializeAgingData();\n-\n- // [GIVEN] Vendor \"V\" with an open ledger entry where Posting Date, Document Date, and Due Date are distinct\n- CreateMinimalVendor(Vendor);\n- CreateVendorLedgerEntry(VendorLedgerEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n- VendorLedgerEntry.\"Document Date\" := WorkDate() - 10;\n- VendorLedgerEntry.Modify();\n- Commit();\n-\n- // [WHEN] Running the Aged Accounts Payable Excel report with Aging By = Posting Date\n- RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Acc Payable Excel\", RequestPageXml);\n- LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Acc Payable Excel\", Variant, RequestPageXml);\n-\n- // [THEN] The Reporting Date matches the Posting Date of the vendor ledger entry\n- LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n- Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n- LibraryReportDataset.GetNextRow();\n- LibraryReportDataset.FindCurrentRowValue('ReportingDate', Variant);\n- ReportingDateText := Variant;\n- Evaluate(ReportingDate, ReportingDateText);\n- Assert.AreEqual(VendorLedgerEntry.\"Posting Date\", ReportingDate, 'Reporting Date should match the Posting Date when aging by Posting Date');\n- end;\n-\n local procedure CreateSampleBusinessUnits(HowMany: Integer)\n var\n BusinessUnit: Record \"Business Unit\";\n@@ -900,109 +782,6 @@ codeunit 139544 \"Trial Balance Excel Reports\"\n GLEntry.Insert();\n end;\n \n- local procedure InitializeAgingData()\n- var\n- Vendor: Record Vendor;\n- Customer: Record Customer;\n- VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n- CustLedgerEntry: Record \"Cust. Ledger Entry\";\n- DetailedVendorLedgEntry: Record \"Detailed Vendor Ledg. Entry\";\n- DetailedCustLedgEntry: Record \"Detailed Cust. Ledg. Entry\";\n- begin\n- DetailedVendorLedgEntry.DeleteAll();\n- DetailedCustLedgEntry.DeleteAll();\n- VendorLedgerEntry.DeleteAll();\n- CustLedgerEntry.DeleteAll();\n- Vendor.DeleteAll();\n- Customer.DeleteAll();\n- end;\n-\n- local procedure CreateMinimalVendor(var Vendor: Record Vendor)\n- begin\n- Vendor.Init();\n- Vendor.\"No.\" := CopyStr(Format(CreateGuid()), 1, MaxStrLen(Vendor.\"No.\"));\n- Vendor.Name := Vendor.\"No.\";\n- Vendor.Insert();\n- end;\n-\n- local procedure CreateMinimalCustomer(var Customer: Record Customer)\n- begin\n- Customer.Init();\n- Customer.\"No.\" := CopyStr(Format(CreateGuid()), 1, MaxStrLen(Customer.\"No.\"));\n- Customer.Name := Customer.\"No.\";\n- Customer.Insert();\n- end;\n-\n- local procedure CreateVendorLedgerEntry(var VendorLedgerEntry: Record \"Vendor Ledger Entry\"; VendorNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\")\n- var\n- DetailedVendorLedgEntry: Record \"Detailed Vendor Ledg. Entry\";\n- EntryNo: Integer;\n- Amount: Decimal;\n- begin\n- if VendorLedgerEntry.FindLast() then;\n- EntryNo := VendorLedgerEntry.\"Entry No.\" + 1;\n-\n- VendorLedgerEntry.Init();\n- VendorLedgerEntry.\"Entry No.\" := EntryNo;\n- VendorLedgerEntry.\"Vendor No.\" := VendorNo;\n- VendorLedgerEntry.\"Vendor Name\" := VendorNo;\n- VendorLedgerEntry.\"Document Type\" := DocumentType;\n- VendorLedgerEntry.\"Document No.\" := 'DOC' + Format(EntryNo);\n- VendorLedgerEntry.\"Posting Date\" := WorkDate();\n- VendorLedgerEntry.\"Document Date\" := WorkDate();\n- VendorLedgerEntry.\"Due Date\" := WorkDate() + 30;\n- VendorLedgerEntry.Open := true;\n- VendorLedgerEntry.Insert();\n-\n- // Create detailed vendor ledger entry for remaining amount\n- Amount := -LibraryRandom.RandDec(1000, 2);\n- if DetailedVendorLedgEntry.FindLast() then;\n- DetailedVendorLedgEntry.Init();\n- DetailedVendorLedgEntry.\"Entry No.\" := DetailedVendorLedgEntry.\"Entry No.\" + 1;\n- DetailedVendorLedgEntry.\"Vendor Ledger Entry No.\" := VendorLedgerEntry.\"Entry No.\";\n- DetailedVendorLedgEntry.\"Vendor No.\" := VendorNo;\n- DetailedVendorLedgEntry.\"Posting Date\" := WorkDate();\n- DetailedVendorLedgEntry.\"Entry Type\" := DetailedVendorLedgEntry.\"Entry Type\"::\"Initial Entry\";\n- DetailedVendorLedgEntry.Amount := Amount;\n- DetailedVendorLedgEntry.\"Amount (LCY)\" := Amount;\n- DetailedVendorLedgEntry.Insert();\n- end;\n-\n- local procedure CreateCustLedgerEntry(var CustLedgerEntry: Record \"Cust. Ledger Entry\"; CustomerNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\")\n- var\n- DetailedCustLedgEntry: Record \"Detailed Cust. Ledg. Entry\";\n- EntryNo: Integer;\n- Amount: Decimal;\n- begin\n- if CustLedgerEntry.FindLast() then;\n- EntryNo := CustLedgerEntry.\"Entry No.\" + 1;\n-\n- CustLedgerEntry.Init();\n- CustLedgerEntry.\"Entry No.\" := EntryNo;\n- CustLedgerEntry.\"Customer No.\" := CustomerNo;\n- CustLedgerEntry.\"Customer Name\" := CustomerNo;\n- CustLedgerEntry.\"Document Type\" := DocumentType;\n- CustLedgerEntry.\"Document No.\" := 'DOC' + Format(EntryNo);\n- CustLedgerEntry.\"Posting Date\" := WorkDate();\n- CustLedgerEntry.\"Document Date\" := WorkDate();\n- CustLedgerEntry.\"Due Date\" := WorkDate() + 30;\n- CustLedgerEntry.Open := true;\n- CustLedgerEntry.Insert();\n-\n- // Create detailed customer ledger entry for remaining amount\n- Amount := LibraryRandom.RandDec(1000, 2);\n- if DetailedCustLedgEntry.FindLast() then;\n- DetailedCustLedgEntry.Init();\n- DetailedCustLedgEntry.\"Entry No.\" := DetailedCustLedgEntry.\"Entry No.\" + 1;\n- DetailedCustLedgEntry.\"Cust. Ledger Entry No.\" := CustLedgerEntry.\"Entry No.\";\n- DetailedCustLedgEntry.\"Customer No.\" := CustomerNo;\n- DetailedCustLedgEntry.\"Posting Date\" := WorkDate();\n- DetailedCustLedgEntry.\"Entry Type\" := DetailedCustLedgEntry.\"Entry Type\"::\"Initial Entry\";\n- DetailedCustLedgEntry.Amount := Amount;\n- DetailedCustLedgEntry.\"Amount (LCY)\" := Amount;\n- DetailedCustLedgEntry.Insert();\n- end;\n-\n [RequestPageHandler]\n procedure EXRTrialBalanceExcelHandler(var EXRTrialBalanceExcel: TestRequestPage \"EXR Trial Balance Excel\")\n begin\n@@ -1032,28 +811,6 @@ codeunit 139544 \"Trial Balance Excel Reports\"\n EXRConsolidatedTrialBalance.OK().Invoke();\n end;\n \n- [RequestPageHandler]\n- procedure EXRAgedAccPayableExcelHandler(var EXRAgedAccPayableExcel: TestRequestPage \"EXR Aged Acc Payable Excel\")\n- begin\n- EXRAgedAccPayableExcel.AgedAsOfOption.SetValue(WorkDate());\n- EXRAgedAccPayableExcel.OK().Invoke();\n- end;\n-\n- [RequestPageHandler]\n- procedure EXRAgedAccountsRecExcelHandler(var EXRAgedAccountsRecExcel: TestRequestPage \"EXR Aged Accounts Rec Excel\")\n- begin\n- EXRAgedAccountsRecExcel.AgedAsOfOption.SetValue(WorkDate());\n- EXRAgedAccountsRecExcel.OK().Invoke();\n- end;\n-\n- [RequestPageHandler]\n- procedure EXRAgedAccPayablePostingDateHandler(var EXRAgedAccPayableExcel: TestRequestPage \"EXR Aged Acc Payable Excel\")\n- begin\n- EXRAgedAccPayableExcel.AgedAsOfOption.SetValue(WorkDate());\n- EXRAgedAccPayableExcel.AgingbyOption.SetValue('Posting Date');\n- EXRAgedAccPayableExcel.OK().Invoke();\n- end;\n-\n #if not CLEAN27\n #pragma warning disable AL0432\n [EventSubscriber(ObjectType::Codeunit, Codeunit::\"Trial Balance\", OnIsPerformantTrialBalanceFeatureActive, '', false, false)]\n"} diff --git a/dataset/problemstatement/microsoft__BCApps-8287/README.md b/dataset/problemstatement/microsoft__BCApps-8287/README.md index 0ca474a55..062e9a8e1 100644 --- a/dataset/problemstatement/microsoft__BCApps-8287/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8287/README.md @@ -1,12 +1,12 @@ # [Quality Management] Add missing validation of "Allowable Values" in Quality Test card -## What & why - -image - - -## Linked work - +## What & why + +image + + +## Linked work + Fixes [AB#624240](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/624240) diff --git a/dataset/problemstatement/microsoft__BCApps-8313/README.md b/dataset/problemstatement/microsoft__BCApps-8313/README.md new file mode 100644 index 000000000..0709a7410 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8313/README.md @@ -0,0 +1,32 @@ +# Fix E-Doc V1 PEPPOL import: Sub Total uses LineExtensionAmount from XML + +## Summary + +- **`EDocImport.Codeunit.al:843`** — `V1_CopyFromPurchaseLine` was setting `"Sub Total"` as `Direct Unit Cost * Quantity` instead of using `PurchaseLine.Amount` which holds the `LineExtensionAmount` parsed directly from the PEPPOL XML. +- **`EDocReceiveTest.Codeunit.al`** — Added regression test `ReceivePeppolInvoice_LineSubTotalFromXml` that verifies `"Sub Total"` = 11.20 for a line with Qty=1.65, Price=6.79, LineExtensionAmount=11.20. +- **`PEPPOL_LineRounding.xml`** — Minimal PEPPOL BIS 3.0 test invoice with rounding-sensitive quantities. + +## Root cause + +In the V1 import path, `EDocImportPEPPOLBIS30` reads `LineExtensionAmount` (the vendor-rounded line total) into `PurchaseLine.Amount`. But `V1_CopyFromPurchaseLine` ignored it and recalculated: + +```al +// Before (bug): +EDocumentPurchaseLine."Sub Total" := PurchaseLine."Direct Unit Cost" * PurchaseLine.Quantity; +// 6.79 * 1.65 = 11.2035 — wrong, shows unrounded value on E-Document Purchase Draft page + +// After (fix): +EDocumentPurchaseLine."Sub Total" := PurchaseLine.Amount; +// 11.20 — correct, preserves vendor-rounded value from XML +``` + +`PurchaseLine.Amount` is set from the XML via `Evaluate(PurchaseLine.Amount, Value, 9)` at `EDocImportPEPPOLBIS30:503` and is preserved through `MapEDocument` (which copies all fields and only transforms Text/Code types, not Decimal). + +## Test plan +- [ ] `ReceivePeppolInvoice_LineSubTotalFromXml` passes: asserts `EDocumentPurchaseLine."Sub Total"` = 11.20 + +Fixes bug [AB#613698](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/613698) + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-8380/README.md b/dataset/problemstatement/microsoft__BCApps-8380/README.md new file mode 100644 index 000000000..567df409a --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8380/README.md @@ -0,0 +1,16 @@ +# [Quality Management] Workflow responses are marked as default for any event + +## What & why + +Quality Management responses are nominally valid only for Quality Management events. + +## Linked work + +Fixes [AB#626774](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/626774) + + + + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-8423/README.md b/dataset/problemstatement/microsoft__BCApps-8423/README.md new file mode 100644 index 000000000..b824fbf61 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8423/README.md @@ -0,0 +1,24 @@ +# Render per-row Currency Code in Aged Accounts Receivable/Payable Excel + +## Summary + +The `CurrencyCode` column in Aged Accounts Receivable Excel (report 4402) and Aged Accounts Payable Excel (report 4403) was bound to a single AgingData-buffer-wide variable (`CurrencyCodeDisplayCode`) computed once after `InsertAgingData`. Every row of a given customer/vendor displayed the same currency — the last one inserted into the buffer. Customers/vendors with entries in multiple currencies saw foreign-currency rows mislabeled with the LCY code (or vice versa). + +This change: +- Binds the `CurrencyCode` column directly to `AgingData."Currency Code"` so each row renders its own currency. +- Falls back to G/L Setup's LCY Code at insertion time when the ledger entry's `Currency Code` is empty. +- Splits the Aged Accounts tests out of `TrialBalanceExcelReports.Codeunit.al` into a new dedicated `AgedAccountsExcelReports.Codeunit.al` (139547), and adds per-row currency rendering tests for both reports. + +Fixes [AB#637444](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/637444) + +## Test plan +- [x] New tests `AgedAccountsRecRendersCurrencyCodePerEntry` and `AgedAccountsPayableRendersCurrencyCodePerEntry` cover the multi-currency rendering case +- [x] Existing Aged Accounts tests continue to pass after relocation + + + + + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-8524/README.md b/dataset/problemstatement/microsoft__BCApps-8524/README.md new file mode 100644 index 000000000..07d0b23a2 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8524/README.md @@ -0,0 +1,21 @@ +# [Quality Management] Improvements in "Value Type Text Expression" and tooltips + +## What & why + +Fixes: +1. Expression Formula not copied to template, not visible on template subform, Default Value not guarded for Text Expression tests +2. Text Expression test value is editable - manual overrides silently lost on re-evaluation +3. Single-line text expression inspection never evaluates the expression + +Improvements: +1. Quality Inspection document teaching tips +2. Setup guide text + +## Linked work + +Fixes [AB#634074](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634074) +Fixes [AB#634080](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634080) +Fixes [AB#634083](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634083) +Fixes [AB#622439](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/622439) + + diff --git a/dataset/problemstatement/microsoft__BCApps-8555/README.md b/dataset/problemstatement/microsoft__BCApps-8555/README.md new file mode 100644 index 000000000..140248ba3 --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8555/README.md @@ -0,0 +1,16 @@ +# [Quality Management] Do not show notification when inspections are not created + +## What & why + +Do not show notifications when new inspections are not created, for example due to setup that instructs to use existing inspections. + +## Linked work +Fixes [AB#624741](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/624741) + + + + + + + + diff --git a/dataset/problemstatement/microsoft__BCApps-8564/README.md b/dataset/problemstatement/microsoft__BCApps-8564/README.md new file mode 100644 index 000000000..48d8647ac --- /dev/null +++ b/dataset/problemstatement/microsoft__BCApps-8564/README.md @@ -0,0 +1,12 @@ +# [Subcontracting] Block Cancel of purchase invoice with subcontracting item charge (Bug 637502) + +Fixes [AB#637502](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/637502) + +Cancelling a Posted Purchase Invoice whose Item Charge is split between a regular item receipt line and a subcontracting service receipt line silently skipped the capacity portion. `CopyDocumentMgt.CopyFromPurchLineItemChargeAssign` rebuilds assignments by iterating Value Entries and looking up the linked Item Ledger Entry; subcontracting item-charge Value Entries have `Item Ledger Entry No. = 0` (only `Capacity Ledger Entry No.` is set), so they were dropped and the orphaned amount was redistributed to inventory entries, corrupting inventory cost. + +Until a proper reversal path exists in BaseApp, this PR narrows the blast radius from the Subcontracting App: + +- `SubcItemJnlPostLineExt`: in `OnBeforeInsertCapValueEntry`, populate `ValueEntry."Item Charge No."` from `ItemJnlLine."Item Charge No."` when `ItemJnlLine."Subc. Item Charge Assign."` is set, so capacity-side Value Entries carry the item charge they came from. +- `SubcPurchPostExt`: subscribe to `Correct Posted Purch. Invoice.OnAfterTestCorrectInvoiceIsAllowed` and block Cancel/Correct when the posted invoice has any Value Entry with `Item Charge No. <> ''` AND `Capacity Ledger Entry No. <> 0`. Plain subcontracting invoices are unaffected. +- Add integration test `CancelInvoiceWithSubcontractingItemChargeIsBlocked` reproducing the bug repro (mixed regular + subcontracting receipt charge assignment) and asserting the block fires. + From ed2ddd9c1be2b6fb6a9f796d0f378f8f55e8c4b4 Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Tue, 23 Jun 2026 10:31:06 +0200 Subject: [PATCH 13/14] Delelte extra lines for README.md --- .../microsoft__BCApps-8287/README.md | 5 -- .../microsoft__BCApps-8293/README.md | 3 - .../microsoft__BCApps-8313/README.md | 73 ++++++++++++------- .../microsoft__BCApps-8380/README.md | 13 ++-- .../microsoft__BCApps-8386/README.md | 5 -- .../microsoft__BCApps-8423/README.md | 45 +++++++----- .../microsoft__BCApps-8524/README.md | 48 +++++++----- .../microsoft__BCApps-8555/README.md | 17 ++--- .../microsoft__BCApps-8564/README.md | 25 ++++--- .../microsoft__BCApps-8600/README.md | 13 +--- .../microsoft__BCApps-8612/README.md | 6 -- .../microsoft__BCApps-8616/README.md | 6 -- .../microsoft__BCApps-8632/README.md | 12 --- 13 files changed, 133 insertions(+), 138 deletions(-) diff --git a/dataset/problemstatement/microsoft__BCApps-8287/README.md b/dataset/problemstatement/microsoft__BCApps-8287/README.md index 062e9a8e1..b8355667b 100644 --- a/dataset/problemstatement/microsoft__BCApps-8287/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8287/README.md @@ -8,8 +8,3 @@ ## Linked work Fixes [AB#624240](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/624240) - - - - - diff --git a/dataset/problemstatement/microsoft__BCApps-8293/README.md b/dataset/problemstatement/microsoft__BCApps-8293/README.md index 250f3cb6e..65c2f4053 100644 --- a/dataset/problemstatement/microsoft__BCApps-8293/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8293/README.md @@ -15,6 +15,3 @@ Added \ProdOFactboxMgmtShowsDataAfterProdOrderFinished\ in codeunit 139989 — v Fixes [AB#634953](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634953) :robot: Generated with GitHub Copilot - - - diff --git a/dataset/problemstatement/microsoft__BCApps-8313/README.md b/dataset/problemstatement/microsoft__BCApps-8313/README.md index 0709a7410..03b104bce 100644 --- a/dataset/problemstatement/microsoft__BCApps-8313/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8313/README.md @@ -1,32 +1,53 @@ # Fix E-Doc V1 PEPPOL import: Sub Total uses LineExtensionAmount from XML -## Summary - -- **`EDocImport.Codeunit.al:843`** — `V1_CopyFromPurchaseLine` was setting `"Sub Total"` as `Direct Unit Cost * Quantity` instead of using `PurchaseLine.Amount` which holds the `LineExtensionAmount` parsed directly from the PEPPOL XML. -- **`EDocReceiveTest.Codeunit.al`** — Added regression test `ReceivePeppolInvoice_LineSubTotalFromXml` that verifies `"Sub Total"` = 11.20 for a line with Qty=1.65, Price=6.79, LineExtensionAmount=11.20. -- **`PEPPOL_LineRounding.xml`** — Minimal PEPPOL BIS 3.0 test invoice with rounding-sensitive quantities. - -## Root cause - -In the V1 import path, `EDocImportPEPPOLBIS30` reads `LineExtensionAmount` (the vendor-rounded line total) into `PurchaseLine.Amount`. But `V1_CopyFromPurchaseLine` ignored it and recalculated: - -```al -// Before (bug): -EDocumentPurchaseLine."Sub Total" := PurchaseLine."Direct Unit Cost" * PurchaseLine.Quantity; -// 6.79 * 1.65 = 11.2035 — wrong, shows unrounded value on E-Document Purchase Draft page - -// After (fix): -EDocumentPurchaseLine."Sub Total" := PurchaseLine.Amount; -// 11.20 — correct, preserves vendor-rounded value from XML -``` - -`PurchaseLine.Amount` is set from the XML via `Evaluate(PurchaseLine.Amount, Value, 9)` at `EDocImportPEPPOLBIS30:503` and is preserved through `MapEDocument` (which copies all fields and only transforms Text/Code types, not Decimal). - -## Test plan -- [ ] `ReceivePeppolInvoice_LineSubTotalFromXml` passes: asserts `EDocumentPurchaseLine."Sub Total"` = 11.20 - -Fixes bug [AB#613698](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/613698) +## Summary + + + +- **`EDocImport.Codeunit.al:843`** — `V1_CopyFromPurchaseLine` was setting `"Sub Total"` as `Direct Unit Cost * Quantity` instead of using `PurchaseLine.Amount` which holds the `LineExtensionAmount` parsed directly from the PEPPOL XML. + +- **`EDocReceiveTest.Codeunit.al`** — Added regression test `ReceivePeppolInvoice_LineSubTotalFromXml` that verifies `"Sub Total"` = 11.20 for a line with Qty=1.65, Price=6.79, LineExtensionAmount=11.20. + +- **`PEPPOL_LineRounding.xml`** — Minimal PEPPOL BIS 3.0 test invoice with rounding-sensitive quantities. + + + +## Root cause + + + +In the V1 import path, `EDocImportPEPPOLBIS30` reads `LineExtensionAmount` (the vendor-rounded line total) into `PurchaseLine.Amount`. But `V1_CopyFromPurchaseLine` ignored it and recalculated: + + + +```al + +// Before (bug): +EDocumentPurchaseLine."Sub Total" := PurchaseLine."Direct Unit Cost" * PurchaseLine.Quantity; +// 6.79 * 1.65 = 11.2035 — wrong, shows unrounded value on E-Document Purchase Draft page + +// After (fix): + +EDocumentPurchaseLine."Sub Total" := PurchaseLine.Amount; + +// 11.20 — correct, preserves vendor-rounded value from XML + +``` + + + +`PurchaseLine.Amount` is set from the XML via `Evaluate(PurchaseLine.Amount, Value, 9)` at `EDocImportPEPPOLBIS30:503` and is preserved through `MapEDocument` (which copies all fields and only transforms Text/Code types, not Decimal). + + + +## Test plan + +- [ ] `ReceivePeppolInvoice_LineSubTotalFromXml` passes: asserts `EDocumentPurchaseLine."Sub Total"` = 11.20 + + + +Fixes bug [AB#613698](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/613698) diff --git a/dataset/problemstatement/microsoft__BCApps-8380/README.md b/dataset/problemstatement/microsoft__BCApps-8380/README.md index 567df409a..be41e29d3 100644 --- a/dataset/problemstatement/microsoft__BCApps-8380/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8380/README.md @@ -1,16 +1,15 @@ # [Quality Management] Workflow responses are marked as default for any event -## What & why - -Quality Management responses are nominally valid only for Quality Management events. - -## Linked work - -Fixes [AB#626774](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/626774) +## What & why + +Quality Management responses are nominally valid only for Quality Management events. +## Linked work + +Fixes [AB#626774](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/626774) diff --git a/dataset/problemstatement/microsoft__BCApps-8386/README.md b/dataset/problemstatement/microsoft__BCApps-8386/README.md index 189d4292a..35976ad13 100644 --- a/dataset/problemstatement/microsoft__BCApps-8386/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8386/README.md @@ -32,8 +32,3 @@ Main only — rare upgrade-window race condition with a self-service mitigation #### Work Item(s) Fixes [AB#637250](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/637250) - - - - - diff --git a/dataset/problemstatement/microsoft__BCApps-8423/README.md b/dataset/problemstatement/microsoft__BCApps-8423/README.md index b824fbf61..ae3b18ad6 100644 --- a/dataset/problemstatement/microsoft__BCApps-8423/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8423/README.md @@ -1,24 +1,29 @@ # Render per-row Currency Code in Aged Accounts Receivable/Payable Excel -## Summary - -The `CurrencyCode` column in Aged Accounts Receivable Excel (report 4402) and Aged Accounts Payable Excel (report 4403) was bound to a single AgingData-buffer-wide variable (`CurrencyCodeDisplayCode`) computed once after `InsertAgingData`. Every row of a given customer/vendor displayed the same currency — the last one inserted into the buffer. Customers/vendors with entries in multiple currencies saw foreign-currency rows mislabeled with the LCY code (or vice versa). - -This change: -- Binds the `CurrencyCode` column directly to `AgingData."Currency Code"` so each row renders its own currency. -- Falls back to G/L Setup's LCY Code at insertion time when the ledger entry's `Currency Code` is empty. -- Splits the Aged Accounts tests out of `TrialBalanceExcelReports.Codeunit.al` into a new dedicated `AgedAccountsExcelReports.Codeunit.al` (139547), and adds per-row currency rendering tests for both reports. - -Fixes [AB#637444](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/637444) - -## Test plan -- [x] New tests `AgedAccountsRecRendersCurrencyCodePerEntry` and `AgedAccountsPayableRendersCurrencyCodePerEntry` cover the multi-currency rendering case -- [x] Existing Aged Accounts tests continue to pass after relocation - - - - - - +## Summary + +The `CurrencyCode` column in Aged Accounts Receivable Excel (report 4402) and Aged Accounts Payable Excel (report 4403) was bound to a single AgingData-buffer-wide variable (`CurrencyCodeDisplayCode`) computed once after `InsertAgingData`. Every row of a given customer/vendor displayed the same currency — the last one inserted into the buffer. Customers/vendors with entries in multiple currencies saw foreign-currency rows mislabeled with the LCY code (or vice versa). + + + +This change: + +- Binds the `CurrencyCode` column directly to `AgingData."Currency Code"` so each row renders its own currency. + +- Falls back to G/L Setup's LCY Code at insertion time when the ledger entry's `Currency Code` is empty. + +- Splits the Aged Accounts tests out of `TrialBalanceExcelReports.Codeunit.al` into a new dedicated `AgedAccountsExcelReports.Codeunit.al` (139547), and adds per-row currency rendering tests for both reports. + + + +Fixes [AB#637444](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/637444) + + + +## Test plan + +- [x] New tests `AgedAccountsRecRendersCurrencyCodePerEntry` and `AgedAccountsPayableRendersCurrencyCodePerEntry` cover the multi-currency rendering case + +- [x] Existing Aged Accounts tests continue to pass after relocation diff --git a/dataset/problemstatement/microsoft__BCApps-8524/README.md b/dataset/problemstatement/microsoft__BCApps-8524/README.md index 07d0b23a2..bd5bcdc80 100644 --- a/dataset/problemstatement/microsoft__BCApps-8524/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8524/README.md @@ -1,21 +1,35 @@ # [Quality Management] Improvements in "Value Type Text Expression" and tooltips -## What & why - -Fixes: -1. Expression Formula not copied to template, not visible on template subform, Default Value not guarded for Text Expression tests -2. Text Expression test value is editable - manual overrides silently lost on re-evaluation -3. Single-line text expression inspection never evaluates the expression - -Improvements: -1. Quality Inspection document teaching tips -2. Setup guide text - -## Linked work - -Fixes [AB#634074](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634074) -Fixes [AB#634080](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634080) -Fixes [AB#634083](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634083) -Fixes [AB#622439](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/622439) +## What & why + + + +Fixes: + +1. Expression Formula not copied to template, not visible on template subform, Default Value not guarded for Text Expression tests + +2. Text Expression test value is editable - manual overrides silently lost on re-evaluation + +3. Single-line text expression inspection never evaluates the expression + + + +Improvements: +1. Quality Inspection document teaching tips +2. Setup guide text + + + +## Linked work + + + +Fixes [AB#634074](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634074) + +Fixes [AB#634080](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634080) + +Fixes [AB#634083](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634083) + +Fixes [AB#622439](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/622439) diff --git a/dataset/problemstatement/microsoft__BCApps-8555/README.md b/dataset/problemstatement/microsoft__BCApps-8555/README.md index 140248ba3..ad0f79655 100644 --- a/dataset/problemstatement/microsoft__BCApps-8555/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8555/README.md @@ -1,16 +1,13 @@ # [Quality Management] Do not show notification when inspections are not created -## What & why - -Do not show notifications when new inspections are not created, for example due to setup that instructs to use existing inspections. - -## Linked work -Fixes [AB#624741](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/624741) - - - - +## What & why +Do not show notifications when new inspections are not created, for example due to setup that instructs to use existing inspections. + + +## Linked work + +Fixes [AB#624741](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/624741) diff --git a/dataset/problemstatement/microsoft__BCApps-8564/README.md b/dataset/problemstatement/microsoft__BCApps-8564/README.md index 48d8647ac..98e114f4b 100644 --- a/dataset/problemstatement/microsoft__BCApps-8564/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8564/README.md @@ -1,12 +1,19 @@ # [Subcontracting] Block Cancel of purchase invoice with subcontracting item charge (Bug 637502) -Fixes [AB#637502](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/637502) - -Cancelling a Posted Purchase Invoice whose Item Charge is split between a regular item receipt line and a subcontracting service receipt line silently skipped the capacity portion. `CopyDocumentMgt.CopyFromPurchLineItemChargeAssign` rebuilds assignments by iterating Value Entries and looking up the linked Item Ledger Entry; subcontracting item-charge Value Entries have `Item Ledger Entry No. = 0` (only `Capacity Ledger Entry No.` is set), so they were dropped and the orphaned amount was redistributed to inventory entries, corrupting inventory cost. - -Until a proper reversal path exists in BaseApp, this PR narrows the blast radius from the Subcontracting App: - -- `SubcItemJnlPostLineExt`: in `OnBeforeInsertCapValueEntry`, populate `ValueEntry."Item Charge No."` from `ItemJnlLine."Item Charge No."` when `ItemJnlLine."Subc. Item Charge Assign."` is set, so capacity-side Value Entries carry the item charge they came from. -- `SubcPurchPostExt`: subscribe to `Correct Posted Purch. Invoice.OnAfterTestCorrectInvoiceIsAllowed` and block Cancel/Correct when the posted invoice has any Value Entry with `Item Charge No. <> ''` AND `Capacity Ledger Entry No. <> 0`. Plain subcontracting invoices are unaffected. -- Add integration test `CancelInvoiceWithSubcontractingItemChargeIsBlocked` reproducing the bug repro (mixed regular + subcontracting receipt charge assignment) and asserting the block fires. +Fixes [AB#637502](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/637502) + + + +Cancelling a Posted Purchase Invoice whose Item Charge is split between a regular item receipt line and a subcontracting service receipt line silently skipped the capacity portion. `CopyDocumentMgt.CopyFromPurchLineItemChargeAssign` rebuilds assignments by iterating Value Entries and looking up the linked Item Ledger Entry; subcontracting item-charge Value Entries have `Item Ledger Entry No. = 0` (only `Capacity Ledger Entry No.` is set), so they were dropped and the orphaned amount was redistributed to inventory entries, corrupting inventory cost. + + +Until a proper reversal path exists in BaseApp, this PR narrows the blast radius from the Subcontracting App: + + + +- `SubcItemJnlPostLineExt`: in `OnBeforeInsertCapValueEntry`, populate `ValueEntry."Item Charge No."` from `ItemJnlLine."Item Charge No."` when `ItemJnlLine."Subc. Item Charge Assign."` is set, so capacity-side Value Entries carry the item charge they came from. + +- `SubcPurchPostExt`: subscribe to `Correct Posted Purch. Invoice.OnAfterTestCorrectInvoiceIsAllowed` and block Cancel/Correct when the posted invoice has any Value Entry with `Item Charge No. <> ''` AND `Capacity Ledger Entry No. <> 0`. Plain subcontracting invoices are unaffected. + +- Add integration test `CancelInvoiceWithSubcontractingItemChargeIsBlocked` reproducing the bug repro (mixed regular + subcontracting receipt charge assignment) and asserting the block fires. diff --git a/dataset/problemstatement/microsoft__BCApps-8600/README.md b/dataset/problemstatement/microsoft__BCApps-8600/README.md index adb7e440e..8a6eb8b30 100644 --- a/dataset/problemstatement/microsoft__BCApps-8600/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8600/README.md @@ -6,19 +6,8 @@ Prevent unsafe changes when subcontracting transfers are in progress When a production order has active transfer orders sending components to a subcontractor, users could previously change or delete the related components and routing lines — potentially causing data mismatches between the transfer orders and the production order. -This PR blocks modifications to key fields (item, quantity, supply method, location, etc.) on Prod. Order Components and Prod. Order Routing Lines when transfer orders or stock at the subcontractor location exist. +This PR blocks modifications to key fields (item, quantity, supply method, location, etc.) on Prod. Order Components and Prod. Order Routing Lines when transfer orders or stock at the subcontractor location exist. ## Linked work Fixes [AB#634269](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/634269) - - - - - - - - - - - diff --git a/dataset/problemstatement/microsoft__BCApps-8612/README.md b/dataset/problemstatement/microsoft__BCApps-8612/README.md index 20c211e75..8dec00a70 100644 --- a/dataset/problemstatement/microsoft__BCApps-8612/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8612/README.md @@ -46,9 +46,3 @@ Fixes [AB#637777](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6- telemetry, feature flags, follow-up work. Write "None" if there's nothing to call out. --> Fixes [AB#637777](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/637777) - - - - - - diff --git a/dataset/problemstatement/microsoft__BCApps-8616/README.md b/dataset/problemstatement/microsoft__BCApps-8616/README.md index 38ad1e372..cec038c6d 100644 --- a/dataset/problemstatement/microsoft__BCApps-8616/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8616/README.md @@ -13,9 +13,3 @@ Added `ItemLedgerEntriesSubcActionsDisabledWhenNotSubcontracting` and `ItemLedge Fixes [AB#638458](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/638458) :robot: Generated with GitHub Copilot - - - - - - diff --git a/dataset/problemstatement/microsoft__BCApps-8632/README.md b/dataset/problemstatement/microsoft__BCApps-8632/README.md index d67cb6c3d..fe2a4baea 100644 --- a/dataset/problemstatement/microsoft__BCApps-8632/README.md +++ b/dataset/problemstatement/microsoft__BCApps-8632/README.md @@ -1,15 +1,3 @@ # [Subcontracting] Add action to view subcontracting transfer orders from production orders Fixes [AB#638532](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/638532) - - - - - - - - - - - - From a4c929891f5cefeb1b3a8eea8c97a1b88559f2d7 Mon Sep 17 00:00:00 2001 From: Jiawen Sun Date: Tue, 23 Jun 2026 11:23:19 +0200 Subject: [PATCH 14/14] Update commit --- dataset/bcbench.jsonl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index 67d7255bf..03efb6e02 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -110,7 +110,7 @@ {"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8524", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-06-08T21:42:31Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Quality Management\\app", "src\\Apps\\W1\\Quality Management\\test"], "patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateLine.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateLine.Table.al\nindex d868fbf50a..e19e4d3dfb 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateLine.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateLine.Table.al\n@@ -48,6 +48,7 @@ table 20403 \"Qlty. Inspection Template Line\"\n if QltyTest.Get(\"Test Code\") then begin\n Rec.Description := QltyTest.Description;\n Rec.\"Unit of Measure Code\" := QltyTest.\"Unit of Measure Code\";\n+ Rec.\"Expression Formula\" := QltyTest.\"Expression Formula\";\n end;\n \n EnsureResultsExist(Rec.\"Test Code\" <> xRec.\"Test Code\");\n@@ -97,7 +98,7 @@ table 20403 \"Qlty. Inspection Template Line\"\n Rec.CalcFields(\"Test Value Type\");\n if Rec.\"Expression Formula\" <> '' then begin\n if not (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Text Expression\"]) then\n- Error(OnlyFieldExpressionErr);\n+ Error(ExpressionFormulaOnlyForTextExpressionErr);\n \n ValidateExpressionFormula();\n end;\n@@ -123,7 +124,7 @@ table 20403 \"Qlty. Inspection Template Line\"\n }\n \n var\n- OnlyFieldExpressionErr: Label 'The Expression Formula can only be used with fields that are a type of Expression';\n+ ExpressionFormulaOnlyForTextExpressionErr: Label 'The Expression Formula can only be used with tests that are a type of Text Expression';\n \n trigger OnInsert()\n begin\ndiff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateSubf.Page.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateSubf.Page.al\nindex 672e18ea4c..2ee3bad573 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateSubf.Page.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/QltyInspectionTemplateSubf.Page.al\n@@ -65,6 +65,12 @@ page 20403 \"Qlty. Inspection Template Subf\"\n {\n StyleExpr = RowStyleText;\n }\n+ field(\"Expression Formula\"; Rec.\"Expression Formula\")\n+ {\n+ StyleExpr = RowStyleText;\n+ Editable = IsExpressionFormulaEditable;\n+ Visible = false;\n+ }\n field(\"Unit of Measure Code\"; Rec.\"Unit of Measure Code\")\n {\n StyleExpr = RowStyleText;\n@@ -503,6 +509,7 @@ page 20403 \"Qlty. Inspection Template Subf\"\n MatrixArrayCaptionSet: array[10] of Text;\n Visible1, Visible2, Visible3, Visible4, Visible5, Visible6, Visible7, Visible8, Visible9, Visible10 : Boolean;\n Editable1, Editable2, Editable3, Editable4, Editable5, Editable6, Editable7, Editable8, Editable9, Editable10 : Boolean;\n+ IsExpressionFormulaEditable: Boolean;\n DescriptionLbl: Label '%1 Description', Comment = '%1 = Matrix field caption';\n ConditionLbl: Label '%1 Condition', Comment = '%1 = Matrix field caption';\n \n@@ -573,6 +580,8 @@ page 20403 \"Qlty. Inspection Template Subf\"\n Editable8 := Visible8 and not RowIsLabel;\n Editable9 := Visible9 and not RowIsLabel;\n Editable10 := Visible10 and not RowIsLabel;\n+\n+ IsExpressionFormulaEditable := Rec.\"Test Value Type\" = Rec.\"Test Value Type\"::\"Value Type Text Expression\";\n end;\n \n local procedure UpdateMatrixDataCondition(Matrix: Integer)\ndiff --git a/src/Apps/W1/Quality Management/app/src/Document/QltyInspection.Page.al b/src/Apps/W1/Quality Management/app/src/Document/QltyInspection.Page.al\nindex f4f87e34e2..d309c3ac76 100644\n--- a/src/Apps/W1/Quality Management/app/src/Document/QltyInspection.Page.al\n+++ b/src/Apps/W1/Quality Management/app/src/Document/QltyInspection.Page.al\n@@ -27,6 +27,8 @@ page 20406 \"Qlty. Inspection\"\n {\n UsageCategory = None;\n Caption = 'Quality Inspection';\n+ AboutTitle = 'About Quality Inspection document';\n+ AboutText = 'The Quality Inspection document is used to manage quality inspections for items, including recording inspection results, taking pictures, and navigating to related documents. The header contains general information about the inspection, while the lines contain details about each quality test performed. You can also create re-inspections, print reports, and perform actions like moving inventory or changing item tracking information based on the inspection results.';\n DataCaptionExpression = GetDataCaptionExpression();\n InsertAllowed = false;\n PageType = Card;\ndiff --git a/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionLine.Table.al b/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionLine.Table.al\nindex 819ca649ca..4b86c3e549 100644\n--- a/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionLine.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionLine.Table.al\n@@ -409,6 +409,8 @@ table 20406 \"Qlty. Inspection Line\"\n if not GetInspection() then\n exit;\n \n+ EvaluateSelfIfOnlyLineIsTextExpression();\n+\n OthersInSameQltyInspectionLine.SetRange(\"Inspection No.\", Rec.\"Inspection No.\");\n OthersInSameQltyInspectionLine.SetRange(\"Re-inspection No.\", Rec.\"Re-inspection No.\");\n OthersInSameQltyInspectionLine.SetFilter(\"Test Value Type\", '%1', QltyInspectionTemplateLine.\"Test Value Type\"::\"Value Type Text Expression\");\n@@ -465,6 +467,21 @@ table 20406 \"Qlty. Inspection Line\"\n until OthersInSameQltyInspectionLine.Next() = 0;\n end;\n \n+ local procedure EvaluateSelfIfOnlyLineIsTextExpression()\n+ var\n+ OtherQltyInspectionLine: Record \"Qlty. Inspection Line\";\n+ begin\n+ Rec.CalcFields(\"Test Value Type\");\n+ if Rec.\"Test Value Type\" <> Rec.\"Test Value Type\"::\"Value Type Text Expression\" then\n+ exit;\n+\n+ OtherQltyInspectionLine.SetRange(\"Inspection No.\", Rec.\"Inspection No.\");\n+ OtherQltyInspectionLine.SetRange(\"Re-inspection No.\", Rec.\"Re-inspection No.\");\n+ OtherQltyInspectionLine.SetFilter(\"Line No.\", '<>%1', Rec.\"Line No.\");\n+ if OtherQltyInspectionLine.IsEmpty() then\n+ Rec.EvaluateTextExpression(QltyInspectionHeader);\n+ end;\n+\n internal procedure EvaluateTextExpression(var EvaluateAgainstQltyInspectionHeader: Record \"Qlty. Inspection Header\")\n var\n QltyExpressionMgmt: Codeunit \"Qlty. Expression Mgmt.\";\ndiff --git a/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionSubform.Page.al b/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionSubform.Page.al\nindex 844802977b..01dc04810b 100644\n--- a/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionSubform.Page.al\n+++ b/src/Apps/W1/Quality Management/app/src/Document/QltyInspectionSubform.Page.al\n@@ -59,7 +59,7 @@ page 20407 \"Qlty. Inspection Subform\"\n trigger OnAssistEdit()\n begin\n Rec.CalcFields(\"Test Value Type\");\n- if Rec.\"Test Value Type\" = Rec.\"Test Value Type\"::\"Value Type Label\" then\n+ if Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Label\", Rec.\"Test Value Type\"::\"Value Type Text Expression\"] then\n exit;\n UpdateRowData();\n \n@@ -371,10 +371,10 @@ page 20407 \"Qlty. Inspection Subform\"\n begin\n OnBeforeCanEditTestValue(Rec, Result, IsHandled);\n if IsHandled then\n- exit;\n+ exit(Result);\n \n Rec.CalcFields(\"Test Value Type\");\n- exit(not (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Label\"]));\n+ exit(not (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Label\", Rec.\"Test Value Type\"::\"Value Type Text Expression\"]));\n end;\n \n /// \ndiff --git a/src/Apps/W1/Quality Management/app/src/Reports/QltyCertificateOfAnalysis.docx b/src/Apps/W1/Quality Management/app/src/Reports/QltyCertificateOfAnalysis.docx\nindex 9202b267d8..db577ad259 100644\nBinary files a/src/Apps/W1/Quality Management/app/src/Reports/QltyCertificateOfAnalysis.docx and b/src/Apps/W1/Quality Management/app/src/Reports/QltyCertificateOfAnalysis.docx differ\ndiff --git a/src/Apps/W1/Quality Management/app/src/Reports/QltyGeneralPurposeInspection.docx b/src/Apps/W1/Quality Management/app/src/Reports/QltyGeneralPurposeInspection.docx\nindex c71945827a..694a6d6621 100644\nBinary files a/src/Apps/W1/Quality Management/app/src/Reports/QltyGeneralPurposeInspection.docx and b/src/Apps/W1/Quality Management/app/src/Reports/QltyGeneralPurposeInspection.docx differ\ndiff --git a/src/Apps/W1/Quality Management/app/src/Reports/QltyNonConformance.docx b/src/Apps/W1/Quality Management/app/src/Reports/QltyNonConformance.docx\nindex c1465f0f1c..abf5c06f36 100644\nBinary files a/src/Apps/W1/Quality Management/app/src/Reports/QltyNonConformance.docx and b/src/Apps/W1/Quality Management/app/src/Reports/QltyNonConformance.docx differ\ndiff --git a/src/Apps/W1/Quality Management/app/src/Setup/QltyManagementSetup.Table.al b/src/Apps/W1/Quality Management/app/src/Setup/QltyManagementSetup.Table.al\nindex 4e8cecbbef..492e58410e 100644\n--- a/src/Apps/W1/Quality Management/app/src/Setup/QltyManagementSetup.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Setup/QltyManagementSetup.Table.al\n@@ -43,7 +43,7 @@ table 20400 \"Qlty. Management Setup\"\n field(4; \"Inspection Creation Option\"; Enum \"Qlty. Inspect. Creation Option\")\n {\n Caption = 'Inspection Creation Option';\n- ToolTip = 'Specifies how the system handles inspection creation when existing inspections exist.';\n+ ToolTip = 'Specifies handling of inspection creation when existing inspections are found.';\n InitValue = \"Use existing open inspection if available\";\n }\n field(5; \"Inspection Search Criteria\"; Enum \"Qlty. Inspect. Search Criteria\")\ndiff --git a/src/Apps/W1/Quality Management/app/src/Setup/SetupGuide/QltyGuidedExperience.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Setup/SetupGuide/QltyGuidedExperience.Codeunit.al\nindex 9395d22992..f0e5f37d38 100644\n--- a/src/Apps/W1/Quality Management/app/src/Setup/SetupGuide/QltyGuidedExperience.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/app/src/Setup/SetupGuide/QltyGuidedExperience.Codeunit.al\n@@ -28,13 +28,13 @@ codeunit 20419 \"Qlty. Guided Experience\"\n DemoDataDescriptionTxt: Label 'Install or explore Contoso demo data for Quality Management with sample quality tests, templates, generation rules, and inspections. This lets you learn how quality checks work without setting up your own data.';\n QualityResultsShortTitleTxt: Label 'Inspection results';\n QualityResultsTitleTxt: Label 'Set up quality inspection results';\n- QualityResultsDescriptionTxt: Label 'Define possible outcomes for quality inspections, like Pass, Fail, or In Progress. Create custom results and set priorities to match your organization''s standards. These results control how inspections are evaluated and how items are blocked or released.';\n+ QualityResultsDescriptionTxt: Label 'Define custom grades for quality inspections, to match your organization''s standards. You can decide evaluation priorities and set conditions for allowed transactions.';\n QualityTestsShortTitleTxt: Label 'Quality tests';\n QualityTestsTitleTxt: Label 'Understand quality tests';\n QualityTestsDescriptionTxt: Label 'Quality tests define what is measured. Visit the Quality Tests list to see available tests, then open a test card to review parameters, limits, and expected values used during inspections.';\n QualityTemplatesShortTitleTxt: Label 'Quality templates';\n QualityTemplatesTitleTxt: Label 'Reuse inspection templates';\n- QualityTemplatesDescriptionTxt: Label 'With templates you can group and reuse quality tests so you can apply consistent inspection standards across items, processes, or scenarios. From the list you can create a new template card to understand its structure and purpose.';\n+ QualityTemplatesDescriptionTxt: Label 'With templates you can group and reuse quality tests to ensure consistent inspection standards. Try creating a new template card to understand its structure and purpose.';\n GenerationRulesShortTitleTxt: Label 'Generation rules';\n GenerationRulesTitleTxt: Label 'Set up inspection generation rules';\n GenerationRulesDescriptionTxt: Label 'Inspection generation rules define when quality inspections are created automatically, such as during receiving, production, or assembly.';\n", "FAIL_TO_PASS": [{"codeunitID": 139965, "functionName": ["TemplateLine_ExpressionFormulaUpdatedWhenTestCodeChanges", "TemplateLine_ExpressionFormulaEmptyWhenTestHasNoFormula", "TemplateLine_ExpressionFormulaCopiedFromTest", "TestTable_DefaultValueNotAllowedForTextExpression"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\nindex 38a8889c60..6df2e749cc 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTest.Table.al\n@@ -154,13 +154,16 @@ table 20401 \"Qlty. Test\"\n \n trigger OnValidate()\n begin\n+ if (Rec.\"Default Value\" <> '') and (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Text Expression\"]) then\n+ Error(DefaultValueNotAllowedForTextExpressionErr);\n+\n Rec.ValidateAllowableValuesOnDefault();\n end;\n }\n field(17; \"Case Sensitive\"; Enum \"Qlty. Case Sensitivity\")\n {\n Caption = 'Case Sensitivity';\n- ToolTip = 'Specifies if case sensitivity will be enabled for text-based fields.';\n+ ToolTip = 'Specifies if case sensitivity will be enabled for text-based tests.';\n }\n field(18; \"Expression Formula\"; Text[500])\n {\n@@ -170,7 +173,7 @@ table 20401 \"Qlty. Test\"\n trigger OnValidate()\n begin\n if (Rec.\"Expression Formula\" <> '') and not (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Text Expression\"]) then\n- Error(OnlyFieldExpressionErr);\n+ Error(ExpressionFormulaOnlyForTextExpressionErr);\n end;\n }\n field(22; \"Unit of Measure Code\"; Code[10])\n@@ -204,7 +207,8 @@ table 20401 \"Qlty. Test\"\n GenericTestTok: Label 'MYTEST', Locked = true;\n ThereIsNoResultErr: Label 'There is no result called \"%1\". Please add the result, or change the existing result conditions.', Comment = '%1=the result';\n ReviewResultsErr: Label 'Advanced configuration required. Please review the result configurations for test \"%1\", for result \"%2\".', Comment = '%1=the test, %2=the result';\n- OnlyFieldExpressionErr: Label 'The Expression Formula can only be used with fields that are a type of Expression';\n+ ExpressionFormulaOnlyForTextExpressionErr: Label 'The Expression Formula can only be used with tests that are a type of Text Expression';\n+ DefaultValueNotAllowedForTextExpressionErr: Label 'The Default Value cannot be set on tests that are a type of Text Expression. The value is computed from the Expression Formula.';\n BooleanChoiceListLbl: Label 'No,Yes';\n ExistingInspectionErr: Label 'The test %1 exists on %2 inspections (such as %3 with template %4). The test cannot be deleted if it is being used on a quality inspection.', Comment = '%1=the test, %2=count of inspections, %3=one example inspection, %4=example template.';\n DeleteQst: Label 'The test %3 exists on %1 Quality Inspection Template(s) (such as template %2) that will be deleted. Do you wish to proceed?', Comment = '%1 = the lines, %2= the Template Code, %3=the test';\n@@ -601,7 +605,7 @@ table 20401 \"Qlty. Test\"\n Expression: Text;\n begin\n if not (Rec.\"Test Value Type\" in [Rec.\"Test Value Type\"::\"Value Type Text Expression\"]) then\n- Error(OnlyFieldExpressionErr);\n+ Error(ExpressionFormulaOnlyForTextExpressionErr);\n \n Expression := Rec.\"Expression Formula\";\n \ndiff --git a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTestCard.Page.al b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTestCard.Page.al\nindex 95c568a137..4418f7a53c 100644\n--- a/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTestCard.Page.al\n+++ b/src/Apps/W1/Quality Management/app/src/Configuration/Template/Test/QltyTestCard.Page.al\n@@ -77,6 +77,8 @@ page 20479 \"Qlty. Test Card\"\n }\n field(\"Default Value\"; Rec.\"Default Value\")\n {\n+ Editable = not IsExpressionFormulaEditable;\n+\n trigger OnAssistEdit()\n begin\n Rec.AssistEditDefaultValue();\n@@ -652,7 +654,7 @@ page 20479 \"Qlty. Test Card\"\n \n EditableResult := (Rec.Code <> '') and (CurrPage.Editable) and (Visible1) and (MatrixArrayCaptionSet[1] <> '');\n \n- IsExpressionFormulaEditable := (Rec.\"Test Value Type\" = Rec.\"Test Value Type\"::\"Value Type Text Expression\");\n+ IsExpressionFormulaEditable := Rec.\"Test Value Type\" = Rec.\"Test Value Type\"::\"Value Type Text Expression\";\n end;\n \n local procedure UpdateMatrixDataCondition(Matrix: Integer)\ndiff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsMoreTests.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsMoreTests.Codeunit.al\nindex 70e318c1ef..69d0029499 100644\n--- a/src/Apps/W1/Quality Management/test/src/QltyTestsMoreTests.Codeunit.al\n+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsMoreTests.Codeunit.al\n@@ -61,7 +61,7 @@ codeunit 139965 \"Qlty. Tests - More Tests\"\n DefaultScheduleGroupTok: Label 'QM', Locked = true;\n ExpressionFormulaTok: Label '[No.]';\n TestValueTypeChangeErrInfoMsg: Label 'Consider replacing this test in the template with a new one, or deleting existing inspections (if allowed). The test was last used on Inspection %1, Re-inspection %2.', Comment = '%1 = Quality Inspection No., %2 = Re-inspection No.';\n- OnlyFieldExpressionErr: Label 'The Expression Formula can only be used with fields that are a type of Expression';\n+ ExpressionFormulaOnlyForTextExpressionErr: Label 'The Expression Formula can only be used with tests that are a type of Text Expression';\n VendorFilterCountryTok: Label 'WHERE(Country/Region Code=FILTER(CA))', Locked = true;\n VendorFilterNoTok: Label 'WHERE(No.=FILTER(%1))', Comment = '%1 = Vendor No.', Locked = true;\n ThereIsNoResultErr: Label 'There is no result called \"%1\". Please add the result, or change the existing result conditions.', Comment = '%1=the result';\n@@ -105,7 +105,7 @@ codeunit 139965 \"Qlty. Tests - More Tests\"\n asserterror ToLoadQltyTest.Validate(\"Expression Formula\", ExpressionFormulaTok);\n \n // [THEN] An error is raised indicating Expression Formula is only for Expression test value types\n- LibraryAssert.ExpectedError(OnlyFieldExpressionErr);\n+ LibraryAssert.ExpectedError(ExpressionFormulaOnlyForTextExpressionErr);\n end;\n \n [Test]\n@@ -612,7 +612,7 @@ codeunit 139965 \"Qlty. Tests - More Tests\"\n asserterror ConfigurationToLoadQltyInspectionTemplateLine.Validate(\"Expression Formula\", ExpressionFormulaTok);\n \n // [THEN] An error is raised indicating Expression Formula is only for Expression field types\n- LibraryAssert.ExpectedError(OnlyFieldExpressionErr);\n+ LibraryAssert.ExpectedError(ExpressionFormulaOnlyForTextExpressionErr);\n end;\n \n [Test]\n@@ -2271,6 +2271,139 @@ codeunit 139965 \"Qlty. Tests - More Tests\"\n LibraryAssert.AreEqual(LotNo, QltyInspectionHeader.\"Source Lot No.\", 'Inspection should have the correct lot number.');\n end;\n \n+ [Test]\n+ procedure TestTable_DefaultValueNotAllowedForTextExpression()\n+ var\n+ QltyTest: Record \"Qlty. Test\";\n+ TestCode: Text;\n+ begin\n+ // [SCENARIO] Default Value cannot be set on tests that are a type of Text Expression\n+ Initialize();\n+\n+ // [GIVEN] A random test code is generated\n+ QltyInspectionUtility.GenerateRandomCharacters(20, TestCode);\n+\n+ // [GIVEN] A new quality test with Test Value Type \"Value Type Text Expression\" is created\n+ QltyTest.Validate(Code, CopyStr(TestCode, 1, MaxStrLen(QltyTest.Code)));\n+ QltyTest.Validate(Description, LibraryUtility.GenerateRandomText(MaxStrLen(QltyTest.Description)));\n+ QltyTest.Validate(\"Test Value Type\", QltyTest.\"Test Value Type\"::\"Value Type Text Expression\");\n+ QltyTest.Insert();\n+\n+ // [WHEN] Attempting to set Default Value on a Text Expression test\n+ asserterror QltyTest.Validate(\"Default Value\", 'some text');\n+\n+ // [THEN] An error is raised indicating Default Value is not allowed for Text Expression tests\n+ LibraryAssert.ExpectedError('The Default Value cannot be set on tests that are a type of Text Expression.');\n+ end;\n+\n+ [Test]\n+ procedure TemplateLine_ExpressionFormulaCopiedFromTest()\n+ var\n+ QltyTest: Record \"Qlty. Test\";\n+ QltyInspectionTemplateHdr: Record \"Qlty. Inspection Template Hdr.\";\n+ QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\";\n+ TestCode: Text;\n+ begin\n+ // [SCENARIO] Expression Formula is copied from the test to the template line when the test is added\n+ Initialize();\n+\n+ // [GIVEN] A random test code is generated\n+ QltyInspectionUtility.GenerateRandomCharacters(20, TestCode);\n+\n+ // [GIVEN] A quality test with Test Value Type \"Value Type Text Expression\" and an Expression Formula is created\n+ QltyTest.Validate(Code, CopyStr(TestCode, 1, MaxStrLen(QltyTest.Code)));\n+ QltyTest.Validate(Description, LibraryUtility.GenerateRandomText(MaxStrLen(QltyTest.Description)));\n+ QltyTest.Validate(\"Test Value Type\", QltyTest.\"Test Value Type\"::\"Value Type Text Expression\");\n+ QltyTest.Insert();\n+ QltyTest.Validate(\"Expression Formula\", ExpressionFormulaTok);\n+ QltyTest.Modify();\n+\n+ // [GIVEN] A template is created\n+ QltyInspectionUtility.CreateTemplate(QltyInspectionTemplateHdr, 0);\n+\n+ // [WHEN] A template line is created with the test code\n+ QltyInspectionTemplateLine.Init();\n+ QltyInspectionTemplateLine.\"Template Code\" := QltyInspectionTemplateHdr.Code;\n+ QltyInspectionTemplateLine.InitLineNoIfNeeded();\n+ QltyInspectionTemplateLine.Validate(\"Test Code\", QltyTest.Code);\n+ QltyInspectionTemplateLine.Insert(true);\n+\n+ // [THEN] The Expression Formula is copied from the test to the template line\n+ LibraryAssert.AreEqual(ExpressionFormulaTok, QltyInspectionTemplateLine.\"Expression Formula\", 'Expression Formula should be copied from the test to the template line.');\n+ end;\n+\n+ [Test]\n+ procedure TemplateLine_ExpressionFormulaEmptyWhenTestHasNoFormula()\n+ var\n+ QltyTest: Record \"Qlty. Test\";\n+ QltyInspectionTemplateHdr: Record \"Qlty. Inspection Template Hdr.\";\n+ QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\";\n+ TestCode: Text;\n+ begin\n+ // [SCENARIO] Expression Formula on template line is empty when the test has no formula\n+ Initialize();\n+\n+ // [GIVEN] A random test code is generated\n+ QltyInspectionUtility.GenerateRandomCharacters(20, TestCode);\n+\n+ // [GIVEN] A quality test with Test Value Type \"Value Type Text Expression\" but no Expression Formula is created\n+ QltyTest.Validate(Code, CopyStr(TestCode, 1, MaxStrLen(QltyTest.Code)));\n+ QltyTest.Validate(Description, LibraryUtility.GenerateRandomText(MaxStrLen(QltyTest.Description)));\n+ QltyTest.Validate(\"Test Value Type\", QltyTest.\"Test Value Type\"::\"Value Type Text Expression\");\n+ QltyTest.Insert();\n+\n+ // [GIVEN] A template is created\n+ QltyInspectionUtility.CreateTemplate(QltyInspectionTemplateHdr, 0);\n+\n+ // [WHEN] A template line is created with the test code\n+ QltyInspectionTemplateLine.Init();\n+ QltyInspectionTemplateLine.\"Template Code\" := QltyInspectionTemplateHdr.Code;\n+ QltyInspectionTemplateLine.InitLineNoIfNeeded();\n+ QltyInspectionTemplateLine.Validate(\"Test Code\", QltyTest.Code);\n+ QltyInspectionTemplateLine.Insert(true);\n+\n+ // [THEN] The Expression Formula on the template line is empty\n+ LibraryAssert.AreEqual('', QltyInspectionTemplateLine.\"Expression Formula\", 'Expression Formula should be empty when the test has no formula.');\n+ end;\n+\n+ [Test]\n+ procedure TemplateLine_ExpressionFormulaUpdatedWhenTestCodeChanges()\n+ var\n+ QltyTest1: Record \"Qlty. Test\";\n+ QltyTest2: Record \"Qlty. Test\";\n+ QltyInspectionTemplateHdr: Record \"Qlty. Inspection Template Hdr.\";\n+ QltyInspectionTemplateLine: Record \"Qlty. Inspection Template Line\";\n+ ExpressionFormula2Tok: Label '[Source Item No.]', Locked = true;\n+ begin\n+ // [SCENARIO] Expression Formula is updated when the Test Code on a template line is changed to a different test\n+ Initialize();\n+\n+ // [GIVEN] A first quality test with an Expression Formula is created\n+ QltyInspectionUtility.CreateTest(QltyTest1, QltyTest1.\"Test Value Type\"::\"Value Type Text Expression\");\n+ QltyTest1.Validate(\"Expression Formula\", ExpressionFormulaTok);\n+ QltyTest1.Modify();\n+\n+ // [GIVEN] A second quality test with a different Expression Formula is created\n+ QltyInspectionUtility.CreateTest(QltyTest2, QltyTest2.\"Test Value Type\"::\"Value Type Text Expression\");\n+ QltyTest2.Validate(\"Expression Formula\", ExpressionFormula2Tok);\n+ QltyTest2.Modify();\n+\n+ // [GIVEN] A template is created with the first test\n+ QltyInspectionUtility.CreateTemplate(QltyInspectionTemplateHdr, 0);\n+ QltyInspectionTemplateLine.Init();\n+ QltyInspectionTemplateLine.\"Template Code\" := QltyInspectionTemplateHdr.Code;\n+ QltyInspectionTemplateLine.InitLineNoIfNeeded();\n+ QltyInspectionTemplateLine.Validate(\"Test Code\", QltyTest1.Code);\n+ QltyInspectionTemplateLine.Insert(true);\n+\n+ // [WHEN] The Test Code on the template line is changed to the second test\n+ QltyInspectionTemplateLine.Validate(\"Test Code\", QltyTest2.Code);\n+ QltyInspectionTemplateLine.Modify(true);\n+\n+ // [THEN] The Expression Formula is updated to the second test's formula\n+ LibraryAssert.AreEqual(ExpressionFormula2Tok, QltyInspectionTemplateLine.\"Expression Formula\", 'Expression Formula should be updated when the test code is changed.');\n+ end;\n+\n local procedure Initialize()\n begin\n if IsInitialized then\n"} {"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8423", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-06-02T14:24:52Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\ExcelReports\\App", "src\\Apps\\W1\\ExcelReports\\Test"], "patch": "diff --git a/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccPayableExcel.Report.al b/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccPayableExcel.Report.al\nindex a09b3759b3..7dc8662512 100644\n--- a/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccPayableExcel.Report.al\n+++ b/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccPayableExcel.Report.al\n@@ -84,8 +84,9 @@ report 4403 \"EXR Aged Acc Payable Excel\"\n {\n IncludeCaption = true;\n }\n- column(CurrencyCode; CurrencyCodeDisplayCode)\n+ column(CurrencyCode; \"Currency Code\")\n {\n+ IncludeCaption = true;\n }\n column(PostingDate; \"Posting Date\")\n {\n@@ -126,11 +127,7 @@ report 4403 \"EXR Aged Acc Payable Excel\"\n Clear(AgingData);\n AgingData.DeleteAll();\n InsertAgingData(VendorAgingData);\n-\n- if AgingData.\"Currency Code\" = '' then\n- CurrencyCodeDisplayCode := GeneralLedgerSetup.GetCurrencyCode('')\n- else\n- CurrencyCodeDisplayCode := AgingData.\"Currency Code\";\n+ CurrencyCodeDisplayCode := AgingData.\"Currency Code\";\n end;\n }\n \n@@ -271,7 +268,6 @@ report 4403 \"EXR Aged Acc Payable Excel\"\n DueByCurrencies = 'Due by Currencies', MaxLength = 31, Comment = 'Excel worksheet name.';\n OpenByFCY = 'Open by (FCY)';\n DataRetrieved = 'Data retrieved:';\n- CurrencyCodeDisplay = 'Currency Code';\n AgedAsOf = 'Aged as of:';\n AgedAccountsPayable = 'Aged Accounts Payable';\n AgedAccountsPayablePrint = 'Aged Accounts Payable (Print)', MaxLength = 31, Comment = 'Excel worksheet name.';\n@@ -322,6 +318,9 @@ report 4403 \"EXR Aged Acc Payable Excel\"\n if PeriodCount = 0 then\n PeriodCount := 5;\n \n+ if not GeneralLedgerSetup.Get() then\n+ Clear(GeneralLedgerSetup);\n+\n WorkingEndDate := EndingDate;\n WorkingStartDate := CalcDate(PeriodLength, WorkingEndDate);\n repeat\n@@ -366,7 +365,10 @@ report 4403 \"EXR Aged Acc Payable Excel\"\n AgingData.\"Document Type\" := VendorLedgerEntry.\"Document Type\";\n AgingData.\"Dimension 1 Code\" := VendorLedgerEntry.\"Global Dimension 1 Code\";\n AgingData.\"Dimension 2 Code\" := VendorLedgerEntry.\"Global Dimension 2 Code\";\n- AgingData.\"Currency Code\" := VendorLedgerEntry.\"Currency Code\";\n+ if VendorLedgerEntry.\"Currency Code\" = '' then\n+ AgingData.\"Currency Code\" := GeneralLedgerSetup.GetCurrencyCode('')\n+ else\n+ AgingData.\"Currency Code\" := VendorLedgerEntry.\"Currency Code\";\n AgingData.\"Posting Date\" := VendorLedgerEntry.\"Posting Date\";\n AgingData.\"Document Date\" := VendorLedgerEntry.\"Document Date\";\n AgingData.\"Due Date\" := VendorLedgerEntry.\"Due Date\";\ndiff --git a/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccountsRecExcel.Report.al b/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccountsRecExcel.Report.al\nindex b16e1ca692..e07ca9a845 100644\n--- a/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccountsRecExcel.Report.al\n+++ b/src/Apps/W1/ExcelReports/App/src/Financials/EXRAgedAccountsRecExcel.Report.al\n@@ -83,8 +83,9 @@ report 4402 \"EXR Aged Accounts Rec Excel\"\n {\n IncludeCaption = true;\n }\n- column(CurrencyCode; CurrencyCodeDisplayCode)\n+ column(CurrencyCode; \"Currency Code\")\n {\n+ IncludeCaption = true;\n }\n column(PostingDate; \"Posting Date\")\n {\n@@ -125,11 +126,7 @@ report 4402 \"EXR Aged Accounts Rec Excel\"\n Clear(AgingData);\n AgingData.DeleteAll();\n InsertAgingData(CustomerAgingData);\n-\n- if AgingData.\"Currency Code\" = '' then\n- CurrencyCodeDisplayCode := GeneralLedgerSetup.GetCurrencyCode('')\n- else\n- CurrencyCodeDisplayCode := AgingData.\"Currency Code\";\n+ CurrencyCodeDisplayCode := AgingData.\"Currency Code\";\n end;\n }\n \n@@ -270,7 +267,6 @@ report 4402 \"EXR Aged Accounts Rec Excel\"\n DueByCurrencies = 'Due by Currencies', MaxLength = 31, Comment = 'Excel worksheet name.';\n OpenByFCY = 'Open by (FCY)';\n DataRetrieved = 'Data retrieved:';\n- CurrencyCodeDisplay = 'Currency Code';\n AgedAsOf = 'Aged as of:';\n AgedAccountsReceivable = 'Aged Accounts Receivable';\n AgedAccountsReceivablePrint = 'Aged Accounts Rec. (Print)', MaxLength = 31, Comment = 'Excel worksheet name.';\n@@ -321,6 +317,9 @@ report 4402 \"EXR Aged Accounts Rec Excel\"\n if PeriodCount = 0 then\n PeriodCount := 5;\n \n+ if not GeneralLedgerSetup.Get() then\n+ Clear(GeneralLedgerSetup);\n+\n WorkingEndDate := EndingDate;\n WorkingStartDate := CalcDate(PeriodLength, WorkingEndDate);\n repeat\n@@ -365,7 +364,10 @@ report 4402 \"EXR Aged Accounts Rec Excel\"\n AgingData.\"Document Type\" := CustLedgerEntry.\"Document Type\";\n AgingData.\"Dimension 1 Code\" := CustLedgerEntry.\"Global Dimension 1 Code\";\n AgingData.\"Dimension 2 Code\" := CustLedgerEntry.\"Global Dimension 2 Code\";\n- AgingData.\"Currency Code\" := CustLedgerEntry.\"Currency Code\";\n+ if CustLedgerEntry.\"Currency Code\" = '' then\n+ AgingData.\"Currency Code\" := GeneralLedgerSetup.GetCurrencyCode('')\n+ else\n+ AgingData.\"Currency Code\" := CustLedgerEntry.\"Currency Code\";\n AgingData.\"Posting Date\" := CustLedgerEntry.\"Posting Date\";\n AgingData.\"Document Date\" := CustLedgerEntry.\"Document Date\";\n AgingData.\"Due Date\" := CustLedgerEntry.\"Due Date\";\n", "FAIL_TO_PASS": [{"codeunitID": 139555, "functionName": ["AgedAccountsPayableReportAgesByPostingDate", "AgedAccountsPayableRendersCurrencyCodePerEntry", "AgedAccountsPayableExportsDocumentTypeAndNo", "AgedAccountsRecExportsDocumentTypeAndNo", "AgedAccountsRecRendersCurrencyCodePerEntry"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/ExcelReports/Test/app.json b/src/Apps/W1/ExcelReports/Test/app.json\nindex 826a16204e..b08abb1f27 100644\n--- a/src/Apps/W1/ExcelReports/Test/app.json\n+++ b/src/Apps/W1/ExcelReports/Test/app.json\n@@ -38,6 +38,10 @@\n {\n \"from\": 139543,\n \"to\": 139547\n+ },\n+ {\n+ \"from\": 139555,\n+ \"to\": 139555\n }\n ],\n \"resourceExposurePolicy\": {\ndiff --git a/src/Apps/W1/ExcelReports/Test/src/AgedAccountsExcelReports.Codeunit.al b/src/Apps/W1/ExcelReports/Test/src/AgedAccountsExcelReports.Codeunit.al\nnew file mode 100644\nindex 0000000000..6442d2d2a8\n--- /dev/null\n+++ b/src/Apps/W1/ExcelReports/Test/src/AgedAccountsExcelReports.Codeunit.al\n@@ -0,0 +1,391 @@\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+\n+namespace Microsoft.Finance.ExcelReports.Test;\n+\n+using Microsoft.Finance.ExcelReports;\n+using Microsoft.Finance.GeneralLedger.Journal;\n+using Microsoft.Finance.GeneralLedger.Setup;\n+using Microsoft.Purchases.Payables;\n+using Microsoft.Purchases.Vendor;\n+using Microsoft.Sales.Customer;\n+using Microsoft.Sales.Receivables;\n+\n+codeunit 139555 \"Aged Accounts Excel Reports\"\n+{\n+ Subtype = Test;\n+ RequiredTestIsolation = Disabled;\n+ TestPermissions = Disabled;\n+\n+ var\n+ LibraryRandom: Codeunit \"Library - Random\";\n+ LibraryReportDataset: Codeunit \"Library - Report Dataset\";\n+ Assert: Codeunit Assert;\n+ DocumentTypeShouldBeInvoiceErr: Label 'Document Type should be Invoice';\n+ DocumentNoShouldMatchErr: Label 'Document No should match the ledger entry';\n+\n+ [Test]\n+ [HandlerFunctions('EXRAgedAccPayableExcelHandler')]\n+ procedure AgedAccountsPayableExportsDocumentTypeAndNo()\n+ var\n+ Vendor: Record Vendor;\n+ VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ Variant: Variant;\n+ RequestPageXml: Text;\n+ ReportDocumentType: Text;\n+ ReportDocumentNo: Text;\n+ begin\n+ // [FEATURE] [AI test]\n+ // [SCENARIO 622247] Aged Accounts Payable Excel report exports Document Type and Document No fields correctly for Invoice entries\n+ InitializeAgingData();\n+\n+ // [GIVEN] Vendor \"V\" with an open vendor ledger entry of type Invoice\n+ // Create vendor directly to avoid VAT posting setup requirements in some localizations\n+ CreateMinimalVendor(Vendor);\n+ CreateVendorLedgerEntry(VendorLedgerEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n+ Commit();\n+\n+ // [WHEN] Running the Aged Accounts Payable Excel report\n+ RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Acc Payable Excel\", RequestPageXml);\n+ LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Acc Payable Excel\", Variant, RequestPageXml);\n+\n+ // [THEN] The exported data contains the Document Type \"Invoice\" and the correct Document No\n+ LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n+ Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n+ LibraryReportDataset.GetNextRow();\n+ LibraryReportDataset.FindCurrentRowValue('DocumentType', Variant);\n+ ReportDocumentType := Variant;\n+ Assert.AreEqual(Format(\"Gen. Journal Document Type\"::Invoice), ReportDocumentType, DocumentTypeShouldBeInvoiceErr);\n+ LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n+ ReportDocumentNo := Variant;\n+ Assert.AreEqual(VendorLedgerEntry.\"Document No.\", ReportDocumentNo, DocumentNoShouldMatchErr);\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('EXRAgedAccountsRecExcelHandler')]\n+ procedure AgedAccountsRecExportsDocumentTypeAndNo()\n+ var\n+ Customer: Record Customer;\n+ CustLedgerEntry: Record \"Cust. Ledger Entry\";\n+ Variant: Variant;\n+ RequestPageXml: Text;\n+ ReportDocumentType: Text;\n+ ReportDocumentNo: Text;\n+ begin\n+ // [FEATURE] [AI test]\n+ // [SCENARIO 622247] Aged Accounts Receivable Excel report exports Document Type and Document No fields correctly for Invoice entries\n+ InitializeAgingData();\n+\n+ // [GIVEN] Customer \"C\" with an open customer ledger entry of type Invoice\n+ // Create customer directly to avoid VAT posting setup requirements in some localizations\n+ CreateMinimalCustomer(Customer);\n+ CreateCustLedgerEntry(CustLedgerEntry, Customer.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n+ Commit();\n+\n+ // [WHEN] Running the Aged Accounts Receivable Excel report\n+ RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Accounts Rec Excel\", RequestPageXml);\n+ LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Accounts Rec Excel\", Variant, RequestPageXml);\n+\n+ // [THEN] The exported data contains the Document Type \"Invoice\" and the correct Document No\n+ LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n+ Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n+ LibraryReportDataset.GetNextRow();\n+ LibraryReportDataset.FindCurrentRowValue('DocumentType', Variant);\n+ ReportDocumentType := Variant;\n+ Assert.AreEqual(Format(\"Gen. Journal Document Type\"::Invoice), ReportDocumentType, DocumentTypeShouldBeInvoiceErr);\n+ LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n+ ReportDocumentNo := Variant;\n+ Assert.AreEqual(CustLedgerEntry.\"Document No.\", ReportDocumentNo, DocumentNoShouldMatchErr);\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('EXRAgedAccPayablePostingDateHandler')]\n+ procedure AgedAccountsPayableReportAgesByPostingDate()\n+ var\n+ Vendor: Record Vendor;\n+ VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ Variant: Variant;\n+ RequestPageXml: Text;\n+ ReportingDateText: Text;\n+ ReportingDate: Date;\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO] Aged Accounts Payable report uses Posting Date as Reporting Date when aging by Posting Date\n+ InitializeAgingData();\n+\n+ // [GIVEN] Vendor \"V\" with an open ledger entry where Posting Date, Document Date, and Due Date are distinct\n+ CreateMinimalVendor(Vendor);\n+ CreateVendorLedgerEntry(VendorLedgerEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n+ VendorLedgerEntry.\"Document Date\" := WorkDate() - 10;\n+ VendorLedgerEntry.Modify();\n+ Commit();\n+\n+ // [WHEN] Running the Aged Accounts Payable Excel report with Aging By = Posting Date\n+ RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Acc Payable Excel\", RequestPageXml);\n+ LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Acc Payable Excel\", Variant, RequestPageXml);\n+\n+ // [THEN] The Reporting Date matches the Posting Date of the vendor ledger entry\n+ LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n+ Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n+ LibraryReportDataset.GetNextRow();\n+ LibraryReportDataset.FindCurrentRowValue('ReportingDate', Variant);\n+ ReportingDateText := Variant;\n+ Evaluate(ReportingDate, ReportingDateText);\n+ Assert.AreEqual(VendorLedgerEntry.\"Posting Date\", ReportingDate, 'Reporting Date should match the Posting Date when aging by Posting Date');\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('EXRAgedAccountsRecExcelHandler')]\n+ procedure AgedAccountsRecRendersCurrencyCodePerEntry()\n+ var\n+ Customer: Record Customer;\n+ GeneralLedgerSetup: Record \"General Ledger Setup\";\n+ UsdEntry, LcyEntry : Record \"Cust. Ledger Entry\";\n+ Variant: Variant;\n+ RequestPageXml: Text;\n+ LcyCode: Code[10];\n+ ForeignCurrencyCode: Code[10];\n+ DocNo, CurrencyCode : Text;\n+ i: Integer;\n+ UsdRowSeen, LcyRowSeen : Boolean;\n+ begin\n+ // [SCENARIO 637444] Aged Accounts Receivable Excel renders each row's own Currency Code, not a single per-customer value\n+ InitializeAgingData();\n+\n+ // [GIVEN] G/L Setup with a distinct LCY Code\n+ LcyCode := 'LCY';\n+ ForeignCurrencyCode := 'USD';\n+ if not GeneralLedgerSetup.Get() then\n+ GeneralLedgerSetup.Insert();\n+ GeneralLedgerSetup.\"LCY Code\" := LcyCode;\n+ GeneralLedgerSetup.Modify();\n+\n+ // [GIVEN] A customer with one foreign-currency entry and one LCY (empty Currency Code) entry\n+ CreateMinimalCustomer(Customer);\n+ CreateCustLedgerEntry(UsdEntry, Customer.\"No.\", \"Gen. Journal Document Type\"::Invoice, ForeignCurrencyCode);\n+ CreateCustLedgerEntry(LcyEntry, Customer.\"No.\", \"Gen. Journal Document Type\"::Invoice, '');\n+ Commit();\n+\n+ // [WHEN] Running the Aged Accounts Receivable Excel report\n+ RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Accounts Rec Excel\", RequestPageXml);\n+ LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Accounts Rec Excel\", Variant, RequestPageXml);\n+\n+ // [THEN] The foreign-currency row shows the foreign code and the LCY row shows the LCY code\n+ LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n+ Assert.AreEqual(2, LibraryReportDataset.RowCount(), 'Two aging entries should be exported');\n+ for i := 1 to 2 do begin\n+ LibraryReportDataset.GetNextRow();\n+ LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n+ DocNo := Variant;\n+ LibraryReportDataset.FindCurrentRowValue('CurrencyCode', Variant);\n+ CurrencyCode := Variant;\n+ if DocNo = UsdEntry.\"Document No.\" then begin\n+ Assert.AreEqual(ForeignCurrencyCode, CurrencyCode, 'Foreign-currency row should show its own currency code');\n+ UsdRowSeen := true;\n+ end else\n+ if DocNo = LcyEntry.\"Document No.\" then begin\n+ Assert.AreEqual(LcyCode, CurrencyCode, 'LCY (empty Currency Code) row should fall back to G/L Setup LCY Code');\n+ LcyRowSeen := true;\n+ end;\n+ end;\n+ Assert.IsTrue(UsdRowSeen, 'Foreign-currency row should be present');\n+ Assert.IsTrue(LcyRowSeen, 'LCY row should be present');\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('EXRAgedAccPayableExcelHandler')]\n+ procedure AgedAccountsPayableRendersCurrencyCodePerEntry()\n+ var\n+ Vendor: Record Vendor;\n+ GeneralLedgerSetup: Record \"General Ledger Setup\";\n+ UsdEntry, LcyEntry : Record \"Vendor Ledger Entry\";\n+ Variant: Variant;\n+ RequestPageXml: Text;\n+ LcyCode: Code[10];\n+ ForeignCurrencyCode: Code[10];\n+ DocNo, CurrencyCode : Text;\n+ i: Integer;\n+ UsdRowSeen, LcyRowSeen : Boolean;\n+ begin\n+ // [SCENARIO 637444] Aged Accounts Payable Excel renders each row's own Currency Code, not a single per-vendor value\n+ InitializeAgingData();\n+\n+ // [GIVEN] G/L Setup with a distinct LCY Code\n+ LcyCode := 'LCY';\n+ ForeignCurrencyCode := 'USD';\n+ if not GeneralLedgerSetup.Get() then\n+ GeneralLedgerSetup.Insert();\n+ GeneralLedgerSetup.\"LCY Code\" := LcyCode;\n+ GeneralLedgerSetup.Modify();\n+\n+ // [GIVEN] A vendor with one foreign-currency entry and one LCY (empty Currency Code) entry\n+ CreateMinimalVendor(Vendor);\n+ CreateVendorLedgerEntry(UsdEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice, ForeignCurrencyCode);\n+ CreateVendorLedgerEntry(LcyEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice, '');\n+ Commit();\n+\n+ // [WHEN] Running the Aged Accounts Payable Excel report\n+ RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Acc Payable Excel\", RequestPageXml);\n+ LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Acc Payable Excel\", Variant, RequestPageXml);\n+\n+ // [THEN] The foreign-currency row shows the foreign code and the LCY row shows the LCY code\n+ LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n+ Assert.AreEqual(2, LibraryReportDataset.RowCount(), 'Two aging entries should be exported');\n+ for i := 1 to 2 do begin\n+ LibraryReportDataset.GetNextRow();\n+ LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n+ DocNo := Variant;\n+ LibraryReportDataset.FindCurrentRowValue('CurrencyCode', Variant);\n+ CurrencyCode := Variant;\n+ if DocNo = UsdEntry.\"Document No.\" then begin\n+ Assert.AreEqual(ForeignCurrencyCode, CurrencyCode, 'Foreign-currency row should show its own currency code');\n+ UsdRowSeen := true;\n+ end else\n+ if DocNo = LcyEntry.\"Document No.\" then begin\n+ Assert.AreEqual(LcyCode, CurrencyCode, 'LCY (empty Currency Code) row should fall back to G/L Setup LCY Code');\n+ LcyRowSeen := true;\n+ end;\n+ end;\n+ Assert.IsTrue(UsdRowSeen, 'Foreign-currency row should be present');\n+ Assert.IsTrue(LcyRowSeen, 'LCY row should be present');\n+ end;\n+\n+ local procedure InitializeAgingData()\n+ var\n+ Vendor: Record Vendor;\n+ Customer: Record Customer;\n+ VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n+ CustLedgerEntry: Record \"Cust. Ledger Entry\";\n+ DetailedVendorLedgEntry: Record \"Detailed Vendor Ledg. Entry\";\n+ DetailedCustLedgEntry: Record \"Detailed Cust. Ledg. Entry\";\n+ begin\n+ DetailedVendorLedgEntry.DeleteAll();\n+ DetailedCustLedgEntry.DeleteAll();\n+ VendorLedgerEntry.DeleteAll();\n+ CustLedgerEntry.DeleteAll();\n+ Vendor.DeleteAll();\n+ Customer.DeleteAll();\n+ end;\n+\n+ local procedure CreateMinimalVendor(var Vendor: Record Vendor)\n+ begin\n+ Vendor.Init();\n+ Vendor.\"No.\" := CopyStr(Format(CreateGuid()), 1, MaxStrLen(Vendor.\"No.\"));\n+ Vendor.Name := Vendor.\"No.\";\n+ Vendor.Insert();\n+ end;\n+\n+ local procedure CreateMinimalCustomer(var Customer: Record Customer)\n+ begin\n+ Customer.Init();\n+ Customer.\"No.\" := CopyStr(Format(CreateGuid()), 1, MaxStrLen(Customer.\"No.\"));\n+ Customer.Name := Customer.\"No.\";\n+ Customer.Insert();\n+ end;\n+\n+ local procedure CreateVendorLedgerEntry(var VendorLedgerEntry: Record \"Vendor Ledger Entry\"; VendorNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\")\n+ begin\n+ CreateVendorLedgerEntry(VendorLedgerEntry, VendorNo, DocumentType, '');\n+ end;\n+\n+ local procedure CreateVendorLedgerEntry(var VendorLedgerEntry: Record \"Vendor Ledger Entry\"; VendorNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\"; CurrencyCode: Code[10])\n+ var\n+ DetailedVendorLedgEntry: Record \"Detailed Vendor Ledg. Entry\";\n+ EntryNo: Integer;\n+ Amount: Decimal;\n+ begin\n+ if VendorLedgerEntry.FindLast() then;\n+ EntryNo := VendorLedgerEntry.\"Entry No.\" + 1;\n+\n+ VendorLedgerEntry.Init();\n+ VendorLedgerEntry.\"Entry No.\" := EntryNo;\n+ VendorLedgerEntry.\"Vendor No.\" := VendorNo;\n+ VendorLedgerEntry.\"Vendor Name\" := VendorNo;\n+ VendorLedgerEntry.\"Document Type\" := DocumentType;\n+ VendorLedgerEntry.\"Document No.\" := 'DOC' + Format(EntryNo);\n+ VendorLedgerEntry.\"Posting Date\" := WorkDate();\n+ VendorLedgerEntry.\"Document Date\" := WorkDate();\n+ VendorLedgerEntry.\"Due Date\" := WorkDate() + 30;\n+ VendorLedgerEntry.\"Currency Code\" := CurrencyCode;\n+ VendorLedgerEntry.Open := true;\n+ VendorLedgerEntry.Insert();\n+\n+ // Create detailed vendor ledger entry for remaining amount\n+ Amount := -LibraryRandom.RandDec(1000, 2);\n+ if DetailedVendorLedgEntry.FindLast() then;\n+ DetailedVendorLedgEntry.Init();\n+ DetailedVendorLedgEntry.\"Entry No.\" := DetailedVendorLedgEntry.\"Entry No.\" + 1;\n+ DetailedVendorLedgEntry.\"Vendor Ledger Entry No.\" := VendorLedgerEntry.\"Entry No.\";\n+ DetailedVendorLedgEntry.\"Vendor No.\" := VendorNo;\n+ DetailedVendorLedgEntry.\"Posting Date\" := WorkDate();\n+ DetailedVendorLedgEntry.\"Entry Type\" := DetailedVendorLedgEntry.\"Entry Type\"::\"Initial Entry\";\n+ DetailedVendorLedgEntry.Amount := Amount;\n+ DetailedVendorLedgEntry.\"Amount (LCY)\" := Amount;\n+ DetailedVendorLedgEntry.Insert();\n+ end;\n+\n+ local procedure CreateCustLedgerEntry(var CustLedgerEntry: Record \"Cust. Ledger Entry\"; CustomerNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\")\n+ begin\n+ CreateCustLedgerEntry(CustLedgerEntry, CustomerNo, DocumentType, '');\n+ end;\n+\n+ local procedure CreateCustLedgerEntry(var CustLedgerEntry: Record \"Cust. Ledger Entry\"; CustomerNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\"; CurrencyCode: Code[10])\n+ var\n+ DetailedCustLedgEntry: Record \"Detailed Cust. Ledg. Entry\";\n+ EntryNo: Integer;\n+ Amount: Decimal;\n+ begin\n+ if CustLedgerEntry.FindLast() then;\n+ EntryNo := CustLedgerEntry.\"Entry No.\" + 1;\n+\n+ CustLedgerEntry.Init();\n+ CustLedgerEntry.\"Entry No.\" := EntryNo;\n+ CustLedgerEntry.\"Customer No.\" := CustomerNo;\n+ CustLedgerEntry.\"Customer Name\" := CustomerNo;\n+ CustLedgerEntry.\"Document Type\" := DocumentType;\n+ CustLedgerEntry.\"Document No.\" := 'DOC' + Format(EntryNo);\n+ CustLedgerEntry.\"Posting Date\" := WorkDate();\n+ CustLedgerEntry.\"Document Date\" := WorkDate();\n+ CustLedgerEntry.\"Due Date\" := WorkDate() + 30;\n+ CustLedgerEntry.\"Currency Code\" := CurrencyCode;\n+ CustLedgerEntry.Open := true;\n+ CustLedgerEntry.Insert();\n+\n+ // Create detailed customer ledger entry for remaining amount\n+ Amount := LibraryRandom.RandDec(1000, 2);\n+ if DetailedCustLedgEntry.FindLast() then;\n+ DetailedCustLedgEntry.Init();\n+ DetailedCustLedgEntry.\"Entry No.\" := DetailedCustLedgEntry.\"Entry No.\" + 1;\n+ DetailedCustLedgEntry.\"Cust. Ledger Entry No.\" := CustLedgerEntry.\"Entry No.\";\n+ DetailedCustLedgEntry.\"Customer No.\" := CustomerNo;\n+ DetailedCustLedgEntry.\"Posting Date\" := WorkDate();\n+ DetailedCustLedgEntry.\"Entry Type\" := DetailedCustLedgEntry.\"Entry Type\"::\"Initial Entry\";\n+ DetailedCustLedgEntry.Amount := Amount;\n+ DetailedCustLedgEntry.\"Amount (LCY)\" := Amount;\n+ DetailedCustLedgEntry.Insert();\n+ end;\n+\n+ [RequestPageHandler]\n+ procedure EXRAgedAccPayableExcelHandler(var EXRAgedAccPayableExcel: TestRequestPage \"EXR Aged Acc Payable Excel\")\n+ begin\n+ EXRAgedAccPayableExcel.AgedAsOfOption.SetValue(WorkDate());\n+ EXRAgedAccPayableExcel.OK().Invoke();\n+ end;\n+\n+ [RequestPageHandler]\n+ procedure EXRAgedAccountsRecExcelHandler(var EXRAgedAccountsRecExcel: TestRequestPage \"EXR Aged Accounts Rec Excel\")\n+ begin\n+ EXRAgedAccountsRecExcel.AgedAsOfOption.SetValue(WorkDate());\n+ EXRAgedAccountsRecExcel.OK().Invoke();\n+ end;\n+\n+ [RequestPageHandler]\n+ procedure EXRAgedAccPayablePostingDateHandler(var EXRAgedAccPayableExcel: TestRequestPage \"EXR Aged Acc Payable Excel\")\n+ begin\n+ EXRAgedAccPayableExcel.AgedAsOfOption.SetValue(WorkDate());\n+ EXRAgedAccPayableExcel.AgingbyOption.SetValue('Posting Date');\n+ EXRAgedAccPayableExcel.OK().Invoke();\n+ end;\n+}\ndiff --git a/src/Apps/W1/ExcelReports/Test/src/TrialBalanceExcelReports.Codeunit.al b/src/Apps/W1/ExcelReports/Test/src/TrialBalanceExcelReports.Codeunit.al\nindex b7bb3a1e21..b2468f3b9a 100644\n--- a/src/Apps/W1/ExcelReports/Test/src/TrialBalanceExcelReports.Codeunit.al\n+++ b/src/Apps/W1/ExcelReports/Test/src/TrialBalanceExcelReports.Codeunit.al\n@@ -10,12 +10,7 @@ using Microsoft.Finance.Dimension;\n using Microsoft.Finance.ExcelReports;\n using Microsoft.Finance.GeneralLedger.Account;\n using Microsoft.Finance.GeneralLedger.Budget;\n-using Microsoft.Finance.GeneralLedger.Journal;\n using Microsoft.Finance.GeneralLedger.Ledger;\n-using Microsoft.Purchases.Payables;\n-using Microsoft.Purchases.Vendor;\n-using Microsoft.Sales.Customer;\n-using Microsoft.Sales.Receivables;\n \n codeunit 139544 \"Trial Balance Excel Reports\"\n {\n@@ -26,11 +21,8 @@ codeunit 139544 \"Trial Balance Excel Reports\"\n \n var\n LibraryERM: Codeunit \"Library - ERM\";\n- LibraryRandom: Codeunit \"Library - Random\";\n LibraryReportDataset: Codeunit \"Library - Report Dataset\";\n Assert: Codeunit Assert;\n- DocumentTypeShouldBeInvoiceErr: Label 'Document Type should be Invoice';\n- DocumentNoShouldMatchErr: Label 'Document No should match the ledger entry';\n \n [Test]\n [HandlerFunctions('EXRTrialBalanceExcelHandler')]\n@@ -667,116 +659,6 @@ codeunit 139544 \"Trial Balance Excel Reports\"\n Assert.AreEqual(0, TempTrialBalanceData.\"Starting Balance\", 'Starting Balance should be zero after closing entries')\n end;\n \n- [Test]\n- [HandlerFunctions('EXRAgedAccPayableExcelHandler')]\n- procedure AgedAccountsPayableExportsDocumentTypeAndNo()\n- var\n- Vendor: Record Vendor;\n- VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n- Variant: Variant;\n- RequestPageXml: Text;\n- ReportDocumentType: Text;\n- ReportDocumentNo: Text;\n- begin\n- // [FEATURE] [AI test]\n- // [SCENARIO 622247] Aged Accounts Payable Excel report exports Document Type and Document No fields correctly for Invoice entries\n- InitializeAgingData();\n-\n- // [GIVEN] Vendor \"V\" with an open vendor ledger entry of type Invoice\n- // Create vendor directly to avoid VAT posting setup requirements in some localizations\n- CreateMinimalVendor(Vendor);\n- CreateVendorLedgerEntry(VendorLedgerEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n- Commit();\n-\n- // [WHEN] Running the Aged Accounts Payable Excel report\n- RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Acc Payable Excel\", RequestPageXml);\n- LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Acc Payable Excel\", Variant, RequestPageXml);\n-\n- // [THEN] The exported data contains the Document Type \"Invoice\" and the correct Document No\n- LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n- Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n- LibraryReportDataset.GetNextRow();\n- LibraryReportDataset.FindCurrentRowValue('DocumentType', Variant);\n- ReportDocumentType := Variant;\n- Assert.AreEqual(Format(\"Gen. Journal Document Type\"::Invoice), ReportDocumentType, DocumentTypeShouldBeInvoiceErr);\n- LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n- ReportDocumentNo := Variant;\n- Assert.AreEqual(VendorLedgerEntry.\"Document No.\", ReportDocumentNo, DocumentNoShouldMatchErr);\n- end;\n-\n- [Test]\n- [HandlerFunctions('EXRAgedAccountsRecExcelHandler')]\n- procedure AgedAccountsRecExportsDocumentTypeAndNo()\n- var\n- Customer: Record Customer;\n- CustLedgerEntry: Record \"Cust. Ledger Entry\";\n- Variant: Variant;\n- RequestPageXml: Text;\n- ReportDocumentType: Text;\n- ReportDocumentNo: Text;\n- begin\n- // [FEATURE] [AI test]\n- // [SCENARIO 622247] Aged Accounts Receivable Excel report exports Document Type and Document No fields correctly for Invoice entries\n- InitializeAgingData();\n-\n- // [GIVEN] Customer \"C\" with an open customer ledger entry of type Invoice\n- // Create customer directly to avoid VAT posting setup requirements in some localizations\n- CreateMinimalCustomer(Customer);\n- CreateCustLedgerEntry(CustLedgerEntry, Customer.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n- Commit();\n-\n- // [WHEN] Running the Aged Accounts Receivable Excel report\n- RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Accounts Rec Excel\", RequestPageXml);\n- LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Accounts Rec Excel\", Variant, RequestPageXml);\n-\n- // [THEN] The exported data contains the Document Type \"Invoice\" and the correct Document No\n- LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n- Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n- LibraryReportDataset.GetNextRow();\n- LibraryReportDataset.FindCurrentRowValue('DocumentType', Variant);\n- ReportDocumentType := Variant;\n- Assert.AreEqual(Format(\"Gen. Journal Document Type\"::Invoice), ReportDocumentType, DocumentTypeShouldBeInvoiceErr);\n- LibraryReportDataset.FindCurrentRowValue('DocumentNo', Variant);\n- ReportDocumentNo := Variant;\n- Assert.AreEqual(CustLedgerEntry.\"Document No.\", ReportDocumentNo, DocumentNoShouldMatchErr);\n- end;\n-\n- [Test]\n- [HandlerFunctions('EXRAgedAccPayablePostingDateHandler')]\n- procedure AgedAccountsPayableReportAgesByPostingDate()\n- var\n- Vendor: Record Vendor;\n- VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n- Variant: Variant;\n- RequestPageXml: Text;\n- ReportingDateText: Text;\n- ReportingDate: Date;\n- begin\n- // [FEATURE] [AI test 0.4]\n- // [SCENARIO] Aged Accounts Payable report uses Posting Date as Reporting Date when aging by Posting Date\n- InitializeAgingData();\n-\n- // [GIVEN] Vendor \"V\" with an open ledger entry where Posting Date, Document Date, and Due Date are distinct\n- CreateMinimalVendor(Vendor);\n- CreateVendorLedgerEntry(VendorLedgerEntry, Vendor.\"No.\", \"Gen. Journal Document Type\"::Invoice);\n- VendorLedgerEntry.\"Document Date\" := WorkDate() - 10;\n- VendorLedgerEntry.Modify();\n- Commit();\n-\n- // [WHEN] Running the Aged Accounts Payable Excel report with Aging By = Posting Date\n- RequestPageXml := Report.RunRequestPage(Report::\"EXR Aged Acc Payable Excel\", RequestPageXml);\n- LibraryReportDataset.RunReportAndLoad(Report::\"EXR Aged Acc Payable Excel\", Variant, RequestPageXml);\n-\n- // [THEN] The Reporting Date matches the Posting Date of the vendor ledger entry\n- LibraryReportDataset.SetXmlNodeList('DataItem[@name=\"AgingData\"]');\n- Assert.AreEqual(1, LibraryReportDataset.RowCount(), 'One aging entry should be exported');\n- LibraryReportDataset.GetNextRow();\n- LibraryReportDataset.FindCurrentRowValue('ReportingDate', Variant);\n- ReportingDateText := Variant;\n- Evaluate(ReportingDate, ReportingDateText);\n- Assert.AreEqual(VendorLedgerEntry.\"Posting Date\", ReportingDate, 'Reporting Date should match the Posting Date when aging by Posting Date');\n- end;\n-\n local procedure CreateSampleBusinessUnits(HowMany: Integer)\n var\n BusinessUnit: Record \"Business Unit\";\n@@ -900,109 +782,6 @@ codeunit 139544 \"Trial Balance Excel Reports\"\n GLEntry.Insert();\n end;\n \n- local procedure InitializeAgingData()\n- var\n- Vendor: Record Vendor;\n- Customer: Record Customer;\n- VendorLedgerEntry: Record \"Vendor Ledger Entry\";\n- CustLedgerEntry: Record \"Cust. Ledger Entry\";\n- DetailedVendorLedgEntry: Record \"Detailed Vendor Ledg. Entry\";\n- DetailedCustLedgEntry: Record \"Detailed Cust. Ledg. Entry\";\n- begin\n- DetailedVendorLedgEntry.DeleteAll();\n- DetailedCustLedgEntry.DeleteAll();\n- VendorLedgerEntry.DeleteAll();\n- CustLedgerEntry.DeleteAll();\n- Vendor.DeleteAll();\n- Customer.DeleteAll();\n- end;\n-\n- local procedure CreateMinimalVendor(var Vendor: Record Vendor)\n- begin\n- Vendor.Init();\n- Vendor.\"No.\" := CopyStr(Format(CreateGuid()), 1, MaxStrLen(Vendor.\"No.\"));\n- Vendor.Name := Vendor.\"No.\";\n- Vendor.Insert();\n- end;\n-\n- local procedure CreateMinimalCustomer(var Customer: Record Customer)\n- begin\n- Customer.Init();\n- Customer.\"No.\" := CopyStr(Format(CreateGuid()), 1, MaxStrLen(Customer.\"No.\"));\n- Customer.Name := Customer.\"No.\";\n- Customer.Insert();\n- end;\n-\n- local procedure CreateVendorLedgerEntry(var VendorLedgerEntry: Record \"Vendor Ledger Entry\"; VendorNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\")\n- var\n- DetailedVendorLedgEntry: Record \"Detailed Vendor Ledg. Entry\";\n- EntryNo: Integer;\n- Amount: Decimal;\n- begin\n- if VendorLedgerEntry.FindLast() then;\n- EntryNo := VendorLedgerEntry.\"Entry No.\" + 1;\n-\n- VendorLedgerEntry.Init();\n- VendorLedgerEntry.\"Entry No.\" := EntryNo;\n- VendorLedgerEntry.\"Vendor No.\" := VendorNo;\n- VendorLedgerEntry.\"Vendor Name\" := VendorNo;\n- VendorLedgerEntry.\"Document Type\" := DocumentType;\n- VendorLedgerEntry.\"Document No.\" := 'DOC' + Format(EntryNo);\n- VendorLedgerEntry.\"Posting Date\" := WorkDate();\n- VendorLedgerEntry.\"Document Date\" := WorkDate();\n- VendorLedgerEntry.\"Due Date\" := WorkDate() + 30;\n- VendorLedgerEntry.Open := true;\n- VendorLedgerEntry.Insert();\n-\n- // Create detailed vendor ledger entry for remaining amount\n- Amount := -LibraryRandom.RandDec(1000, 2);\n- if DetailedVendorLedgEntry.FindLast() then;\n- DetailedVendorLedgEntry.Init();\n- DetailedVendorLedgEntry.\"Entry No.\" := DetailedVendorLedgEntry.\"Entry No.\" + 1;\n- DetailedVendorLedgEntry.\"Vendor Ledger Entry No.\" := VendorLedgerEntry.\"Entry No.\";\n- DetailedVendorLedgEntry.\"Vendor No.\" := VendorNo;\n- DetailedVendorLedgEntry.\"Posting Date\" := WorkDate();\n- DetailedVendorLedgEntry.\"Entry Type\" := DetailedVendorLedgEntry.\"Entry Type\"::\"Initial Entry\";\n- DetailedVendorLedgEntry.Amount := Amount;\n- DetailedVendorLedgEntry.\"Amount (LCY)\" := Amount;\n- DetailedVendorLedgEntry.Insert();\n- end;\n-\n- local procedure CreateCustLedgerEntry(var CustLedgerEntry: Record \"Cust. Ledger Entry\"; CustomerNo: Code[20]; DocumentType: Enum \"Gen. Journal Document Type\")\n- var\n- DetailedCustLedgEntry: Record \"Detailed Cust. Ledg. Entry\";\n- EntryNo: Integer;\n- Amount: Decimal;\n- begin\n- if CustLedgerEntry.FindLast() then;\n- EntryNo := CustLedgerEntry.\"Entry No.\" + 1;\n-\n- CustLedgerEntry.Init();\n- CustLedgerEntry.\"Entry No.\" := EntryNo;\n- CustLedgerEntry.\"Customer No.\" := CustomerNo;\n- CustLedgerEntry.\"Customer Name\" := CustomerNo;\n- CustLedgerEntry.\"Document Type\" := DocumentType;\n- CustLedgerEntry.\"Document No.\" := 'DOC' + Format(EntryNo);\n- CustLedgerEntry.\"Posting Date\" := WorkDate();\n- CustLedgerEntry.\"Document Date\" := WorkDate();\n- CustLedgerEntry.\"Due Date\" := WorkDate() + 30;\n- CustLedgerEntry.Open := true;\n- CustLedgerEntry.Insert();\n-\n- // Create detailed customer ledger entry for remaining amount\n- Amount := LibraryRandom.RandDec(1000, 2);\n- if DetailedCustLedgEntry.FindLast() then;\n- DetailedCustLedgEntry.Init();\n- DetailedCustLedgEntry.\"Entry No.\" := DetailedCustLedgEntry.\"Entry No.\" + 1;\n- DetailedCustLedgEntry.\"Cust. Ledger Entry No.\" := CustLedgerEntry.\"Entry No.\";\n- DetailedCustLedgEntry.\"Customer No.\" := CustomerNo;\n- DetailedCustLedgEntry.\"Posting Date\" := WorkDate();\n- DetailedCustLedgEntry.\"Entry Type\" := DetailedCustLedgEntry.\"Entry Type\"::\"Initial Entry\";\n- DetailedCustLedgEntry.Amount := Amount;\n- DetailedCustLedgEntry.\"Amount (LCY)\" := Amount;\n- DetailedCustLedgEntry.Insert();\n- end;\n-\n [RequestPageHandler]\n procedure EXRTrialBalanceExcelHandler(var EXRTrialBalanceExcel: TestRequestPage \"EXR Trial Balance Excel\")\n begin\n@@ -1032,28 +811,6 @@ codeunit 139544 \"Trial Balance Excel Reports\"\n EXRConsolidatedTrialBalance.OK().Invoke();\n end;\n \n- [RequestPageHandler]\n- procedure EXRAgedAccPayableExcelHandler(var EXRAgedAccPayableExcel: TestRequestPage \"EXR Aged Acc Payable Excel\")\n- begin\n- EXRAgedAccPayableExcel.AgedAsOfOption.SetValue(WorkDate());\n- EXRAgedAccPayableExcel.OK().Invoke();\n- end;\n-\n- [RequestPageHandler]\n- procedure EXRAgedAccountsRecExcelHandler(var EXRAgedAccountsRecExcel: TestRequestPage \"EXR Aged Accounts Rec Excel\")\n- begin\n- EXRAgedAccountsRecExcel.AgedAsOfOption.SetValue(WorkDate());\n- EXRAgedAccountsRecExcel.OK().Invoke();\n- end;\n-\n- [RequestPageHandler]\n- procedure EXRAgedAccPayablePostingDateHandler(var EXRAgedAccPayableExcel: TestRequestPage \"EXR Aged Acc Payable Excel\")\n- begin\n- EXRAgedAccPayableExcel.AgedAsOfOption.SetValue(WorkDate());\n- EXRAgedAccPayableExcel.AgingbyOption.SetValue('Posting Date');\n- EXRAgedAccPayableExcel.OK().Invoke();\n- end;\n-\n #if not CLEAN27\n #pragma warning disable AL0432\n [EventSubscriber(ObjectType::Codeunit, Codeunit::\"Trial Balance\", OnIsPerformantTrialBalanceFeatureActive, '', false, false)]\n"} {"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8632", "base_commit": "b3d3921ad18ebb9ae148c196ba465a7af8abb91f", "created_at": "2026-06-16T06:33:07Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchFactboxMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchFactboxMgmt.Codeunit.al\nindex a3dce9b95a..42b769b1c0 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchFactboxMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchFactboxMgmt.Codeunit.al\n@@ -376,6 +376,41 @@ codeunit 99001560 \"Subc. Purch. Factbox Mgmt.\"\n end;\n end;\n \n+ /// \n+ /// Opens the subcontracting transfer order(s) linked to the given production order.\n+ /// \n+ /// The production order to show the related subcontracting transfer orders for.\n+ procedure ShowTransferOrdersFromProductionOrder(ProductionOrder: Record \"Production Order\")\n+ var\n+ TransferHeader: Record \"Transfer Header\";\n+ TransferHeaderToOpen: Record \"Transfer Header\";\n+ TransferLine: Record \"Transfer Line\";\n+ PageManagement: Codeunit \"Page Management\";\n+ SelectionFilterMgt: Codeunit SelectionFilterManagement;\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ TransferLine.SetCurrentKey(\"Subc. Prod. Order No.\", \"Subc. Prod. Order Line No.\", \"Subc. Routing Reference No.\", \"Subc. Routing No.\", \"Subc. Operation No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Order No.\", ProductionOrder.\"No.\");\n+ TransferLine.SetRange(\"Derived From Line No.\", 0);\n+ if TransferLine.FindSet() then\n+ repeat\n+ if TransferHeader.Get(TransferLine.\"Document No.\") then\n+ TransferHeader.Mark(true);\n+ until TransferLine.Next() = 0;\n+ TransferHeader.MarkedOnly(true);\n+\n+ if TransferHeader.IsEmpty() then\n+ TransferHeaderToOpen.SetRange(\"No.\", '')\n+ else\n+ TransferHeaderToOpen.SetFilter(\"No.\", SelectionFilterMgt.GetSelectionFilterForTransferHeader(TransferHeader));\n+ PageManagement.PageRunList(TransferHeaderToOpen);\n+ end;\n+\n /// \n /// Returns the number of subcontractor prices matching the given purchase line.\n /// \ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrder.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrder.PageExt.al\nindex 3fe5eb00ce..9305138f0c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrder.PageExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrder.PageExt.al\n@@ -1,55 +1,69 @@\n-// ------------------------------------------------------------------------------------------------\n-// Copyright (c) Microsoft Corporation. All rights reserved.\n-// Licensed under the MIT License. See License.txt in the project root for license information.\n-// ------------------------------------------------------------------------------------------------\n-namespace Microsoft.Manufacturing.Subcontracting;\n-\n-using Microsoft.Inventory.Ledger;\n-using Microsoft.Manufacturing.Document;\n-using Microsoft.Purchases.Document;\n-\n-pageextension 99001548 \"Subc. Finished Prod. Order\" extends \"Finished Production Order\"\n-{\n- actions\n- {\n- addafter(\"Registered Put-away Lines\")\n- {\n- action(\"Subcontracting Purchase Lines\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting Order Lines';\n- Image = SubcontractingWorksheet;\n- RunObject = page \"Purchase Lines\";\n- RunPageLink = \"Document Type\" = const(Order), \"Prod. Order No.\" = field(\"No.\");\n- ToolTip = 'Show purchase order lines for subcontracting.';\n- }\n- }\n- addafter(\"&Warehouse Entries\")\n- {\n- action(\"Subc. Transfer Entries\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting Transfer Entries';\n- Image = ItemLedger;\n- RunObject = page \"Item Ledger Entries\";\n- RunPageLink = \"Entry Type\" = const(Transfer), \"Subc. Prod. Order No.\" = field(\"No.\");\n- RunPageView = sorting(\"Order Type\", \"Order No.\");\n- ToolTip = 'View the list of subcontracting transfers.';\n- }\n- action(\"WIP Ledger Entries\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting WIP Entries';\n- Image = LedgerEntries;\n- RunObject = page \"Subc. WIP Ledger Entries\";\n- RunPageLink = \"Prod. Order Status\" = field(Status), \"Prod. Order No.\" = field(\"No.\");\n- ToolTip = 'View the Subcontracting WIP Entries for this production order.';\n- }\n- }\n- addlast(Category_Entries)\n- {\n- actionref(\"Subc. Transfer Entries_Promoted\"; \"Subc. Transfer Entries\") { }\n- actionref(\"WIP Ledger Entries_Promoted\"; \"WIP Ledger Entries\") { }\n- }\n- }\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+namespace Microsoft.Manufacturing.Subcontracting;\n+\n+using Microsoft.Inventory.Ledger;\n+using Microsoft.Manufacturing.Document;\n+using Microsoft.Purchases.Document;\n+\n+pageextension 99001548 \"Subc. Finished Prod. Order\" extends \"Finished Production Order\"\n+{\n+ actions\n+ {\n+ addafter(\"Registered Put-away Lines\")\n+ {\n+ action(\"Subcontracting Purchase Lines\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Order Lines';\n+ Image = SubcontractingWorksheet;\n+ RunObject = page \"Purchase Lines\";\n+ RunPageLink = \"Document Type\" = const(Order), \"Prod. Order No.\" = field(\"No.\");\n+ ToolTip = 'Show purchase order lines for subcontracting.';\n+ }\n+ }\n+ addafter(\"&Warehouse Entries\")\n+ {\n+ action(\"Subc. Transfer Orders\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Orders';\n+ Image = TransferOrder;\n+ ToolTip = 'View the subcontracting transfer orders related to this production order.';\n+\n+ trigger OnAction()\n+ var\n+ SubcPurchFactboxMgmt: Codeunit \"Subc. Purch. Factbox Mgmt.\";\n+ begin\n+ SubcPurchFactboxMgmt.ShowTransferOrdersFromProductionOrder(Rec);\n+ end;\n+ }\n+ action(\"Subc. Transfer Entries\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Entries';\n+ Image = ItemLedger;\n+ RunObject = page \"Item Ledger Entries\";\n+ RunPageLink = \"Entry Type\" = const(Transfer), \"Subc. Prod. Order No.\" = field(\"No.\");\n+ RunPageView = sorting(\"Order Type\", \"Order No.\");\n+ ToolTip = 'View the list of subcontracting transfers.';\n+ }\n+ action(\"WIP Ledger Entries\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting WIP Entries';\n+ Image = LedgerEntries;\n+ RunObject = page \"Subc. WIP Ledger Entries\";\n+ RunPageLink = \"Prod. Order Status\" = field(Status), \"Prod. Order No.\" = field(\"No.\");\n+ ToolTip = 'View the Subcontracting WIP Entries for this production order.';\n+ }\n+ }\n+ addlast(Category_Entries)\n+ {\n+ actionref(\"Subc. Transfer Entries_Promoted\"; \"Subc. Transfer Entries\") { }\n+ actionref(\"WIP Ledger Entries_Promoted\"; \"WIP Ledger Entries\") { }\n+ }\n+ }\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrders.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrders.PageExt.al\nindex d6753ba257..ff954e609e 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrders.PageExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcFinishedProdOrders.PageExt.al\n@@ -1,50 +1,64 @@\n-// ------------------------------------------------------------------------------------------------\n-// Copyright (c) Microsoft Corporation. All rights reserved.\n-// Licensed under the MIT License. See License.txt in the project root for license information.\n-// ------------------------------------------------------------------------------------------------\n-namespace Microsoft.Manufacturing.Subcontracting;\n-\n-using Microsoft.Inventory.Ledger;\n-using Microsoft.Manufacturing.Document;\n-using Microsoft.Purchases.Document;\n-\n-pageextension 99001543 \"Subc. Finished Prod. Orders\" extends \"Finished Production Orders\"\n-{\n- actions\n- {\n- addafter(\"E&ntries\")\n- {\n- action(\"Subcontracting Purchase Lines\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting Order Lines';\n- Image = SubcontractingWorksheet;\n- RunObject = page \"Purchase Lines\";\n- RunPageLink = \"Document Type\" = const(Order), \"Prod. Order No.\" = field(\"No.\");\n- ToolTip = 'Show purchase order lines for subcontracting.';\n- }\n- }\n- addafter(\"&Warehouse Entries\")\n- {\n- action(\"Subc. Transfer Entries\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting Transfer Entries';\n- Image = ItemLedger;\n- RunObject = page \"Item Ledger Entries\";\n- RunPageLink = \"Entry Type\" = const(Transfer), \"Subc. Prod. Order No.\" = field(\"No.\");\n- RunPageView = sorting(\"Order Type\", \"Order No.\");\n- ToolTip = 'View the list of subcontracting transfers.';\n- }\n- action(\"WIP Ledger Entries\")\n- {\n- ApplicationArea = Subcontracting;\n- Caption = 'Subcontracting WIP Entries';\n- Image = LedgerEntries;\n- RunObject = page \"Subc. WIP Ledger Entries\";\n- RunPageLink = \"Prod. Order Status\" = field(Status), \"Prod. Order No.\" = field(\"No.\");\n- ToolTip = 'View the Subcontracting WIP Entries for this production order.';\n- }\n- }\n- }\n+// ------------------------------------------------------------------------------------------------\n+// Copyright (c) Microsoft Corporation. All rights reserved.\n+// Licensed under the MIT License. See License.txt in the project root for license information.\n+// ------------------------------------------------------------------------------------------------\n+namespace Microsoft.Manufacturing.Subcontracting;\n+\n+using Microsoft.Inventory.Ledger;\n+using Microsoft.Manufacturing.Document;\n+using Microsoft.Purchases.Document;\n+\n+pageextension 99001543 \"Subc. Finished Prod. Orders\" extends \"Finished Production Orders\"\n+{\n+ actions\n+ {\n+ addafter(\"E&ntries\")\n+ {\n+ action(\"Subcontracting Purchase Lines\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Order Lines';\n+ Image = SubcontractingWorksheet;\n+ RunObject = page \"Purchase Lines\";\n+ RunPageLink = \"Document Type\" = const(Order), \"Prod. Order No.\" = field(\"No.\");\n+ ToolTip = 'Show purchase order lines for subcontracting.';\n+ }\n+ }\n+ addafter(\"&Warehouse Entries\")\n+ {\n+ action(\"Subc. Transfer Orders\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Orders';\n+ Image = TransferOrder;\n+ ToolTip = 'View the subcontracting transfer orders related to this production order.';\n+\n+ trigger OnAction()\n+ var\n+ SubcPurchFactboxMgmt: Codeunit \"Subc. Purch. Factbox Mgmt.\";\n+ begin\n+ SubcPurchFactboxMgmt.ShowTransferOrdersFromProductionOrder(Rec);\n+ end;\n+ }\n+ action(\"Subc. Transfer Entries\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Entries';\n+ Image = ItemLedger;\n+ RunObject = page \"Item Ledger Entries\";\n+ RunPageLink = \"Entry Type\" = const(Transfer), \"Subc. Prod. Order No.\" = field(\"No.\");\n+ RunPageView = sorting(\"Order Type\", \"Order No.\");\n+ ToolTip = 'View the list of subcontracting transfers.';\n+ }\n+ action(\"WIP Ledger Entries\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting WIP Entries';\n+ Image = LedgerEntries;\n+ RunObject = page \"Subc. WIP Ledger Entries\";\n+ RunPageLink = \"Prod. Order Status\" = field(Status), \"Prod. Order No.\" = field(\"No.\");\n+ ToolTip = 'View the Subcontracting WIP Entries for this production order.';\n+ }\n+ }\n+ }\n }\n\\ No newline at end of file\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrder.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrder.PageExt.al\nindex fae7afb0ca..7612fdcf78 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrder.PageExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrder.PageExt.al\n@@ -25,6 +25,20 @@ pageextension 99001504 \"Subc. Rel. Prod. Order\" extends \"Released Production Ord\n }\n addafter(\"&Warehouse Entries\")\n {\n+ action(\"Subc. Transfer Orders\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Orders';\n+ Image = TransferOrder;\n+ ToolTip = 'View the subcontracting transfer orders related to this production order.';\n+\n+ trigger OnAction()\n+ var\n+ SubcPurchFactboxMgmt: Codeunit \"Subc. Purch. Factbox Mgmt.\";\n+ begin\n+ SubcPurchFactboxMgmt.ShowTransferOrdersFromProductionOrder(Rec);\n+ end;\n+ }\n action(\"Subc. Transfer Entries\")\n {\n ApplicationArea = Subcontracting;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrders.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrders.PageExt.al\nindex a6a74dc3d3..0446a28a16 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrders.PageExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/Manufacturing/SubcRelProdOrders.PageExt.al\n@@ -25,6 +25,20 @@ pageextension 99001505 \"Subc. Rel. Prod. Orders\" extends \"Released Production Or\n }\n addafter(\"&Warehouse Entries\")\n {\n+ action(\"Subc. Transfer Orders\")\n+ {\n+ ApplicationArea = Subcontracting;\n+ Caption = 'Subcontracting Transfer Orders';\n+ Image = TransferOrder;\n+ ToolTip = 'View the subcontracting transfer orders related to this production order.';\n+\n+ trigger OnAction()\n+ var\n+ SubcPurchFactboxMgmt: Codeunit \"Subc. Purch. Factbox Mgmt.\";\n+ begin\n+ SubcPurchFactboxMgmt.ShowTransferOrdersFromProductionOrder(Rec);\n+ end;\n+ }\n action(\"Subc. Transfer Entries\")\n {\n ApplicationArea = Subcontracting;\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["SubcTransferOrdersActionOnProductionOrdersListOpensRelatedTransferOrder", "SubcTransferOrdersActionOnProductionOrderOpensRelatedTransferOrder"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex c2ad504090..ef56e4265d 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -164,6 +164,72 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.RecordIsNotEmpty(TransferLine);\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmHandler,HandleTransferOrder,HandleSubcTransferOrdersList')]\n+ procedure SubcTransferOrdersActionOnProductionOrderOpensRelatedTransferOrder()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ UnrelatedProductionOrder: Record \"Production Order\";\n+ ProductionLocation: Record Location;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedTransferOrderNo: Code[20];\n+ ReleasedProductionOrder: TestPage \"Released Production Order\";\n+ begin\n+ // [SCENARIO 638532] The Released Production Order card provides a navigation action to view only its related subcontracting transfer orders.\n+\n+ // [GIVEN] Subcontracting setup with two released production orders, each ending up with its own subcontracting purchase order and transfer order.\n+ // The transfer route is location-based (component location -> subcontractor location), so it is created only for the first order and reused by the second.\n+ SetupSubcontractingForTransferOrderTests(Item, WorkCenter, ProductionLocation);\n+ ExpectedTransferOrderNo := CreateProductionOrderWithSubcTransferOrder(Item, WorkCenter, ProductionLocation.Code, true, ProductionOrder);\n+ CreateProductionOrderWithSubcTransferOrder(Item, WorkCenter, ProductionLocation.Code, false, UnrelatedProductionOrder);\n+\n+ // [WHEN] Invoking the \"Subcontracting Transfer Orders\" action on the first production order card\n+ OpenedTransferOrderListNo := '';\n+ ReleasedProductionOrder.OpenView();\n+ ReleasedProductionOrder.GoToRecord(ProductionOrder);\n+ ReleasedProductionOrder.\"Subc. Transfer Orders\".Invoke();\n+ ReleasedProductionOrder.Close();\n+\n+ // [THEN] Only the related transfer order is shown - the handler asserts exactly one record, so the unrelated order is excluded\n+ Assert.AreEqual(\n+ ExpectedTransferOrderNo, OpenedTransferOrderListNo,\n+ 'The production order card action must open only the related subcontracting transfer order.');\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('ConfirmHandler,HandleTransferOrder,HandleSubcTransferOrdersList')]\n+ procedure SubcTransferOrdersActionOnProductionOrdersListOpensRelatedTransferOrder()\n+ var\n+ Item: Record Item;\n+ ProductionOrder: Record \"Production Order\";\n+ UnrelatedProductionOrder: Record \"Production Order\";\n+ ProductionLocation: Record Location;\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ ExpectedTransferOrderNo: Code[20];\n+ ReleasedProductionOrders: TestPage \"Released Production Orders\";\n+ begin\n+ // [SCENARIO 638532] The Released Production Orders list provides a navigation action to view only the related subcontracting transfer orders.\n+\n+ // [GIVEN] Subcontracting setup with two released production orders, each ending up with its own subcontracting purchase order and transfer order.\n+ // The transfer route is location-based (component location -> subcontractor location), so it is created only for the first order and reused by the second.\n+ SetupSubcontractingForTransferOrderTests(Item, WorkCenter, ProductionLocation);\n+ ExpectedTransferOrderNo := CreateProductionOrderWithSubcTransferOrder(Item, WorkCenter, ProductionLocation.Code, true, ProductionOrder);\n+ CreateProductionOrderWithSubcTransferOrder(Item, WorkCenter, ProductionLocation.Code, false, UnrelatedProductionOrder);\n+\n+ // [WHEN] Invoking the \"Subcontracting Transfer Orders\" action on the first production order in the list\n+ OpenedTransferOrderListNo := '';\n+ ReleasedProductionOrders.OpenView();\n+ ReleasedProductionOrders.GoToRecord(ProductionOrder);\n+ ReleasedProductionOrders.\"Subc. Transfer Orders\".Invoke();\n+ ReleasedProductionOrders.Close();\n+\n+ // [THEN] Only the related transfer order is shown - the handler asserts exactly one record, so the unrelated order is excluded\n+ Assert.AreEqual(\n+ ExpectedTransferOrderNo, OpenedTransferOrderListNo,\n+ 'The production orders list action must open only the related subcontracting transfer order.');\n+ end;\n+\n [Test]\n [HandlerFunctions('ConfirmHandler,HandleTransferOrder')]\n procedure CannotDeleteSubcontractingOrderWithAssociatedTransferOrder()\n@@ -3013,6 +3079,15 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n TransfOrderPage.OK().Invoke();\n end;\n \n+ [PageHandler]\n+ procedure HandleSubcTransferOrdersList(var TransferOrders: TestPage \"Transfer Orders\")\n+ begin\n+ Assert.IsTrue(TransferOrders.First(), 'Expected at least one subcontracting transfer order in the list.');\n+ OpenedTransferOrderListNo := CopyStr(TransferOrders.\"No.\".Value(), 1, MaxStrLen(OpenedTransferOrderListNo));\n+ Assert.IsFalse(TransferOrders.Next(), 'Expected exactly one subcontracting transfer order in the list.');\n+ TransferOrders.OK().Invoke();\n+ end;\n+\n [ConfirmHandler]\n procedure ConfirmYesShowSubcontractingPurchOrders(Question: Text[1024]; var Reply: Boolean)\n begin\n@@ -3131,6 +3206,65 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n exit(RoutingLine.\"Operation No.\");\n end;\n \n+ local procedure SetupSubcontractingForTransferOrderTests(var Item: Record Item; var WorkCenter: array[2] of Record \"Work Center\"; var ProductionLocation: Record Location)\n+ var\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ begin\n+ Initialize();\n+ SubcontractingMgmtLibrary.UpdateManufacturingSetupWithSubcontractingLocation();\n+ SubcontractingMgmtLibrary.SetupInventorySetup();\n+\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ UpdateProdBomAndRoutingWithRoutingLink(Item, WorkCenter[2].\"No.\");\n+ SubcontractingMgmtLibrary.UpdateProdBomWithComponentSupplyMethod(Item, \"Component Supply Method\"::\"Transfer to Vendor\");\n+ UpdateVendorWithSubcontractingLocationCode(WorkCenter[2]);\n+ LibraryWarehouse.CreateLocationWithInventoryPostingSetup(ProductionLocation);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+ end;\n+\n+ local procedure CreateProductionOrderWithSubcTransferOrder(Item: Record Item; var WorkCenter: array[2] of Record \"Work Center\"; ProductionLocationCode: Code[10]; CreateTransferRouteForOrder: Boolean; var ProductionOrder: Record \"Production Order\"): Code[20]\n+ var\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ TransferHeader: Record \"Transfer Header\";\n+ ReleasedProdOrderRtng: TestPage \"Prod. Order Routing\";\n+ PurchaseHeaderPage: TestPage \"Purchase Order\";\n+ begin\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ SetAllProdOrderTransferComponentLocations(ProductionOrder.\"No.\", ProductionLocationCode);\n+ // The transfer route is keyed by from/to location, so it must be created only once for a given location pair.\n+ // Callers that reuse the same locations pass false for subsequent orders to reuse the existing route.\n+ if CreateTransferRouteForOrder then\n+ SubcontractingMgmtLibrary.CreateTransferRoute(WorkCenter[2], ProductionOrder);\n+\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ ProdOrderRoutingLine.SetRange(\"Work Center No.\", WorkCenter[2].\"No.\");\n+ ProdOrderRoutingLine.FindFirst();\n+ ReleasedProdOrderRtng.OpenView();\n+ ReleasedProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ ReleasedProdOrderRtng.CreateSubcontracting.Invoke();\n+ ReleasedProdOrderRtng.Close();\n+\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+\n+ PurchaseHeaderPage.OpenView();\n+ PurchaseHeaderPage.GoToRecord(PurchaseHeader);\n+ PurchaseHeaderPage.CreateTransfOrdToSubcontractor.Invoke();\n+ PurchaseHeaderPage.Close();\n+\n+ TransferHeader.SetRange(\"Subcontr. Purch. Order No.\", PurchaseHeader.\"No.\");\n+ Assert.IsTrue(TransferHeader.FindFirst(), 'Expected a subcontracting transfer order for the production order.');\n+ exit(TransferHeader.\"No.\");\n+ end;\n+\n local procedure CreateAndCalculateNeededWorkAndMachineCenter(var WorkCenter: array[2] of Record \"Work Center\"; var MachineCenter: array[2] of Record \"Machine Center\")\n var\n CapacityUnitOfMeasure: Record \"Capacity Unit of Measure\";\n@@ -3983,6 +4117,7 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n IsInitialized: Boolean;\n Subcontracting: Boolean;\n OpenedTransferOrderNo: Code[20];\n+ OpenedTransferOrderListNo: Code[20];\n PurchaseOrderPageOpened: Boolean;\n PurchaseLinesPageOpened: Boolean;\n UnitCostCalculation: Option Time,Units;\n"} -{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8616", "base_commit": "34cc7ccdc6ab40f6212196856671d9f4c531677b", "created_at": "2026-06-15T21:29:21Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al\nindex 2631e38aec..8af3d51e41 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al\n@@ -4,7 +4,6 @@\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting;\n \n-using Microsoft.QualityManagement.Setup.ApplicationAreas;\n using System.Upgrade;\n \n codeunit 99001501 \"Subcontracting Install\"\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al b/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al\nindex 74a24a8bf0..42b5428962 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al\n@@ -3,8 +3,8 @@\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting;\n+\n using Microsoft.Manufacturing.Planning;\n-using Microsoft.QualityManagement.Setup.ApplicationAreas;\n \n permissionset 99001501 \"Subcontract. - Objs\"\n {\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al\nindex 260fe4b050..d1d232c956 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al\n@@ -49,6 +49,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Production Order';\n+ Enabled = Rec.\"Subc. Prod. Order No.\" <> '';\n Image = Production;\n ToolTip = 'View the related production order.';\n trigger OnAction()\n@@ -60,6 +61,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Production Order Routing';\n+ Enabled = Rec.\"Subc. Prod. Order No.\" <> '';\n Image = Route;\n ToolTip = 'View the related production order routing.';\n trigger OnAction()\n@@ -71,6 +73,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Production Order Components';\n+ Enabled = Rec.\"Subc. Prod. Order No.\" <> '';\n Image = Components;\n ToolTip = 'View the related production order components.';\n trigger OnAction()\n@@ -82,6 +85,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Subcontracting Purchase Order';\n+ Enabled = Rec.\"Subc. Purch. Order No.\" <> '';\n Image = Order;\n ToolTip = 'View the related subcontracting purchase order.';\n trigger OnAction()\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al\nindex 3449fe2689..88abec2181 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al\n@@ -2,7 +2,7 @@\n // Copyright (c) Microsoft Corporation. All rights reserved.\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n-namespace Microsoft.QualityManagement.Setup.ApplicationAreas;\n+namespace Microsoft.Manufacturing.Subcontracting;\n \n #if not CLEAN29\n using Microsoft.Manufacturing.Setup;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al\nindex 109321363f..6551dec314 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al\n@@ -2,7 +2,7 @@\n // Copyright (c) Microsoft Corporation. All rights reserved.\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n-namespace Microsoft.QualityManagement.Setup.ApplicationAreas;\n+namespace Microsoft.Manufacturing.Subcontracting;\n \n using System.Environment.Configuration;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139990, "functionName": ["ItemLedgerEntriesSubcActionsEnabledWhenSubcontracting", "ItemLedgerEntriesSubcActionsDisabledWhenNotSubcontracting"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al\nindex 46606182df..c598c8c43c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al\n@@ -4,6 +4,7 @@\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting.Test;\n \n+using Microsoft.Inventory.Ledger;\n using Microsoft.Inventory.Planning;\n using Microsoft.Inventory.Requisition;\n using Microsoft.Manufacturing.Capacity;\n@@ -588,6 +589,91 @@ codeunit 139990 \"Subc. Subcontracting UI Test\"\n PurchaseOrder.Close();\n end;\n \n+ [Test]\n+ procedure ItemLedgerEntriesSubcActionsDisabledWhenNotSubcontracting()\n+ var\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ ItemLedgerEntries: TestPage \"Item Ledger Entries\";\n+ begin\n+ // [SCENARIO 638458] Subcontracting actions on Item Ledger Entries are disabled when the entry has no subcontracting production order or purchase order.\n+ Initialize();\n+\n+ // [GIVEN] An Item Ledger Entry that is NOT related to subcontracting (no Subc. Prod. Order No. or Subc. Purch. Order No.)\n+ ItemLedgerEntry.Init();\n+ ItemLedgerEntry.\"Entry No.\" := GetNextItemLedgerEntryNo();\n+ ItemLedgerEntry.\"Item No.\" := 'TEST-ITEM';\n+ ItemLedgerEntry.\"Entry Type\" := ItemLedgerEntry.\"Entry Type\"::Purchase;\n+ ItemLedgerEntry.\"Subc. Prod. Order No.\" := '';\n+ ItemLedgerEntry.\"Subc. Purch. Order No.\" := '';\n+ ItemLedgerEntry.Insert();\n+\n+ // [WHEN] The Item Ledger Entries page is opened for that entry\n+ ItemLedgerEntries.OpenView();\n+ ItemLedgerEntries.GoToRecord(ItemLedgerEntry);\n+\n+ // [THEN] The Production Order action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Production Order\".Enabled(), ILEProdActionsEnabledErr);\n+ // [THEN] The Production Order Routing action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Production Order Routing\".Enabled(), ILEProdActionsEnabledErr);\n+ // [THEN] The Production Order Components action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Production Order Components\".Enabled(), ILEProdActionsEnabledErr);\n+ // [THEN] The Purchase Order action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Purchase Order\".Enabled(), ILEPurchActionsEnabledErr);\n+\n+ ItemLedgerEntries.Close();\n+\n+ // Cleanup\n+ ItemLedgerEntry.Delete();\n+ end;\n+\n+ [Test]\n+ procedure ItemLedgerEntriesSubcActionsEnabledWhenSubcontracting()\n+ var\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ ItemLedgerEntries: TestPage \"Item Ledger Entries\";\n+ begin\n+ // [SCENARIO 638458] Subcontracting actions on Item Ledger Entries are enabled when the entry is related to a subcontracting production order and purchase order.\n+ Initialize();\n+\n+ // [GIVEN] An Item Ledger Entry that IS related to subcontracting\n+ ItemLedgerEntry.Init();\n+ ItemLedgerEntry.\"Entry No.\" := GetNextItemLedgerEntryNo();\n+ ItemLedgerEntry.\"Item No.\" := 'TEST-ITEM';\n+ ItemLedgerEntry.\"Entry Type\" := ItemLedgerEntry.\"Entry Type\"::Purchase;\n+ ItemLedgerEntry.\"Subc. Prod. Order No.\" := 'PO-SUBC-001';\n+ ItemLedgerEntry.\"Subc. Prod. Order Line No.\" := 10000;\n+ ItemLedgerEntry.\"Subc. Purch. Order No.\" := 'PURCH-SUBC-001';\n+ ItemLedgerEntry.\"Subc. Purch. Order Line No.\" := 10000;\n+ ItemLedgerEntry.Insert();\n+\n+ // [WHEN] The Item Ledger Entries page is opened for that entry\n+ ItemLedgerEntries.OpenView();\n+ ItemLedgerEntries.GoToRecord(ItemLedgerEntry);\n+\n+ // [THEN] The Production Order action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Production Order\".Enabled(), ILEProdActionsNotEnabledErr);\n+ // [THEN] The Production Order Routing action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Production Order Routing\".Enabled(), ILEProdActionsNotEnabledErr);\n+ // [THEN] The Production Order Components action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Production Order Components\".Enabled(), ILEProdActionsNotEnabledErr);\n+ // [THEN] The Purchase Order action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Purchase Order\".Enabled(), ILEPurchActionsNotEnabledErr);\n+\n+ ItemLedgerEntries.Close();\n+\n+ // Cleanup\n+ ItemLedgerEntry.Delete();\n+ end;\n+\n+ local procedure GetNextItemLedgerEntryNo(): Integer\n+ var\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ begin\n+ if ItemLedgerEntry.FindLast() then\n+ exit(ItemLedgerEntry.\"Entry No.\" + 1);\n+ exit(1);\n+ end;\n+\n var\n Assert: Codeunit Assert;\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -602,4 +688,8 @@ codeunit 139990 \"Subc. Subcontracting UI Test\"\n SubcontractingActionsEnabledErr: Label 'Subcontractor Prices action should not be enabled for a non-subcontracting Work Center.';\n SubcontractingActionsNotVisibleErr: Label 'Subcontractor Prices action should be visible for a subcontracting Work Center.';\n SubcontractingActionsNotEnabledErr: Label 'Subcontractor Prices action should be enabled for a subcontracting Work Center.';\n+ ILEProdActionsEnabledErr: Label 'Production actions should not be enabled for a non-subcontracting Item Ledger Entry.';\n+ ILEProdActionsNotEnabledErr: Label 'Production actions should be enabled for a subcontracting Item Ledger Entry.';\n+ ILEPurchActionsEnabledErr: Label 'Purchase Order action should not be enabled for a non-subcontracting Item Ledger Entry.';\n+ ILEPurchActionsNotEnabledErr: Label 'Purchase Order action should be enabled for a subcontracting Item Ledger Entry.';\n }\n\\ No newline at end of file\n"} -{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8612", "base_commit": "34cc7ccdc6ab40f6212196856671d9f4c531677b", "created_at": "2026-06-15T14:26:39Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex b6de5b5ea0..6a958ce4b4 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -39,7 +39,6 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n PurchOrderCreatedPluralTxt: Label '%1 purchase orders were created.\\\\Do you want to view them?', Comment = '%1 = number of purchase orders created';\n PurchOrderAlreadyCreatedQst: Label 'Purchase orders have already been created.\\\\Do you want to view them?';\n CreationOfSubcontractingOrderIsNotAllowedErr: Label 'You cannot create Subcontracting Order, because the Production Order %1 is not released.', Comment = '%1=Production Order No.';\n- NoProdOrderLineWithRemQtyErr: Label 'No Prod. Order Line with Remaining Quantity.';\n BlankLocationConfirmQst: Label 'One or more Prod. Order Components with Component Supply Method Transfer to Vendor have a blank Location Code. Without a Location Code, you will not be able to create a transfer order to send the components to the subcontractor.\\\\Do you want to create the Subcontracting Order anyway?';\n SameAsSubcLocConfirmQst: Label 'One or more Prod. Order Components with Component Supply Method Transfer to Vendor have Location Code %1, which is the same as the Subcontracting Location Code of vendor %2. A transfer order cannot be created from and to the same location.\\\\Do you want to create the Subcontracting Order anyway?', Comment = '%1=Component Location Code, %2=Vendor No.';\n NotEnoughSpaceErr: Label 'There is not enough space to insert the subcontracting info line.';\n@@ -61,7 +60,8 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n ManufacturingSetup.TestField(\"Subcontracting Template Name\");\n ManufacturingSetup.TestField(\"Subcontracting Batch Name\");\n \n- CheckProdOrderRtngLine(ProdOrderRoutingLine, ProdOrderLine);\n+ if not CheckProdOrderRtngLine(ProdOrderRoutingLine, ProdOrderLine) then\n+ exit(0);\n \n if not CheckProdOrderComponentLines(ProdOrderRoutingLine) then\n exit;\n@@ -259,7 +259,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n Clear(RoutingReferenceNo);\n end;\n \n- local procedure CheckProdOrderRtngLine(ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\")\n+ local procedure CheckProdOrderRtngLine(ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n var\n WorkCenter: Record \"Work Center\";\n begin\n@@ -273,12 +273,13 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n ProdOrderLine.SetRange(\"Routing Reference No.\", ProdOrderRoutingLine.\"Routing Reference No.\");\n ProdOrderLine.SetFilter(\"Remaining Quantity\", '<>%1', 0);\n if ProdOrderLine.IsEmpty() then\n- Error(NoProdOrderLineWithRemQtyErr);\n+ exit(false);\n \n WorkCenter.SetLoadFields(\"Gen. Prod. Posting Group\", \"Subcontractor No.\");\n WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\");\n WorkCenter.TestField(\"Subcontractor No.\");\n WorkCenter.TestField(\"Gen. Prod. Posting Group\");\n+ exit(true);\n end;\n \n internal procedure ShowExistingPurchaseOrdersForRoutingLines(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\")\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ShowExistingPurchOrdersAfterReceiptDoesNotError"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 950c628cf5..c2ad504090 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2774,6 +2774,50 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmYesShowSubcontractingPurchOrders,HandlePurchaseOrderPage,HandlePurchaseLinesPage')]\n+ procedure ShowExistingPurchOrdersAfterReceiptDoesNotError()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ begin\n+ // [SCENARIO 637777] Re-running Create Subcontracting Order after fully receiving the existing subcontracting purchase order should offer to view the existing order instead of raising \"No Prod. Order Line with Remaining Quantity.\"\n+\n+ // [GIVEN] Manufacturing setup with subcontracting work center, item with routing/BOM, released production order, and a created subcontracting purchase order\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", WorkCenter[2].\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+\n+ // [GIVEN] The existing subcontracting purchase order is fully received\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [WHEN] Create Subcontracting Order is invoked again from the same routing line\n+ PurchaseLinesPageOpened := false;\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] The existing purchase lines are shown and no raw remaining-quantity error is raised\n+ Assert.IsTrue(PurchaseLinesPageOpened, 'Purchase Lines list should open when the subcontracting purchase order already exists after full receipt.');\n+ end;\n+\n [Test]\n procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n var\n"} -{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8600", "base_commit": "34cc7ccdc6ab40f6212196856671d9f4c531677b", "created_at": "2026-06-12T15:07:44Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al\nindex 3d906b1720..bb2d4555e8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al\n@@ -25,6 +25,8 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n ExistingPurchLineErr: Label 'You cannot change this field because the component is already assigned to subcontracting purchase order %1.\\\\Updating the quantity is only allowed through the purchase order.', Comment = '%1=Document No';\n ExistingTransferLineQst: Label 'The component has already been assigned to the subcontracting transfer order %1.\\\\The quantity may only be updated via the purchase order and processing of the stock transfer.', Comment = '%1=Transfer Order No';\n ExistingTransferLineErr: Label 'You cannot open Tracking Specification because this component is already specified in Transfer Order %1.', Comment = '%1=Document No.';\n+ CannotModifyCompTransferExistsErr: Label 'You cannot change this component because transfer orders exist for the linked production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n+ CannotModifyCompStockAtSubcErr: Label 'You cannot change this component because there are remaining components or WIP items transferred to the subcontractor for production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n \n [EventSubscriber(ObjectType::Codeunit, Codeunit::\"Prod. Order Comp.-Reserve\", OnAfterInitFromProdOrderComp, '', false, false)]\n local procedure OnAfterInitFromProdOrderComp(ProdOrderComponent: Record \"Prod. Order Component\")\n@@ -92,6 +94,65 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n if Rec.IsTemporary then\n exit;\n CheckExistingSubcontractingTransferOrder(Rec, xRec, CurrFieldNo);\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Location Code\" <> xRec.\"Location Code\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Bin Code\", false, false)]\n+ local procedure OnBeforeValidateBinCode(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Bin Code\" <> xRec.\"Bin Code\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Item No.\", false, false)]\n+ local procedure OnBeforeValidateItemNo(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Item No.\" <> xRec.\"Item No.\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Variant Code\", false, false)]\n+ local procedure OnBeforeValidateVariantCode(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Variant Code\" <> xRec.\"Variant Code\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n end;\n \n [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Quantity per\", false, false)]\n@@ -106,6 +167,65 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n if Rec.IsTemporary then\n exit;\n CheckExistingDocumentsForSubcontracting(Rec, xRec, CurrFieldNo);\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Quantity per\" <> xRec.\"Quantity per\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Expected Quantity\", false, false)]\n+ local procedure OnBeforeValidateExpectedQuantity(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Expected Quantity\" <> xRec.\"Expected Quantity\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Component Supply Method\", false, false)]\n+ local procedure OnBeforeValidateComponentSupplyMethod(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Component Supply Method\" <> xRec.\"Component Supply Method\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeDeleteEvent, '', false, false)]\n+ local procedure OnBeforeDeleteProdOrderComponent(var Rec: Record \"Prod. Order Component\"; RunTrigger: Boolean)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+ if not RunTrigger then\n+ exit;\n+\n+ if Rec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(Rec);\n end;\n \n local procedure CheckExistingPostedSubcontractingTransferOrder(ProdOrderComponent: Record \"Prod. Order Component\"): Boolean\n@@ -364,4 +484,66 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n CheckExistingSubcontractingPurchaseOrder(ProdOrderComponent);\n end;\n end;\n+\n+ local procedure CheckUncompletedSubcontractingDocumentsExist(ProdOrderComponent: Record \"Prod. Order Component\")\n+ var\n+ ProdOrderLine: Record \"Prod. Order Line\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ begin\n+ ProdOrderLine.SetLoadFields(\"Routing Reference No.\", \"Routing No.\");\n+ if not ProdOrderLine.Get(ProdOrderComponent.Status, ProdOrderComponent.\"Prod. Order No.\", ProdOrderComponent.\"Prod. Order Line No.\") then\n+ exit;\n+\n+ PurchaseLine.SetCurrentKey(\"Document Type\", Type, \"Prod. Order No.\", \"Prod. Order Line No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProdOrderComponent.\"Prod. Order No.\");\n+ PurchaseLine.SetRange(\"Prod. Order Line No.\", ProdOrderComponent.\"Prod. Order Line No.\");\n+\n+ if ProdOrderComponent.\"Routing Link Code\" <> '' then begin\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n+ ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLine.\"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetRange(\"Routing Link Code\", ProdOrderComponent.\"Routing Link Code\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Operation No.\");\n+ if ProdOrderRoutingLine.FindFirst() then\n+ PurchaseLine.SetRange(\"Operation No.\", ProdOrderRoutingLine.\"Operation No.\");\n+ end;\n+\n+ if PurchaseLine.FindSet() then\n+ repeat\n+ if HasSubcTransferForPurchLine(PurchaseLine, ProdOrderComponent) then\n+ Error(CannotModifyCompTransferExistsErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+\n+ ProdOrderComponent.SetRange(\"Subc. Purchase Order Filter\", PurchaseLine.\"Document No.\");\n+ if HasStockAtSubcLocationForComponentForPurchLine(ProdOrderComponent) then\n+ Error(CannotModifyCompStockAtSubcErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+ until PurchaseLine.Next() = 0;\n+ end;\n+\n+ local procedure HasSubcTransferForPurchLine(PurchaseLine: Record \"Purchase Line\"; ProdOrderComponent: Record \"Prod. Order Component\"): Boolean\n+ var\n+ TransferLine: Record \"Transfer Line\";\n+ begin\n+ TransferLine.SetCurrentKey(\"Subc. Purch. Order No.\", \"Subc. Prod. Order No.\", \"Subc. Prod. Order Line No.\", \"Subc. Operation No.\");\n+ TransferLine.SetRange(\"Subc. Purch. Order No.\", PurchaseLine.\"Document No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Order No.\", ProdOrderComponent.\"Prod. Order No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Order Line No.\", ProdOrderComponent.\"Prod. Order Line No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Ord. Comp Line No.\", ProdOrderComponent.\"Line No.\");\n+ exit(not TransferLine.IsEmpty());\n+ end;\n+\n+ local procedure HasStockAtSubcLocationForComponentForPurchLine(ProdOrderComponent: Record \"Prod. Order Component\"): Boolean\n+ var\n+ SubcTransferManagement: Codeunit \"Subc. Transfer Management\";\n+ NetStockAtSubcLocation: Decimal;\n+ begin\n+ ProdOrderComponent.CalcFields(\"Subc. Qty. transf. to Subcontr\");\n+ if ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\" = 0 then\n+ exit(false);\n+\n+ NetStockAtSubcLocation := ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\";\n+ NetStockAtSubcLocation -= SubcTransferManagement.CalcConsumedQtyAtSubcLocation(ProdOrderComponent);\n+ exit(NetStockAtSubcLocation > 0);\n+ end;\n }\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al\nindex e7e85257d3..0c886fc5ec 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al\n@@ -1,22 +1,45 @@\n-// ------------------------------------------------------------------------------------------------\n+// ------------------------------------------------------------------------------------------------\n // Copyright (c) Microsoft Corporation. All rights reserved.\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting;\n \n+using Microsoft.Inventory.Transfer;\n using Microsoft.Manufacturing.Document;\n using Microsoft.Manufacturing.Routing;\n using Microsoft.Manufacturing.WorkCenter;\n+using Microsoft.Purchases.Document;\n \n codeunit 99001520 \"Subc. Prod. Order Rtng. Ext.\"\n {\n-#if not CLEAN29\n var\n+#if not CLEAN29\n #pragma warning disable AL0432\n SubcFeatureFlagHandler: Codeunit \"Subc. Feature Flag Handler\";\n #pragma warning restore AL0432\n+#endif\n+ CannotModifyRtngLineTransferExistsErr: Label 'You cannot change this routing line because transfer orders exist for the linked production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n+ CannotModifyRtngLineStockAtSubcErr: Label 'You cannot change this routing line because there are remaining components or WIP items transferred to the subcontractor for production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n \n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeDeleteEvent, '', false, false)]\n+ local procedure OnBeforeDeleteProdOrderRtngLine(var Rec: Record \"Prod. Order Routing Line\"; RunTrigger: Boolean)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n #endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if not RunTrigger then\n+ exit;\n+\n+ if Rec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(Rec);\n+ end;\n+\n [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnAfterDeleteEvent, '', false, false)]\n local procedure OnAfterDeleteProdOrderRtngLine(var Rec: Record \"Prod. Order Routing Line\"; RunTrigger: Boolean)\n begin\n@@ -49,10 +72,82 @@ codeunit 99001520 \"Subc. Prod. Order Rtng. Ext.\"\n if Rec.IsTemporary then\n exit;\n \n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"No.\" <> Rec.\"No.\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+\n if (xRec.\"No.\" <> Rec.\"No.\") and (Rec.\"Routing Link Code\" <> '') then\n SubcontractingManagement.UpdLinkedComponents(Rec, true);\n end;\n \n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Operation No.\", false, false)]\n+ local procedure OnBeforeValidateOperationNo(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"Operation No.\" <> Rec.\"Operation No.\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Routing Link Code\", false, false)]\n+ local procedure OnBeforeValidateRoutingLinkCode(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"Routing Link Code\" <> Rec.\"Routing Link Code\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Type\", false, false)]\n+ local procedure OnBeforeValidateType(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.Type <> Rec.Type) and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Transfer WIP Item\", false, false)]\n+ local procedure OnBeforeValidateTransferWIPItem(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"Transfer WIP Item\" <> Rec.\"Transfer WIP Item\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnAfterValidateEvent, \"Routing Link Code\", false, false)]\n local procedure OnAfterValidateRoutingLinkCode(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n begin\n@@ -150,4 +245,73 @@ codeunit 99001520 \"Subc. Prod. Order Rtng. Ext.\"\n SubcontractingManagement.DelLocationLinkedComponents(ProdOrderRoutingLine, false);\n end;\n end;\n-}\n\\ No newline at end of file\n+\n+ local procedure CheckSubcRtngLineDocumentsExist(ProdOrderRoutingLine: Record \"Prod. Order Routing Line\")\n+ var\n+ PurchaseLine: Record \"Purchase Line\";\n+ begin\n+ PurchaseLine.SetCurrentKey(\"Document Type\", Type, \"Prod. Order No.\", \"Prod. Order Line No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProdOrderRoutingLine.\"Prod. Order No.\");\n+ PurchaseLine.SetRange(\"Routing No.\", ProdOrderRoutingLine.\"Routing No.\");\n+ PurchaseLine.SetRange(\"Routing Reference No.\", ProdOrderRoutingLine.\"Routing Reference No.\");\n+ PurchaseLine.SetRange(\"Operation No.\", ProdOrderRoutingLine.\"Operation No.\");\n+ if PurchaseLine.FindSet() then\n+ repeat\n+ if HasSubcTransferForPurchLine(PurchaseLine) then\n+ Error(CannotModifyRtngLineTransferExistsErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+ if HasStockAtSubcLocation(PurchaseLine, ProdOrderRoutingLine) then\n+ Error(CannotModifyRtngLineStockAtSubcErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+ until PurchaseLine.Next() = 0;\n+ end;\n+\n+ local procedure HasSubcTransferForPurchLine(PurchaseLine: Record \"Purchase Line\"): Boolean\n+ var\n+ TransferLine: Record \"Transfer Line\";\n+ begin\n+ TransferLine.SetRange(\"Subc. Purch. Order No.\", PurchaseLine.\"Document No.\");\n+ TransferLine.SetRange(\"Subc. Purch. Order Line No.\", PurchaseLine.\"Line No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Order No.\", PurchaseLine.\"Prod. Order No.\");\n+ exit(not TransferLine.IsEmpty());\n+ end;\n+\n+ local procedure HasStockAtSubcLocation(PurchaseLine: Record \"Purchase Line\"; ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"): Boolean\n+ var\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ SubcWIPLedgerEntry: Record \"Subcontractor WIP Ledger Entry\";\n+ SubcTransferManagement: Codeunit \"Subc. Transfer Management\";\n+ NetStockAtSubcLocation: Decimal;\n+ begin\n+ ProdOrderComponent.SetCurrentKey(Status, \"Prod. Order No.\", \"Routing Link Code\");\n+ ProdOrderComponent.SetRange(Status, \"Production Order Status\"::Released);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", PurchaseLine.\"Prod. Order No.\");\n+ ProdOrderComponent.SetRange(\"Prod. Order Line No.\", PurchaseLine.\"Prod. Order Line No.\");\n+ ProdOrderComponent.SetRange(\"Component Supply Method\", ProdOrderComponent.\"Component Supply Method\"::\"Transfer to Vendor\");\n+ ProdOrderComponent.SetRange(\"Subc. Purchase Order Filter\", PurchaseLine.\"Document No.\");\n+ ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n+ ProdOrderComponent.SetAutoCalcFields(\"Subc. Qty. transf. to Subcontr\");\n+ if ProdOrderComponent.FindSet() then\n+ repeat\n+ if ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\" <> 0 then begin\n+ NetStockAtSubcLocation := ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\";\n+ NetStockAtSubcLocation -= SubcTransferManagement.CalcConsumedQtyAtSubcLocation(ProdOrderComponent);\n+ if NetStockAtSubcLocation > 0 then\n+ exit(true);\n+ end;\n+ until ProdOrderComponent.Next() = 0;\n+\n+ SubcWIPLedgerEntry.SetCurrentKey(\"Prod. Order No.\", \"Prod. Order Status\", \"Prod. Order Line No.\", \"Routing Reference No.\", \"Routing No.\", \"Operation No.\", \"Location Code\");\n+ SubcWIPLedgerEntry.SetRange(\"Prod. Order No.\", PurchaseLine.\"Prod. Order No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Prod. Order Status\", \"Production Order Status\"::Released);\n+ SubcWIPLedgerEntry.SetRange(\"Prod. Order Line No.\", PurchaseLine.\"Prod. Order Line No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Routing Reference No.\", ProdOrderRoutingLine.\"Routing Reference No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Routing No.\", ProdOrderRoutingLine.\"Routing No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Operation No.\", ProdOrderRoutingLine.\"Operation No.\");\n+ SubcWIPLedgerEntry.SetRange(\"In Transit\", false);\n+ SubcWIPLedgerEntry.CalcSums(\"Quantity (Base)\");\n+ if SubcWIPLedgerEntry.\"Quantity (Base)\" <> 0 then\n+ exit(true);\n+\n+ exit(false);\n+ end;\n+}\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al\nindex 40d3598456..41e67eba1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al\n@@ -104,6 +104,7 @@ codeunit 99001516 \"Subc. Req. Wksh. Make Ord.\"\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", RequisitionLine.\"Prod. Order Line No.\");\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n ProdOrderComponent.SetRange(\"Component Supply Method\", \"Component Supply Method\"::\"Vendor-Supplied\");\n+ ProdOrderComponent.SetLoadFields(\"Item No.\", \"Variant Code\", \"Remaining Quantity\");\n if ProdOrderComponent.FindSet() then\n repeat\n PurchaseLineComp.SetRange(\"Document Type\", PurchaseLine.\"Document Type\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al\nindex c84eace729..e90d3f7160 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al\n@@ -134,7 +134,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(Quantity) then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.Quantity = xRec.Quantity then\n@@ -160,7 +160,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"No.\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"No.\" = xRec.\"No.\" then\n@@ -186,7 +186,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Location Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Location Code\" = xRec.\"Location Code\" then\n@@ -212,7 +212,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Bin Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Bin Code\" = xRec.\"Bin Code\" then\n@@ -238,7 +238,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Variant Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Variant Code\" = xRec.\"Variant Code\" then\n@@ -264,7 +264,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Unit of Measure Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Unit of Measure Code\" = xRec.\"Unit of Measure Code\" then\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al\nindex 11e9867475..0918e43ef0 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al\n@@ -62,7 +62,7 @@ codeunit 99001544 \"Subc. Transfer Line Ext.\"\n if Rec.IsTemporary() then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Item No.\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Item No.\" = xRec.\"Item No.\" then\n@@ -85,7 +85,7 @@ codeunit 99001544 \"Subc. Transfer Line Ext.\"\n if Rec.IsTemporary() then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Variant Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Variant Code\" = xRec.\"Variant Code\" then\n@@ -108,7 +108,7 @@ codeunit 99001544 \"Subc. Transfer Line Ext.\"\n if Rec.IsTemporary() then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(Quantity) then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.Quantity = xRec.Quantity then\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al\nindex f6150f7b04..b6246cfb5d 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al\n@@ -389,6 +389,7 @@ codeunit 99001504 \"Subc. Transfer Management\"\n ProdOrderComponent.SetRange(\"Subc. Purchase Order Filter\", PurchaseLine.\"Document No.\");\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n ProdOrderComponent.SetRange(\"Component Supply Method\", ProdOrderComponent.\"Component Supply Method\"::\"Transfer to Vendor\");\n+ ProdOrderComponent.SetLoadFields(\"Subc. Qty. transf. to Subcontr\", \"Location Code\");\n ProdOrderComponent.SetAutoCalcFields(\"Subc. Qty. transf. to Subcontr\");\n if ProdOrderComponent.FindSet() then\n repeat\n@@ -407,7 +408,6 @@ codeunit 99001504 \"Subc. Transfer Management\"\n SubcWIPLedgerEntry.SetRange(\"Routing Reference No.\", PurchaseLine.\"Routing Reference No.\");\n SubcWIPLedgerEntry.SetRange(\"Routing No.\", PurchaseLine.\"Routing No.\");\n SubcWIPLedgerEntry.SetRange(\"Operation No.\", PurchaseLine.\"Operation No.\");\n-\n SubcWIPLedgerEntry.SetRange(\"In Transit\", false);\n SubcWIPLedgerEntry.CalcSums(\"Quantity (Base)\");\n if SubcWIPLedgerEntry.\"Quantity (Base)\" <> 0 then\n@@ -427,6 +427,7 @@ codeunit 99001504 \"Subc. Transfer Management\"\n ItemLedgerEntry.SetRange(\"Entry Type\", ItemLedgerEntry.\"Entry Type\"::Consumption);\n ItemLedgerEntry.SetRange(\"Prod. Order Comp. Line No.\", ProdOrderComponent.\"Line No.\");\n ItemLedgerEntry.SetRange(\"Location Code\", ProdOrderComponent.\"Location Code\");\n+ ItemLedgerEntry.SetLoadFields(Quantity);\n ItemLedgerEntry.CalcSums(Quantity);\n exit(-ItemLedgerEntry.Quantity);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139991, "functionName": ["CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithTransferToVendor", "CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithVendorSupplied"]}, {"codeunitID": 149915, "functionName": ["CannotModifyOrDeleteProdOrderComponentWhenTransferOrderExists"]}], "PASS_TO_PASS": [], "test_patch": "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\nindex f07c0afb34..0f6b7901b3 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcPurchSubcontTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcPurchSubcontTest.Codeunit.al\n@@ -510,6 +510,118 @@ codeunit 139991 \"Subc. Purch. Subcont. Test\"\n PostDirectTransferOrder(ReturnTransferHeader);\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoConfirmCreateProdOrderForSubcontractingProcess,HandleTransferOrder')]\n+ procedure CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithTransferToVendor()\n+ var\n+ Item: Record Item;\n+ HomeLocation: Record Location;\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderRtng: TestPage \"Prod. Order Routing\";\n+ begin\n+ // [SCENARIO] Modifying key fields or deleting a Prod. Order Routing Line must be blocked\n+ // when subcontracting transfer orders exist for Transfer to Vendor components.\n+ Initialize();\n+\n+ // [GIVEN] A subcontracting purchase order with a linked transfer order\n+ SetupSubContractingProdOrder(Item, HomeLocation, WorkCenter, MachineCenter, ProductionOrder, \"Component Supply Method\"::\"Transfer to Vendor\", LibraryRandom.RandIntInRange(1, 10));\n+ CreateSubcontractingPurchaseOrderForProdOrder(PurchaseHeader, PurchaseLine, Item, WorkCenter, ProductionOrder);\n+ CreateTransferOrderForPurchaseOrder(PurchaseHeader);\n+\n+ // [GIVEN] Find routing line for the subcontracting work center\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderRoutingLine.SetRange(\"Transfer WIP Item\", true);\n+#pragma warning restore AA0210\n+ ProdOrderRoutingLine.FindFirst();\n+\n+ // [THEN] Changing No. is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"No.\".SetValue(WorkCenter[1].\"No.\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Type is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.Type.SetValue(ProdOrderRoutingLine.Type::\"Machine Center\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Routing Link Code is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"Routing Link Code\".SetValue('');\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Deleting the routing line is blocked\n+ asserterror ProdOrderRoutingLine.Delete(true);\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('DoConfirmCreateProdOrderForSubcontractingProcess,HandleTransferOrder')]\n+ procedure CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithVendorSupplied()\n+ var\n+ Item: Record Item;\n+ HomeLocation: Record Location;\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderRtng: TestPage \"Prod. Order Routing\";\n+ begin\n+ // [SCENARIO] Modifying key fields or deleting a Prod. Order Routing Line must be blocked\n+ // when subcontracting transfer orders exist for Transfer to Vendor components.\n+ Initialize();\n+\n+ // [GIVEN] A subcontracting purchase order with a linked transfer order\n+ SetupSubContractingProdOrder(Item, HomeLocation, WorkCenter, MachineCenter, ProductionOrder, \"Component Supply Method\"::\"Vendor-Supplied\", LibraryRandom.RandIntInRange(1, 10));\n+ CreateSubcontractingPurchaseOrderForProdOrder(PurchaseHeader, PurchaseLine, Item, WorkCenter, ProductionOrder);\n+ CreateTransferOrderForPurchaseOrder(PurchaseHeader);\n+\n+ // [GIVEN] Find routing line for the subcontracting work center\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderRoutingLine.SetRange(\"Transfer WIP Item\", true);\n+#pragma warning restore AA0210\n+ ProdOrderRoutingLine.FindFirst();\n+\n+ // [THEN] Changing No. is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"No.\".SetValue(WorkCenter[1].\"No.\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Type is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.Type.SetValue(ProdOrderRoutingLine.Type::\"Machine Center\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Routing Link Code is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"Routing Link Code\".SetValue('');\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Deleting the routing line is blocked\n+ asserterror ProdOrderRoutingLine.Delete(true);\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ end;\n+\n [ModalPageHandler]\n procedure ItemTrackingLinesSimpleHandler(var ItemTrackingLines: TestPage \"Item Tracking Lines\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al\nindex ca4426c340..79a2777217 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al\n@@ -341,6 +341,58 @@ codeunit 149915 \"Subc. TransOrd. Reserv. Test\"\n Assert.AreEqual(30, TransferLine.\"Quantity (Base)\", 'Recreated transfer line must have the full component quantity');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting,HandleTransferOrder')]\n+ procedure CannotModifyOrDeleteProdOrderComponentWhenTransferOrderExists()\n+ var\n+ Item: Record Item;\n+ NewItem: Record Item;\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderCompPage: TestPage \"Prod. Order Components\";\n+ begin\n+ // [SCENARIO] Modifying key fields or deleting a Prod. Order Component with Component Supply Method = Transfer to Vendor\n+ // must be blocked when a subcontracting transfer order exists.\n+ Initialize();\n+\n+ // [GIVEN] A subcontracting transfer order linked to a production order with Transfer to Vendor components\n+ SetupTransferReservationScenario(Item, WorkCenter, MachineCenter, ProductionOrder, ProdOrderComponent, 10, 3, false);\n+ CreateSubcontractingPurchaseOrderAndReduceQuantity(Item, WorkCenter[2], ProductionOrder, PurchaseHeader, PurchaseLine, 0);\n+ CreateTransferOrder(PurchaseHeader);\n+\n+ // [GIVEN] Create another item to use for Item No. change\n+ LibraryInventory.CreateItem(NewItem);\n+\n+ // [THEN] Changing Item No. is blocked\n+ ProdOrderCompPage.OpenEdit();\n+ ProdOrderCompPage.GoToRecord(ProdOrderComponent);\n+ asserterror ProdOrderCompPage.\"Item No.\".SetValue(NewItem.\"No.\");\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ ProdOrderCompPage.Close();\n+\n+ // [THEN] Changing Quantity per is blocked\n+ ProdOrderCompPage.OpenEdit();\n+ ProdOrderCompPage.GoToRecord(ProdOrderComponent);\n+ asserterror ProdOrderCompPage.\"Quantity per\".SetValue(ProdOrderComponent.\"Quantity per\" + 1);\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ ProdOrderCompPage.Close();\n+\n+ // [THEN] Changing Component Supply Method is blocked\n+ ProdOrderCompPage.OpenEdit();\n+ ProdOrderCompPage.GoToRecord(ProdOrderComponent);\n+ asserterror ProdOrderCompPage.\"Component Supply Method\".SetValue(\"Component Supply Method\"::Empty);\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ ProdOrderCompPage.Close();\n+\n+ // [THEN] Deleting the component is blocked\n+ asserterror ProdOrderComponent.Delete(true);\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. TransOrd. Reserv. Test\");\n"} -{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8386", "base_commit": "34cc7ccdc6ab40f6212196856671d9f4c531677b", "created_at": "2026-06-01T09:42:51Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Shopify\\App", "src\\Apps\\W1\\Shopify\\Test"], "patch": "diff --git a/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al b/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al\nindex b4508e5546..884b8bdd71 100644\n--- a/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al\n@@ -88,7 +88,8 @@ codeunit 30281 \"Shpfy Bulk UpdateProductPrice\" implements \"Shpfy IBulk Operation\n ShopifyVariant.Price := JVariant.GetDecimal('price');\n ShopifyVariant.\"Compare at Price\" := JVariant.GetDecimal('compareAtPrice');\n ShopifyVariant.\"Updated At\" := JVariant.GetDateTime('updatedAt');\n- ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n+ if JVariant.Contains('unitCost') then\n+ ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n ShopifyVariant.Modify();\n end;\n end;\ndiff --git a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\nindex cee48d5400..91bcde34a8 100644\n--- a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\n@@ -894,7 +894,8 @@ codeunit 30178 \"Shpfy Product Export\"\n ShopifyVariant.Price := JVariant.GetDecimal('price');\n ShopifyVariant.\"Compare at Price\" := JVariant.GetDecimal('compareAtPrice');\n ShopifyVariant.\"Updated At\" := JVariant.GetDateTime('updatedAt');\n- ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n+ if JVariant.Contains('unitCost') then\n+ ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n ShopifyVariant.Modify();\n end;\n exit;\n", "FAIL_TO_PASS": [{"codeunitID": 139633, "functionName": ["TestBulkOperationRevertFailedWithLegacyRequestDataMissingUnitCost"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al\nindex 86c7a952fd..6a6e049ec0 100644\n--- a/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al\n+++ b/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al\n@@ -314,6 +314,70 @@ codeunit 139633 \"Shpfy Bulk Operations Test\"\n ClearSetup();\n end;\n \n+ [Test]\n+ [HandlerFunctions('BulkOperationHttpHandler')]\n+ procedure TestBulkOperationRevertFailedWithLegacyRequestDataMissingUnitCost()\n+ var\n+ ShopifyVariant: Record \"Shpfy Variant\";\n+ BulkOperation: Record \"Shpfy Bulk Operation\";\n+ BulkOperationType: Enum \"Shpfy Bulk Operation Type\";\n+ ProductId: BigInteger;\n+ VariantId: BigInteger;\n+ VariantIds: List of [BigInteger];\n+ Index: Integer;\n+ begin\n+ // [SCENARIO] A bulk operation persisted before the unitCost key was added still\n+ // completes its revert without throwing, leaving Unit Cost untouched.\n+ // Regression for bug 637250.\n+\n+ // [GIVEN] A bulk operation whose request data was written by the pre-unitCost code\n+ // (i.e. the JSON objects only contain id/price/compareAtPrice/updatedAt) and four variants\n+ Initialize();\n+ for Index := 1 to 4 do begin\n+ ProductId := Any.IntegerInRange(100000, 555555);\n+ VariantId := Any.IntegerInRange(100000, 555555);\n+ VariantIds.Add(VariantId);\n+ ShopifyVariant.\"Product Id\" := ProductId;\n+ ShopifyVariant.Id := VariantId;\n+ ShopifyVariant.Price := 200;\n+ ShopifyVariant.\"Compare at Price\" := 250;\n+ ShopifyVariant.\"Unit Cost\" := 75;\n+ ShopifyVariant.Insert();\n+ end;\n+ BulkOperationUrl := 'https://storage.googleapis.com/shopify-bulk-result/' + Any.AlphabeticText(20);\n+ BulkOperation := CreateBulkOperation(BulkOperationId1, BulkOperationType::UpdateProductPrice, Shop.Code, BulkOperationUrl, GenerateLegacyRequestDataWithoutUnitCost(VariantIds, 100, 150));\n+\n+ // [WHEN] Bulk operation is completed\n+ BulkOperationIdCurrent := BulkOperationId1;\n+ VariantId1 := VariantIds.Get(1);\n+ VariantId2 := VariantIds.Get(4);\n+ BulkOperation.Status := BulkOperation.Status::Completed;\n+ BulkOperation.Modify(true);\n+\n+ // [THEN] The bulk operation is processed without throwing on the missing unitCost key,\n+ // failed variants have their Price/Compare at Price reverted, and Unit Cost is left\n+ // untouched on every variant (since the legacy blob doesn't know the pre-update value).\n+ BulkOperation.Get(BulkOperationId1, Shop.Code, BulkOperation.Type::mutation);\n+ LibraryAssert.IsTrue(BulkOperation.Processed, 'Bulk operation should be processed.');\n+ ShopifyVariant.Get(VariantIds.Get(1));\n+ LibraryAssert.AreEqual(200, ShopifyVariant.Price, 'Variant price should not be reverted.');\n+ LibraryAssert.AreEqual(250, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should not be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ShopifyVariant.Get(VariantIds.Get(2));\n+ LibraryAssert.AreEqual(100, ShopifyVariant.Price, 'Variant price should be reverted.');\n+ LibraryAssert.AreEqual(150, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ShopifyVariant.Get(VariantIds.Get(3));\n+ LibraryAssert.AreEqual(100, ShopifyVariant.Price, 'Variant price should be reverted.');\n+ LibraryAssert.AreEqual(150, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ShopifyVariant.Get(VariantIds.Get(4));\n+ LibraryAssert.AreEqual(200, ShopifyVariant.Price, 'Variant price should not be reverted.');\n+ LibraryAssert.AreEqual(250, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should not be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ClearSetup();\n+ end;\n+\n [Test]\n procedure TestBulkUpdateProductPriceClearsCompareAtPriceAsNull()\n var\n@@ -495,6 +559,26 @@ codeunit 139633 \"Shpfy Bulk Operations Test\"\n exit(RequestData);\n end;\n \n+ local procedure GenerateLegacyRequestDataWithoutUnitCost(VariantIds: List of [BigInteger]; Price: Decimal; CompareAtPrice: Decimal): JsonArray\n+ var\n+ RequestData: JsonArray;\n+ VariantId: BigInteger;\n+ Data: JsonObject;\n+ begin\n+ // Simulates the request-data layout written by the connector before the unitCost key\n+ // was added to the bulk-operation rollback bookkeeping. Used to test that the revert\n+ // tolerates legacy blobs persisted before the upgrade.\n+ foreach VariantId in VariantIds do begin\n+ Clear(Data);\n+ Data.Add('id', VariantId);\n+ Data.Add('price', Price);\n+ Data.Add('compareAtPrice', CompareAtPrice);\n+ Data.Add('updatedAt', '2025-02-25T13:40:15.6530000Z');\n+ RequestData.Add(Data);\n+ end;\n+ exit(RequestData);\n+ end;\n+\n local procedure EnqueueGraphQLResponsesForSendBulkMutation()\n begin\n GraphQLResponses.Enqueue('StagedUpload');\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8616", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-06-15T21:29:21Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al\nindex 2631e38aec..8af3d51e41 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Install/SubcontractingInstall.Codeunit.al\n@@ -4,7 +4,6 @@\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting;\n \n-using Microsoft.QualityManagement.Setup.ApplicationAreas;\n using System.Upgrade;\n \n codeunit 99001501 \"Subcontracting Install\"\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al b/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al\nindex 74a24a8bf0..42b5428962 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Permissions/SubcontractObjs.PermissionSet.al\n@@ -3,8 +3,8 @@\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting;\n+\n using Microsoft.Manufacturing.Planning;\n-using Microsoft.QualityManagement.Setup.ApplicationAreas;\n \n permissionset 99001501 \"Subcontract. - Objs\"\n {\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al\nindex 260fe4b050..d1d232c956 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Pageextensions/SubcILEntries.PageExt.al\n@@ -49,6 +49,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Production Order';\n+ Enabled = Rec.\"Subc. Prod. Order No.\" <> '';\n Image = Production;\n ToolTip = 'View the related production order.';\n trigger OnAction()\n@@ -60,6 +61,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Production Order Routing';\n+ Enabled = Rec.\"Subc. Prod. Order No.\" <> '';\n Image = Route;\n ToolTip = 'View the related production order routing.';\n trigger OnAction()\n@@ -71,6 +73,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Production Order Components';\n+ Enabled = Rec.\"Subc. Prod. Order No.\" <> '';\n Image = Components;\n ToolTip = 'View the related production order components.';\n trigger OnAction()\n@@ -82,6 +85,7 @@ pageextension 99001501 \"Subc. ILEntries\" extends \"Item Ledger Entries\"\n {\n ApplicationArea = Subcontracting;\n Caption = 'Subcontracting Purchase Order';\n+ Enabled = Rec.\"Subc. Purch. Order No.\" <> '';\n Image = Order;\n ToolTip = 'View the related subcontracting purchase order.';\n trigger OnAction()\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al\nindex 3449fe2689..88abec2181 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaMgmt.Codeunit.al\n@@ -2,7 +2,7 @@\n // Copyright (c) Microsoft Corporation. All rights reserved.\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n-namespace Microsoft.QualityManagement.Setup.ApplicationAreas;\n+namespace Microsoft.Manufacturing.Subcontracting;\n \n #if not CLEAN29\n using Microsoft.Manufacturing.Setup;\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al\nindex 109321363f..6551dec314 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Setup/ApplicationAreas/SubcApplicationAreaSetup.TableExt.al\n@@ -2,7 +2,7 @@\n // Copyright (c) Microsoft Corporation. All rights reserved.\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n-namespace Microsoft.QualityManagement.Setup.ApplicationAreas;\n+namespace Microsoft.Manufacturing.Subcontracting;\n \n using System.Environment.Configuration;\n \n", "FAIL_TO_PASS": [{"codeunitID": 139990, "functionName": ["ItemLedgerEntriesSubcActionsEnabledWhenSubcontracting", "ItemLedgerEntriesSubcActionsDisabledWhenNotSubcontracting"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al\nindex 46606182df..c598c8c43c 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingUITest.Codeunit.al\n@@ -4,6 +4,7 @@\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting.Test;\n \n+using Microsoft.Inventory.Ledger;\n using Microsoft.Inventory.Planning;\n using Microsoft.Inventory.Requisition;\n using Microsoft.Manufacturing.Capacity;\n@@ -588,6 +589,91 @@ codeunit 139990 \"Subc. Subcontracting UI Test\"\n PurchaseOrder.Close();\n end;\n \n+ [Test]\n+ procedure ItemLedgerEntriesSubcActionsDisabledWhenNotSubcontracting()\n+ var\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ ItemLedgerEntries: TestPage \"Item Ledger Entries\";\n+ begin\n+ // [SCENARIO 638458] Subcontracting actions on Item Ledger Entries are disabled when the entry has no subcontracting production order or purchase order.\n+ Initialize();\n+\n+ // [GIVEN] An Item Ledger Entry that is NOT related to subcontracting (no Subc. Prod. Order No. or Subc. Purch. Order No.)\n+ ItemLedgerEntry.Init();\n+ ItemLedgerEntry.\"Entry No.\" := GetNextItemLedgerEntryNo();\n+ ItemLedgerEntry.\"Item No.\" := 'TEST-ITEM';\n+ ItemLedgerEntry.\"Entry Type\" := ItemLedgerEntry.\"Entry Type\"::Purchase;\n+ ItemLedgerEntry.\"Subc. Prod. Order No.\" := '';\n+ ItemLedgerEntry.\"Subc. Purch. Order No.\" := '';\n+ ItemLedgerEntry.Insert();\n+\n+ // [WHEN] The Item Ledger Entries page is opened for that entry\n+ ItemLedgerEntries.OpenView();\n+ ItemLedgerEntries.GoToRecord(ItemLedgerEntry);\n+\n+ // [THEN] The Production Order action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Production Order\".Enabled(), ILEProdActionsEnabledErr);\n+ // [THEN] The Production Order Routing action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Production Order Routing\".Enabled(), ILEProdActionsEnabledErr);\n+ // [THEN] The Production Order Components action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Production Order Components\".Enabled(), ILEProdActionsEnabledErr);\n+ // [THEN] The Purchase Order action is disabled\n+ Assert.IsFalse(ItemLedgerEntries.\"Purchase Order\".Enabled(), ILEPurchActionsEnabledErr);\n+\n+ ItemLedgerEntries.Close();\n+\n+ // Cleanup\n+ ItemLedgerEntry.Delete();\n+ end;\n+\n+ [Test]\n+ procedure ItemLedgerEntriesSubcActionsEnabledWhenSubcontracting()\n+ var\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ ItemLedgerEntries: TestPage \"Item Ledger Entries\";\n+ begin\n+ // [SCENARIO 638458] Subcontracting actions on Item Ledger Entries are enabled when the entry is related to a subcontracting production order and purchase order.\n+ Initialize();\n+\n+ // [GIVEN] An Item Ledger Entry that IS related to subcontracting\n+ ItemLedgerEntry.Init();\n+ ItemLedgerEntry.\"Entry No.\" := GetNextItemLedgerEntryNo();\n+ ItemLedgerEntry.\"Item No.\" := 'TEST-ITEM';\n+ ItemLedgerEntry.\"Entry Type\" := ItemLedgerEntry.\"Entry Type\"::Purchase;\n+ ItemLedgerEntry.\"Subc. Prod. Order No.\" := 'PO-SUBC-001';\n+ ItemLedgerEntry.\"Subc. Prod. Order Line No.\" := 10000;\n+ ItemLedgerEntry.\"Subc. Purch. Order No.\" := 'PURCH-SUBC-001';\n+ ItemLedgerEntry.\"Subc. Purch. Order Line No.\" := 10000;\n+ ItemLedgerEntry.Insert();\n+\n+ // [WHEN] The Item Ledger Entries page is opened for that entry\n+ ItemLedgerEntries.OpenView();\n+ ItemLedgerEntries.GoToRecord(ItemLedgerEntry);\n+\n+ // [THEN] The Production Order action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Production Order\".Enabled(), ILEProdActionsNotEnabledErr);\n+ // [THEN] The Production Order Routing action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Production Order Routing\".Enabled(), ILEProdActionsNotEnabledErr);\n+ // [THEN] The Production Order Components action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Production Order Components\".Enabled(), ILEProdActionsNotEnabledErr);\n+ // [THEN] The Purchase Order action is enabled\n+ Assert.IsTrue(ItemLedgerEntries.\"Purchase Order\".Enabled(), ILEPurchActionsNotEnabledErr);\n+\n+ ItemLedgerEntries.Close();\n+\n+ // Cleanup\n+ ItemLedgerEntry.Delete();\n+ end;\n+\n+ local procedure GetNextItemLedgerEntryNo(): Integer\n+ var\n+ ItemLedgerEntry: Record \"Item Ledger Entry\";\n+ begin\n+ if ItemLedgerEntry.FindLast() then\n+ exit(ItemLedgerEntry.\"Entry No.\" + 1);\n+ exit(1);\n+ end;\n+\n var\n Assert: Codeunit Assert;\n LibraryERMCountryData: Codeunit \"Library - ERM Country Data\";\n@@ -602,4 +688,8 @@ codeunit 139990 \"Subc. Subcontracting UI Test\"\n SubcontractingActionsEnabledErr: Label 'Subcontractor Prices action should not be enabled for a non-subcontracting Work Center.';\n SubcontractingActionsNotVisibleErr: Label 'Subcontractor Prices action should be visible for a subcontracting Work Center.';\n SubcontractingActionsNotEnabledErr: Label 'Subcontractor Prices action should be enabled for a subcontracting Work Center.';\n+ ILEProdActionsEnabledErr: Label 'Production actions should not be enabled for a non-subcontracting Item Ledger Entry.';\n+ ILEProdActionsNotEnabledErr: Label 'Production actions should be enabled for a subcontracting Item Ledger Entry.';\n+ ILEPurchActionsEnabledErr: Label 'Purchase Order action should not be enabled for a non-subcontracting Item Ledger Entry.';\n+ ILEPurchActionsNotEnabledErr: Label 'Purchase Order action should be enabled for a subcontracting Item Ledger Entry.';\n }\n\\ No newline at end of file\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8612", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-06-15T14:26:39Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\nindex b6de5b5ea0..6a958ce4b4 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcPurchaseOrderCreator.Codeunit.al\n@@ -39,7 +39,6 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n PurchOrderCreatedPluralTxt: Label '%1 purchase orders were created.\\\\Do you want to view them?', Comment = '%1 = number of purchase orders created';\n PurchOrderAlreadyCreatedQst: Label 'Purchase orders have already been created.\\\\Do you want to view them?';\n CreationOfSubcontractingOrderIsNotAllowedErr: Label 'You cannot create Subcontracting Order, because the Production Order %1 is not released.', Comment = '%1=Production Order No.';\n- NoProdOrderLineWithRemQtyErr: Label 'No Prod. Order Line with Remaining Quantity.';\n BlankLocationConfirmQst: Label 'One or more Prod. Order Components with Component Supply Method Transfer to Vendor have a blank Location Code. Without a Location Code, you will not be able to create a transfer order to send the components to the subcontractor.\\\\Do you want to create the Subcontracting Order anyway?';\n SameAsSubcLocConfirmQst: Label 'One or more Prod. Order Components with Component Supply Method Transfer to Vendor have Location Code %1, which is the same as the Subcontracting Location Code of vendor %2. A transfer order cannot be created from and to the same location.\\\\Do you want to create the Subcontracting Order anyway?', Comment = '%1=Component Location Code, %2=Vendor No.';\n NotEnoughSpaceErr: Label 'There is not enough space to insert the subcontracting info line.';\n@@ -61,7 +60,8 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n ManufacturingSetup.TestField(\"Subcontracting Template Name\");\n ManufacturingSetup.TestField(\"Subcontracting Batch Name\");\n \n- CheckProdOrderRtngLine(ProdOrderRoutingLine, ProdOrderLine);\n+ if not CheckProdOrderRtngLine(ProdOrderRoutingLine, ProdOrderLine) then\n+ exit(0);\n \n if not CheckProdOrderComponentLines(ProdOrderRoutingLine) then\n exit;\n@@ -259,7 +259,7 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n Clear(RoutingReferenceNo);\n end;\n \n- local procedure CheckProdOrderRtngLine(ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\")\n+ local procedure CheckProdOrderRtngLine(ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"; var ProdOrderLine: Record \"Prod. Order Line\"): Boolean\n var\n WorkCenter: Record \"Work Center\";\n begin\n@@ -273,12 +273,13 @@ codeunit 99001557 \"Subc. Purchase Order Creator\"\n ProdOrderLine.SetRange(\"Routing Reference No.\", ProdOrderRoutingLine.\"Routing Reference No.\");\n ProdOrderLine.SetFilter(\"Remaining Quantity\", '<>%1', 0);\n if ProdOrderLine.IsEmpty() then\n- Error(NoProdOrderLineWithRemQtyErr);\n+ exit(false);\n \n WorkCenter.SetLoadFields(\"Gen. Prod. Posting Group\", \"Subcontractor No.\");\n WorkCenter.Get(ProdOrderRoutingLine.\"Work Center No.\");\n WorkCenter.TestField(\"Subcontractor No.\");\n WorkCenter.TestField(\"Gen. Prod. Posting Group\");\n+ exit(true);\n end;\n \n internal procedure ShowExistingPurchaseOrdersForRoutingLines(var ProdOrderRoutingLine: Record \"Prod. Order Routing Line\")\n", "FAIL_TO_PASS": [{"codeunitID": 139989, "functionName": ["ShowExistingPurchOrdersAfterReceiptDoesNotError"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\nindex 950c628cf5..c2ad504090 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcSubcontractingTest.Codeunit.al\n@@ -2774,6 +2774,50 @@ codeunit 139989 \"Subc. Subcontracting Test\"\n Assert.IsFalse(PurchaseOrderPageOpened, 'Purchase Order card should not open when purchase orders already exist.');\n end;\n \n+ [Test]\n+ [HandlerFunctions('ConfirmYesShowSubcontractingPurchOrders,HandlePurchaseOrderPage,HandlePurchaseLinesPage')]\n+ procedure ShowExistingPurchOrdersAfterReceiptDoesNotError()\n+ var\n+ Item: Record Item;\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ begin\n+ // [SCENARIO 637777] Re-running Create Subcontracting Order after fully receiving the existing subcontracting purchase order should offer to view the existing order instead of raising \"No Prod. Order Line with Remaining Quantity.\"\n+\n+ // [GIVEN] Manufacturing setup with subcontracting work center, item with routing/BOM, released production order, and a created subcontracting purchase order\n+ Initialize();\n+ Subcontracting := true;\n+ UnitCostCalculation := UnitCostCalculation::Units;\n+ CreateAndCalculateNeededWorkAndMachineCenter(WorkCenter, MachineCenter);\n+ CreateItemForProductionIncludeRoutingAndProdBOM(Item, WorkCenter, MachineCenter);\n+ SubcontractingMgmtLibrary.CreateAndRefreshProductionOrder(\n+ ProductionOrder, \"Production Order Status\"::Released, ProductionOrder.\"Source Type\"::Item, Item.\"No.\", LibraryRandom.RandInt(10) + 5);\n+ UpdateSubMgmtSetupWithReqWkshTemplate();\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ PurchaseLine.SetRange(\"Work Center No.\", WorkCenter[2].\"No.\");\n+#pragma warning restore AA0210\n+ PurchaseLine.FindFirst();\n+ PurchaseHeader.Get(PurchaseLine.\"Document Type\", PurchaseLine.\"Document No.\");\n+ EnsureGeneralPostingSetupIsValid(PurchaseLine.\"Gen. Bus. Posting Group\", PurchaseLine.\"Gen. Prod. Posting Group\");\n+\n+ // [GIVEN] The existing subcontracting purchase order is fully received\n+ LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, false);\n+\n+ // [WHEN] Create Subcontracting Order is invoked again from the same routing line\n+ PurchaseLinesPageOpened := false;\n+ SubcontractingMgmtLibrary.CreateSubcontractingOrderFromProdOrderRtngPage(Item.\"Routing No.\", WorkCenter[2].\"No.\");\n+\n+ // [THEN] The existing purchase lines are shown and no raw remaining-quantity error is raised\n+ Assert.IsTrue(PurchaseLinesPageOpened, 'Purchase Lines list should open when the subcontracting purchase order already exists after full receipt.');\n+ end;\n+\n [Test]\n procedure StandardTaskCodePropagatedAndDrivesSubcPriceLookup()\n var\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8600", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-06-12T15:07:44Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Subcontracting\\App", "src\\Apps\\W1\\Subcontracting\\Test"], "patch": "diff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al\nindex 3d906b1720..bb2d4555e8 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderCompExt.Codeunit.al\n@@ -25,6 +25,8 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n ExistingPurchLineErr: Label 'You cannot change this field because the component is already assigned to subcontracting purchase order %1.\\\\Updating the quantity is only allowed through the purchase order.', Comment = '%1=Document No';\n ExistingTransferLineQst: Label 'The component has already been assigned to the subcontracting transfer order %1.\\\\The quantity may only be updated via the purchase order and processing of the stock transfer.', Comment = '%1=Transfer Order No';\n ExistingTransferLineErr: Label 'You cannot open Tracking Specification because this component is already specified in Transfer Order %1.', Comment = '%1=Document No.';\n+ CannotModifyCompTransferExistsErr: Label 'You cannot change this component because transfer orders exist for the linked production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n+ CannotModifyCompStockAtSubcErr: Label 'You cannot change this component because there are remaining components or WIP items transferred to the subcontractor for production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n \n [EventSubscriber(ObjectType::Codeunit, Codeunit::\"Prod. Order Comp.-Reserve\", OnAfterInitFromProdOrderComp, '', false, false)]\n local procedure OnAfterInitFromProdOrderComp(ProdOrderComponent: Record \"Prod. Order Component\")\n@@ -92,6 +94,65 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n if Rec.IsTemporary then\n exit;\n CheckExistingSubcontractingTransferOrder(Rec, xRec, CurrFieldNo);\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Location Code\" <> xRec.\"Location Code\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Bin Code\", false, false)]\n+ local procedure OnBeforeValidateBinCode(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Bin Code\" <> xRec.\"Bin Code\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Item No.\", false, false)]\n+ local procedure OnBeforeValidateItemNo(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Item No.\" <> xRec.\"Item No.\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Variant Code\", false, false)]\n+ local procedure OnBeforeValidateVariantCode(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Variant Code\" <> xRec.\"Variant Code\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n end;\n \n [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Quantity per\", false, false)]\n@@ -106,6 +167,65 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n if Rec.IsTemporary then\n exit;\n CheckExistingDocumentsForSubcontracting(Rec, xRec, CurrFieldNo);\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Quantity per\" <> xRec.\"Quantity per\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Expected Quantity\", false, false)]\n+ local procedure OnBeforeValidateExpectedQuantity(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Expected Quantity\" <> xRec.\"Expected Quantity\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeValidateEvent, \"Component Supply Method\", false, false)]\n+ local procedure OnBeforeValidateComponentSupplyMethod(var Rec: Record \"Prod. Order Component\"; var xRec: Record \"Prod. Order Component\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if Rec.\"Component Supply Method\" <> xRec.\"Component Supply Method\" then\n+ if xRec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Component\", OnBeforeDeleteEvent, '', false, false)]\n+ local procedure OnBeforeDeleteProdOrderComponent(var Rec: Record \"Prod. Order Component\"; RunTrigger: Boolean)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+ if not RunTrigger then\n+ exit;\n+\n+ if Rec.\"Component Supply Method\" = Rec.\"Component Supply Method\"::\"Transfer to Vendor\" then\n+ CheckUncompletedSubcontractingDocumentsExist(Rec);\n end;\n \n local procedure CheckExistingPostedSubcontractingTransferOrder(ProdOrderComponent: Record \"Prod. Order Component\"): Boolean\n@@ -364,4 +484,66 @@ codeunit 99001524 \"Subc. Prod. Order Comp. Ext.\"\n CheckExistingSubcontractingPurchaseOrder(ProdOrderComponent);\n end;\n end;\n+\n+ local procedure CheckUncompletedSubcontractingDocumentsExist(ProdOrderComponent: Record \"Prod. Order Component\")\n+ var\n+ ProdOrderLine: Record \"Prod. Order Line\";\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ begin\n+ ProdOrderLine.SetLoadFields(\"Routing Reference No.\", \"Routing No.\");\n+ if not ProdOrderLine.Get(ProdOrderComponent.Status, ProdOrderComponent.\"Prod. Order No.\", ProdOrderComponent.\"Prod. Order Line No.\") then\n+ exit;\n+\n+ PurchaseLine.SetCurrentKey(\"Document Type\", Type, \"Prod. Order No.\", \"Prod. Order Line No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProdOrderComponent.\"Prod. Order No.\");\n+ PurchaseLine.SetRange(\"Prod. Order Line No.\", ProdOrderComponent.\"Prod. Order Line No.\");\n+\n+ if ProdOrderComponent.\"Routing Link Code\" <> '' then begin\n+ ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProdOrderLine.\"Prod. Order No.\");\n+ ProdOrderRoutingLine.SetRange(\"Routing Reference No.\", ProdOrderLine.\"Routing Reference No.\");\n+ ProdOrderRoutingLine.SetRange(\"Routing Link Code\", ProdOrderComponent.\"Routing Link Code\");\n+ ProdOrderRoutingLine.SetLoadFields(\"Operation No.\");\n+ if ProdOrderRoutingLine.FindFirst() then\n+ PurchaseLine.SetRange(\"Operation No.\", ProdOrderRoutingLine.\"Operation No.\");\n+ end;\n+\n+ if PurchaseLine.FindSet() then\n+ repeat\n+ if HasSubcTransferForPurchLine(PurchaseLine, ProdOrderComponent) then\n+ Error(CannotModifyCompTransferExistsErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+\n+ ProdOrderComponent.SetRange(\"Subc. Purchase Order Filter\", PurchaseLine.\"Document No.\");\n+ if HasStockAtSubcLocationForComponentForPurchLine(ProdOrderComponent) then\n+ Error(CannotModifyCompStockAtSubcErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+ until PurchaseLine.Next() = 0;\n+ end;\n+\n+ local procedure HasSubcTransferForPurchLine(PurchaseLine: Record \"Purchase Line\"; ProdOrderComponent: Record \"Prod. Order Component\"): Boolean\n+ var\n+ TransferLine: Record \"Transfer Line\";\n+ begin\n+ TransferLine.SetCurrentKey(\"Subc. Purch. Order No.\", \"Subc. Prod. Order No.\", \"Subc. Prod. Order Line No.\", \"Subc. Operation No.\");\n+ TransferLine.SetRange(\"Subc. Purch. Order No.\", PurchaseLine.\"Document No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Order No.\", ProdOrderComponent.\"Prod. Order No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Order Line No.\", ProdOrderComponent.\"Prod. Order Line No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Ord. Comp Line No.\", ProdOrderComponent.\"Line No.\");\n+ exit(not TransferLine.IsEmpty());\n+ end;\n+\n+ local procedure HasStockAtSubcLocationForComponentForPurchLine(ProdOrderComponent: Record \"Prod. Order Component\"): Boolean\n+ var\n+ SubcTransferManagement: Codeunit \"Subc. Transfer Management\";\n+ NetStockAtSubcLocation: Decimal;\n+ begin\n+ ProdOrderComponent.CalcFields(\"Subc. Qty. transf. to Subcontr\");\n+ if ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\" = 0 then\n+ exit(false);\n+\n+ NetStockAtSubcLocation := ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\";\n+ NetStockAtSubcLocation -= SubcTransferManagement.CalcConsumedQtyAtSubcLocation(ProdOrderComponent);\n+ exit(NetStockAtSubcLocation > 0);\n+ end;\n }\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al\nindex e7e85257d3..0c886fc5ec 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcProdOrderRtngExt.Codeunit.al\n@@ -1,22 +1,45 @@\n-// ------------------------------------------------------------------------------------------------\n+// ------------------------------------------------------------------------------------------------\n // Copyright (c) Microsoft Corporation. All rights reserved.\n // Licensed under the MIT License. See License.txt in the project root for license information.\n // ------------------------------------------------------------------------------------------------\n namespace Microsoft.Manufacturing.Subcontracting;\n \n+using Microsoft.Inventory.Transfer;\n using Microsoft.Manufacturing.Document;\n using Microsoft.Manufacturing.Routing;\n using Microsoft.Manufacturing.WorkCenter;\n+using Microsoft.Purchases.Document;\n \n codeunit 99001520 \"Subc. Prod. Order Rtng. Ext.\"\n {\n-#if not CLEAN29\n var\n+#if not CLEAN29\n #pragma warning disable AL0432\n SubcFeatureFlagHandler: Codeunit \"Subc. Feature Flag Handler\";\n #pragma warning restore AL0432\n+#endif\n+ CannotModifyRtngLineTransferExistsErr: Label 'You cannot change this routing line because transfer orders exist for the linked production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n+ CannotModifyRtngLineStockAtSubcErr: Label 'You cannot change this routing line because there are remaining components or WIP items transferred to the subcontractor for production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';\n \n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeDeleteEvent, '', false, false)]\n+ local procedure OnBeforeDeleteProdOrderRtngLine(var Rec: Record \"Prod. Order Routing Line\"; RunTrigger: Boolean)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n #endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if not RunTrigger then\n+ exit;\n+\n+ if Rec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(Rec);\n+ end;\n+\n [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnAfterDeleteEvent, '', false, false)]\n local procedure OnAfterDeleteProdOrderRtngLine(var Rec: Record \"Prod. Order Routing Line\"; RunTrigger: Boolean)\n begin\n@@ -49,10 +72,82 @@ codeunit 99001520 \"Subc. Prod. Order Rtng. Ext.\"\n if Rec.IsTemporary then\n exit;\n \n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"No.\" <> Rec.\"No.\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+\n if (xRec.\"No.\" <> Rec.\"No.\") and (Rec.\"Routing Link Code\" <> '') then\n SubcontractingManagement.UpdLinkedComponents(Rec, true);\n end;\n \n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Operation No.\", false, false)]\n+ local procedure OnBeforeValidateOperationNo(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"Operation No.\" <> Rec.\"Operation No.\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Routing Link Code\", false, false)]\n+ local procedure OnBeforeValidateRoutingLinkCode(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"Routing Link Code\" <> Rec.\"Routing Link Code\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Type\", false, false)]\n+ local procedure OnBeforeValidateType(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.Type <> Rec.Type) and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n+ [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnBeforeValidateEvent, \"Transfer WIP Item\", false, false)]\n+ local procedure OnBeforeValidateTransferWIPItem(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n+ begin\n+#if not CLEAN29\n+#pragma warning disable AL0432\n+ if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then\n+#pragma warning restore AL0432\n+ exit;\n+#endif\n+ if Rec.IsTemporary then\n+ exit;\n+\n+ if CurrFieldNo <> 0 then\n+ if (xRec.\"Transfer WIP Item\" <> Rec.\"Transfer WIP Item\") and xRec.\"Transfer WIP Item\" then\n+ CheckSubcRtngLineDocumentsExist(xRec);\n+ end;\n+\n [EventSubscriber(ObjectType::Table, Database::\"Prod. Order Routing Line\", OnAfterValidateEvent, \"Routing Link Code\", false, false)]\n local procedure OnAfterValidateRoutingLinkCode(var Rec: Record \"Prod. Order Routing Line\"; var xRec: Record \"Prod. Order Routing Line\"; CurrFieldNo: Integer)\n begin\n@@ -150,4 +245,73 @@ codeunit 99001520 \"Subc. Prod. Order Rtng. Ext.\"\n SubcontractingManagement.DelLocationLinkedComponents(ProdOrderRoutingLine, false);\n end;\n end;\n-}\n\\ No newline at end of file\n+\n+ local procedure CheckSubcRtngLineDocumentsExist(ProdOrderRoutingLine: Record \"Prod. Order Routing Line\")\n+ var\n+ PurchaseLine: Record \"Purchase Line\";\n+ begin\n+ PurchaseLine.SetCurrentKey(\"Document Type\", Type, \"Prod. Order No.\", \"Prod. Order Line No.\");\n+ PurchaseLine.SetRange(\"Document Type\", PurchaseLine.\"Document Type\"::Order);\n+ PurchaseLine.SetRange(\"Prod. Order No.\", ProdOrderRoutingLine.\"Prod. Order No.\");\n+ PurchaseLine.SetRange(\"Routing No.\", ProdOrderRoutingLine.\"Routing No.\");\n+ PurchaseLine.SetRange(\"Routing Reference No.\", ProdOrderRoutingLine.\"Routing Reference No.\");\n+ PurchaseLine.SetRange(\"Operation No.\", ProdOrderRoutingLine.\"Operation No.\");\n+ if PurchaseLine.FindSet() then\n+ repeat\n+ if HasSubcTransferForPurchLine(PurchaseLine) then\n+ Error(CannotModifyRtngLineTransferExistsErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+ if HasStockAtSubcLocation(PurchaseLine, ProdOrderRoutingLine) then\n+ Error(CannotModifyRtngLineStockAtSubcErr, PurchaseLine.\"Prod. Order No.\", PurchaseLine.\"Document No.\");\n+ until PurchaseLine.Next() = 0;\n+ end;\n+\n+ local procedure HasSubcTransferForPurchLine(PurchaseLine: Record \"Purchase Line\"): Boolean\n+ var\n+ TransferLine: Record \"Transfer Line\";\n+ begin\n+ TransferLine.SetRange(\"Subc. Purch. Order No.\", PurchaseLine.\"Document No.\");\n+ TransferLine.SetRange(\"Subc. Purch. Order Line No.\", PurchaseLine.\"Line No.\");\n+ TransferLine.SetRange(\"Subc. Prod. Order No.\", PurchaseLine.\"Prod. Order No.\");\n+ exit(not TransferLine.IsEmpty());\n+ end;\n+\n+ local procedure HasStockAtSubcLocation(PurchaseLine: Record \"Purchase Line\"; ProdOrderRoutingLine: Record \"Prod. Order Routing Line\"): Boolean\n+ var\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ SubcWIPLedgerEntry: Record \"Subcontractor WIP Ledger Entry\";\n+ SubcTransferManagement: Codeunit \"Subc. Transfer Management\";\n+ NetStockAtSubcLocation: Decimal;\n+ begin\n+ ProdOrderComponent.SetCurrentKey(Status, \"Prod. Order No.\", \"Routing Link Code\");\n+ ProdOrderComponent.SetRange(Status, \"Production Order Status\"::Released);\n+ ProdOrderComponent.SetRange(\"Prod. Order No.\", PurchaseLine.\"Prod. Order No.\");\n+ ProdOrderComponent.SetRange(\"Prod. Order Line No.\", PurchaseLine.\"Prod. Order Line No.\");\n+ ProdOrderComponent.SetRange(\"Component Supply Method\", ProdOrderComponent.\"Component Supply Method\"::\"Transfer to Vendor\");\n+ ProdOrderComponent.SetRange(\"Subc. Purchase Order Filter\", PurchaseLine.\"Document No.\");\n+ ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n+ ProdOrderComponent.SetAutoCalcFields(\"Subc. Qty. transf. to Subcontr\");\n+ if ProdOrderComponent.FindSet() then\n+ repeat\n+ if ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\" <> 0 then begin\n+ NetStockAtSubcLocation := ProdOrderComponent.\"Subc. Qty. transf. to Subcontr\";\n+ NetStockAtSubcLocation -= SubcTransferManagement.CalcConsumedQtyAtSubcLocation(ProdOrderComponent);\n+ if NetStockAtSubcLocation > 0 then\n+ exit(true);\n+ end;\n+ until ProdOrderComponent.Next() = 0;\n+\n+ SubcWIPLedgerEntry.SetCurrentKey(\"Prod. Order No.\", \"Prod. Order Status\", \"Prod. Order Line No.\", \"Routing Reference No.\", \"Routing No.\", \"Operation No.\", \"Location Code\");\n+ SubcWIPLedgerEntry.SetRange(\"Prod. Order No.\", PurchaseLine.\"Prod. Order No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Prod. Order Status\", \"Production Order Status\"::Released);\n+ SubcWIPLedgerEntry.SetRange(\"Prod. Order Line No.\", PurchaseLine.\"Prod. Order Line No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Routing Reference No.\", ProdOrderRoutingLine.\"Routing Reference No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Routing No.\", ProdOrderRoutingLine.\"Routing No.\");\n+ SubcWIPLedgerEntry.SetRange(\"Operation No.\", ProdOrderRoutingLine.\"Operation No.\");\n+ SubcWIPLedgerEntry.SetRange(\"In Transit\", false);\n+ SubcWIPLedgerEntry.CalcSums(\"Quantity (Base)\");\n+ if SubcWIPLedgerEntry.\"Quantity (Base)\" <> 0 then\n+ exit(true);\n+\n+ exit(false);\n+ end;\n+}\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al\nindex 40d3598456..41e67eba1c 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al\n@@ -104,6 +104,7 @@ codeunit 99001516 \"Subc. Req. Wksh. Make Ord.\"\n ProdOrderComponent.SetRange(\"Prod. Order Line No.\", RequisitionLine.\"Prod. Order Line No.\");\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n ProdOrderComponent.SetRange(\"Component Supply Method\", \"Component Supply Method\"::\"Vendor-Supplied\");\n+ ProdOrderComponent.SetLoadFields(\"Item No.\", \"Variant Code\", \"Remaining Quantity\");\n if ProdOrderComponent.FindSet() then\n repeat\n PurchaseLineComp.SetRange(\"Document Type\", PurchaseLine.\"Document Type\");\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al\nindex c84eace729..e90d3f7160 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Purchase/SubcPurchaseLineExt.Codeunit.al\n@@ -134,7 +134,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(Quantity) then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.Quantity = xRec.Quantity then\n@@ -160,7 +160,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"No.\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"No.\" = xRec.\"No.\" then\n@@ -186,7 +186,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Location Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Location Code\" = xRec.\"Location Code\" then\n@@ -212,7 +212,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Bin Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Bin Code\" = xRec.\"Bin Code\" then\n@@ -238,7 +238,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Variant Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Variant Code\" = xRec.\"Variant Code\" then\n@@ -264,7 +264,7 @@ codeunit 99001534 \"Subc. Purchase Line Ext\"\n if Rec.\"Prod. Order No.\" = '' then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Unit of Measure Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Unit of Measure Code\" = xRec.\"Unit of Measure Code\" then\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al\nindex 11e9867475..0918e43ef0 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/Extensions/Transfer/SubcTransferLineExt.Codeunit.al\n@@ -62,7 +62,7 @@ codeunit 99001544 \"Subc. Transfer Line Ext.\"\n if Rec.IsTemporary() then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Item No.\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Item No.\" = xRec.\"Item No.\" then\n@@ -85,7 +85,7 @@ codeunit 99001544 \"Subc. Transfer Line Ext.\"\n if Rec.IsTemporary() then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(\"Variant Code\") then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.\"Variant Code\" = xRec.\"Variant Code\" then\n@@ -108,7 +108,7 @@ codeunit 99001544 \"Subc. Transfer Line Ext.\"\n if Rec.IsTemporary() then\n exit;\n \n- if CurrFieldNo <> Rec.FieldNo(Quantity) then\n+ if CurrFieldNo = 0 then\n exit;\n \n if Rec.Quantity = xRec.Quantity then\ndiff --git a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al\nindex f6150f7b04..b6246cfb5d 100644\n--- a/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/App/src/Process/Codeunits/SubcTransferManagement.Codeunit.al\n@@ -389,6 +389,7 @@ codeunit 99001504 \"Subc. Transfer Management\"\n ProdOrderComponent.SetRange(\"Subc. Purchase Order Filter\", PurchaseLine.\"Document No.\");\n ProdOrderComponent.SetRange(\"Routing Link Code\", ProdOrderRoutingLine.\"Routing Link Code\");\n ProdOrderComponent.SetRange(\"Component Supply Method\", ProdOrderComponent.\"Component Supply Method\"::\"Transfer to Vendor\");\n+ ProdOrderComponent.SetLoadFields(\"Subc. Qty. transf. to Subcontr\", \"Location Code\");\n ProdOrderComponent.SetAutoCalcFields(\"Subc. Qty. transf. to Subcontr\");\n if ProdOrderComponent.FindSet() then\n repeat\n@@ -407,7 +408,6 @@ codeunit 99001504 \"Subc. Transfer Management\"\n SubcWIPLedgerEntry.SetRange(\"Routing Reference No.\", PurchaseLine.\"Routing Reference No.\");\n SubcWIPLedgerEntry.SetRange(\"Routing No.\", PurchaseLine.\"Routing No.\");\n SubcWIPLedgerEntry.SetRange(\"Operation No.\", PurchaseLine.\"Operation No.\");\n-\n SubcWIPLedgerEntry.SetRange(\"In Transit\", false);\n SubcWIPLedgerEntry.CalcSums(\"Quantity (Base)\");\n if SubcWIPLedgerEntry.\"Quantity (Base)\" <> 0 then\n@@ -427,6 +427,7 @@ codeunit 99001504 \"Subc. Transfer Management\"\n ItemLedgerEntry.SetRange(\"Entry Type\", ItemLedgerEntry.\"Entry Type\"::Consumption);\n ItemLedgerEntry.SetRange(\"Prod. Order Comp. Line No.\", ProdOrderComponent.\"Line No.\");\n ItemLedgerEntry.SetRange(\"Location Code\", ProdOrderComponent.\"Location Code\");\n+ ItemLedgerEntry.SetLoadFields(Quantity);\n ItemLedgerEntry.CalcSums(Quantity);\n exit(-ItemLedgerEntry.Quantity);\n end;\n", "FAIL_TO_PASS": [{"codeunitID": 139991, "functionName": ["CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithTransferToVendor", "CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithVendorSupplied"]}, {"codeunitID": 149915, "functionName": ["CannotModifyOrDeleteProdOrderComponentWhenTransferOrderExists"]}], "PASS_TO_PASS": [], "test_patch": "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\nindex f07c0afb34..0f6b7901b3 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcPurchSubcontTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcPurchSubcontTest.Codeunit.al\n@@ -510,6 +510,118 @@ codeunit 139991 \"Subc. Purch. Subcont. Test\"\n PostDirectTransferOrder(ReturnTransferHeader);\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoConfirmCreateProdOrderForSubcontractingProcess,HandleTransferOrder')]\n+ procedure CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithTransferToVendor()\n+ var\n+ Item: Record Item;\n+ HomeLocation: Record Location;\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderRtng: TestPage \"Prod. Order Routing\";\n+ begin\n+ // [SCENARIO] Modifying key fields or deleting a Prod. Order Routing Line must be blocked\n+ // when subcontracting transfer orders exist for Transfer to Vendor components.\n+ Initialize();\n+\n+ // [GIVEN] A subcontracting purchase order with a linked transfer order\n+ SetupSubContractingProdOrder(Item, HomeLocation, WorkCenter, MachineCenter, ProductionOrder, \"Component Supply Method\"::\"Transfer to Vendor\", LibraryRandom.RandIntInRange(1, 10));\n+ CreateSubcontractingPurchaseOrderForProdOrder(PurchaseHeader, PurchaseLine, Item, WorkCenter, ProductionOrder);\n+ CreateTransferOrderForPurchaseOrder(PurchaseHeader);\n+\n+ // [GIVEN] Find routing line for the subcontracting work center\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderRoutingLine.SetRange(\"Transfer WIP Item\", true);\n+#pragma warning restore AA0210\n+ ProdOrderRoutingLine.FindFirst();\n+\n+ // [THEN] Changing No. is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"No.\".SetValue(WorkCenter[1].\"No.\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Type is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.Type.SetValue(ProdOrderRoutingLine.Type::\"Machine Center\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Routing Link Code is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"Routing Link Code\".SetValue('');\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Deleting the routing line is blocked\n+ asserterror ProdOrderRoutingLine.Delete(true);\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('DoConfirmCreateProdOrderForSubcontractingProcess,HandleTransferOrder')]\n+ procedure CannotModifyOrDeleteRoutingLineWhenTransferOrderExistsWithVendorSupplied()\n+ var\n+ Item: Record Item;\n+ HomeLocation: Record Location;\n+ ProdOrderRoutingLine: Record \"Prod. Order Routing Line\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderRtng: TestPage \"Prod. Order Routing\";\n+ begin\n+ // [SCENARIO] Modifying key fields or deleting a Prod. Order Routing Line must be blocked\n+ // when subcontracting transfer orders exist for Transfer to Vendor components.\n+ Initialize();\n+\n+ // [GIVEN] A subcontracting purchase order with a linked transfer order\n+ SetupSubContractingProdOrder(Item, HomeLocation, WorkCenter, MachineCenter, ProductionOrder, \"Component Supply Method\"::\"Vendor-Supplied\", LibraryRandom.RandIntInRange(1, 10));\n+ CreateSubcontractingPurchaseOrderForProdOrder(PurchaseHeader, PurchaseLine, Item, WorkCenter, ProductionOrder);\n+ CreateTransferOrderForPurchaseOrder(PurchaseHeader);\n+\n+ // [GIVEN] Find routing line for the subcontracting work center\n+ ProdOrderRoutingLine.SetRange(\"Prod. Order No.\", ProductionOrder.\"No.\");\n+#pragma warning disable AA0210\n+ ProdOrderRoutingLine.SetRange(\"Transfer WIP Item\", true);\n+#pragma warning restore AA0210\n+ ProdOrderRoutingLine.FindFirst();\n+\n+ // [THEN] Changing No. is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"No.\".SetValue(WorkCenter[1].\"No.\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Type is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.Type.SetValue(ProdOrderRoutingLine.Type::\"Machine Center\");\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Changing Routing Link Code is blocked\n+ ProdOrderRtng.OpenEdit();\n+ ProdOrderRtng.GoToRecord(ProdOrderRoutingLine);\n+ asserterror ProdOrderRtng.\"Routing Link Code\".SetValue('');\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ ProdOrderRtng.Close();\n+\n+ // [THEN] Deleting the routing line is blocked\n+ asserterror ProdOrderRoutingLine.Delete(true);\n+ Assert.ExpectedError('You cannot change this routing line because transfer orders exist');\n+ end;\n+\n [ModalPageHandler]\n procedure ItemTrackingLinesSimpleHandler(var ItemTrackingLines: TestPage \"Item Tracking Lines\")\n begin\ndiff --git a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al\nindex ca4426c340..79a2777217 100644\n--- a/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al\n+++ b/src/Apps/W1/Subcontracting/Test/src/Codeunits/Tests/SubcTransOrdReservTest.Codeunit.al\n@@ -341,6 +341,58 @@ codeunit 149915 \"Subc. TransOrd. Reserv. Test\"\n Assert.AreEqual(30, TransferLine.\"Quantity (Base)\", 'Recreated transfer line must have the full component quantity');\n end;\n \n+ [Test]\n+ [HandlerFunctions('DoNotConfirmShowCreatedPurchOrderForSubcontracting,HandleTransferOrder')]\n+ procedure CannotModifyOrDeleteProdOrderComponentWhenTransferOrderExists()\n+ var\n+ Item: Record Item;\n+ NewItem: Record Item;\n+ ProdOrderComponent: Record \"Prod. Order Component\";\n+ ProductionOrder: Record \"Production Order\";\n+ PurchaseHeader: Record \"Purchase Header\";\n+ PurchaseLine: Record \"Purchase Line\";\n+ WorkCenter: array[2] of Record \"Work Center\";\n+ MachineCenter: array[2] of Record \"Machine Center\";\n+ ProdOrderCompPage: TestPage \"Prod. Order Components\";\n+ begin\n+ // [SCENARIO] Modifying key fields or deleting a Prod. Order Component with Component Supply Method = Transfer to Vendor\n+ // must be blocked when a subcontracting transfer order exists.\n+ Initialize();\n+\n+ // [GIVEN] A subcontracting transfer order linked to a production order with Transfer to Vendor components\n+ SetupTransferReservationScenario(Item, WorkCenter, MachineCenter, ProductionOrder, ProdOrderComponent, 10, 3, false);\n+ CreateSubcontractingPurchaseOrderAndReduceQuantity(Item, WorkCenter[2], ProductionOrder, PurchaseHeader, PurchaseLine, 0);\n+ CreateTransferOrder(PurchaseHeader);\n+\n+ // [GIVEN] Create another item to use for Item No. change\n+ LibraryInventory.CreateItem(NewItem);\n+\n+ // [THEN] Changing Item No. is blocked\n+ ProdOrderCompPage.OpenEdit();\n+ ProdOrderCompPage.GoToRecord(ProdOrderComponent);\n+ asserterror ProdOrderCompPage.\"Item No.\".SetValue(NewItem.\"No.\");\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ ProdOrderCompPage.Close();\n+\n+ // [THEN] Changing Quantity per is blocked\n+ ProdOrderCompPage.OpenEdit();\n+ ProdOrderCompPage.GoToRecord(ProdOrderComponent);\n+ asserterror ProdOrderCompPage.\"Quantity per\".SetValue(ProdOrderComponent.\"Quantity per\" + 1);\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ ProdOrderCompPage.Close();\n+\n+ // [THEN] Changing Component Supply Method is blocked\n+ ProdOrderCompPage.OpenEdit();\n+ ProdOrderCompPage.GoToRecord(ProdOrderComponent);\n+ asserterror ProdOrderCompPage.\"Component Supply Method\".SetValue(\"Component Supply Method\"::Empty);\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ ProdOrderCompPage.Close();\n+\n+ // [THEN] Deleting the component is blocked\n+ asserterror ProdOrderComponent.Delete(true);\n+ Assert.ExpectedError('You cannot change this component because transfer orders exist');\n+ end;\n+\n local procedure Initialize()\n begin\n LibraryTestInitialize.OnTestInitialize(Codeunit::\"Subc. TransOrd. Reserv. Test\");\n"} +{"metadata": {"area": null, "image_count": null, "persona": null}, "repo": "microsoft/BCApps", "instance_id": "microsoft__BCApps-8386", "base_commit": "f7a8a18571b1c99a30bad8d749474336f1c8c60a", "created_at": "2026-06-01T09:42:51Z", "environment_setup_version": "28.2", "project_paths": ["src\\Apps\\W1\\Shopify\\App", "src\\Apps\\W1\\Shopify\\Test"], "patch": "diff --git a/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al b/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al\nindex b4508e5546..884b8bdd71 100644\n--- a/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Bulk Operations/Codeunits/ShpfyBulkUpdateProductPrice.Codeunit.al\n@@ -88,7 +88,8 @@ codeunit 30281 \"Shpfy Bulk UpdateProductPrice\" implements \"Shpfy IBulk Operation\n ShopifyVariant.Price := JVariant.GetDecimal('price');\n ShopifyVariant.\"Compare at Price\" := JVariant.GetDecimal('compareAtPrice');\n ShopifyVariant.\"Updated At\" := JVariant.GetDateTime('updatedAt');\n- ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n+ if JVariant.Contains('unitCost') then\n+ ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n ShopifyVariant.Modify();\n end;\n end;\ndiff --git a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\nindex cee48d5400..91bcde34a8 100644\n--- a/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\n+++ b/src/Apps/W1/Shopify/App/src/Products/Codeunits/ShpfyProductExport.Codeunit.al\n@@ -894,7 +894,8 @@ codeunit 30178 \"Shpfy Product Export\"\n ShopifyVariant.Price := JVariant.GetDecimal('price');\n ShopifyVariant.\"Compare at Price\" := JVariant.GetDecimal('compareAtPrice');\n ShopifyVariant.\"Updated At\" := JVariant.GetDateTime('updatedAt');\n- ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n+ if JVariant.Contains('unitCost') then\n+ ShopifyVariant.\"Unit Cost\" := JVariant.GetDecimal('unitCost');\n ShopifyVariant.Modify();\n end;\n exit;\n", "FAIL_TO_PASS": [{"codeunitID": 139633, "functionName": ["TestBulkOperationRevertFailedWithLegacyRequestDataMissingUnitCost"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al\nindex 86c7a952fd..6a6e049ec0 100644\n--- a/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al\n+++ b/src/Apps/W1/Shopify/Test/Bulk Operations/Codeunits/ShpfyBulkOperationsTest.Codeunit.al\n@@ -314,6 +314,70 @@ codeunit 139633 \"Shpfy Bulk Operations Test\"\n ClearSetup();\n end;\n \n+ [Test]\n+ [HandlerFunctions('BulkOperationHttpHandler')]\n+ procedure TestBulkOperationRevertFailedWithLegacyRequestDataMissingUnitCost()\n+ var\n+ ShopifyVariant: Record \"Shpfy Variant\";\n+ BulkOperation: Record \"Shpfy Bulk Operation\";\n+ BulkOperationType: Enum \"Shpfy Bulk Operation Type\";\n+ ProductId: BigInteger;\n+ VariantId: BigInteger;\n+ VariantIds: List of [BigInteger];\n+ Index: Integer;\n+ begin\n+ // [SCENARIO] A bulk operation persisted before the unitCost key was added still\n+ // completes its revert without throwing, leaving Unit Cost untouched.\n+ // Regression for bug 637250.\n+\n+ // [GIVEN] A bulk operation whose request data was written by the pre-unitCost code\n+ // (i.e. the JSON objects only contain id/price/compareAtPrice/updatedAt) and four variants\n+ Initialize();\n+ for Index := 1 to 4 do begin\n+ ProductId := Any.IntegerInRange(100000, 555555);\n+ VariantId := Any.IntegerInRange(100000, 555555);\n+ VariantIds.Add(VariantId);\n+ ShopifyVariant.\"Product Id\" := ProductId;\n+ ShopifyVariant.Id := VariantId;\n+ ShopifyVariant.Price := 200;\n+ ShopifyVariant.\"Compare at Price\" := 250;\n+ ShopifyVariant.\"Unit Cost\" := 75;\n+ ShopifyVariant.Insert();\n+ end;\n+ BulkOperationUrl := 'https://storage.googleapis.com/shopify-bulk-result/' + Any.AlphabeticText(20);\n+ BulkOperation := CreateBulkOperation(BulkOperationId1, BulkOperationType::UpdateProductPrice, Shop.Code, BulkOperationUrl, GenerateLegacyRequestDataWithoutUnitCost(VariantIds, 100, 150));\n+\n+ // [WHEN] Bulk operation is completed\n+ BulkOperationIdCurrent := BulkOperationId1;\n+ VariantId1 := VariantIds.Get(1);\n+ VariantId2 := VariantIds.Get(4);\n+ BulkOperation.Status := BulkOperation.Status::Completed;\n+ BulkOperation.Modify(true);\n+\n+ // [THEN] The bulk operation is processed without throwing on the missing unitCost key,\n+ // failed variants have their Price/Compare at Price reverted, and Unit Cost is left\n+ // untouched on every variant (since the legacy blob doesn't know the pre-update value).\n+ BulkOperation.Get(BulkOperationId1, Shop.Code, BulkOperation.Type::mutation);\n+ LibraryAssert.IsTrue(BulkOperation.Processed, 'Bulk operation should be processed.');\n+ ShopifyVariant.Get(VariantIds.Get(1));\n+ LibraryAssert.AreEqual(200, ShopifyVariant.Price, 'Variant price should not be reverted.');\n+ LibraryAssert.AreEqual(250, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should not be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ShopifyVariant.Get(VariantIds.Get(2));\n+ LibraryAssert.AreEqual(100, ShopifyVariant.Price, 'Variant price should be reverted.');\n+ LibraryAssert.AreEqual(150, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ShopifyVariant.Get(VariantIds.Get(3));\n+ LibraryAssert.AreEqual(100, ShopifyVariant.Price, 'Variant price should be reverted.');\n+ LibraryAssert.AreEqual(150, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ShopifyVariant.Get(VariantIds.Get(4));\n+ LibraryAssert.AreEqual(200, ShopifyVariant.Price, 'Variant price should not be reverted.');\n+ LibraryAssert.AreEqual(250, ShopifyVariant.\"Compare at Price\", 'Variant compare at price should not be reverted.');\n+ LibraryAssert.AreEqual(75, ShopifyVariant.\"Unit Cost\", 'Variant unit cost should be left untouched when legacy blob lacks unitCost.');\n+ ClearSetup();\n+ end;\n+\n [Test]\n procedure TestBulkUpdateProductPriceClearsCompareAtPriceAsNull()\n var\n@@ -495,6 +559,26 @@ codeunit 139633 \"Shpfy Bulk Operations Test\"\n exit(RequestData);\n end;\n \n+ local procedure GenerateLegacyRequestDataWithoutUnitCost(VariantIds: List of [BigInteger]; Price: Decimal; CompareAtPrice: Decimal): JsonArray\n+ var\n+ RequestData: JsonArray;\n+ VariantId: BigInteger;\n+ Data: JsonObject;\n+ begin\n+ // Simulates the request-data layout written by the connector before the unitCost key\n+ // was added to the bulk-operation rollback bookkeeping. Used to test that the revert\n+ // tolerates legacy blobs persisted before the upgrade.\n+ foreach VariantId in VariantIds do begin\n+ Clear(Data);\n+ Data.Add('id', VariantId);\n+ Data.Add('price', Price);\n+ Data.Add('compareAtPrice', CompareAtPrice);\n+ Data.Add('updatedAt', '2025-02-25T13:40:15.6530000Z');\n+ RequestData.Add(Data);\n+ end;\n+ exit(RequestData);\n+ end;\n+\n local procedure EnqueueGraphQLResponsesForSendBulkMutation()\n begin\n GraphQLResponses.Enqueue('StagedUpload');\n"}