From ddd34344ed4eb168df06021cddb5cdccfcfd07d0 Mon Sep 17 00:00:00 2001 From: Alexey Dobriansky Date: Fri, 25 Sep 2026 17:14:03 +0200 Subject: [PATCH 1/3] Add NAV 246904 mileage rounding task Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d824ab77-41d6-4cfc-9445-9204d1d08988 --- dataset/bcbench.jsonl | 1 + .../microsoftInternal__NAV-246904/README.md | 29 +++++++++++ scripts/BCBenchUtils.psm1 | 10 +++- scripts/Download-BCSymbols.ps1 | 4 +- tests/test_artifact_config.py | 52 +++++++++++++++++++ 5 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 dataset/problemstatement/microsoftInternal__NAV-246904/README.md create mode 100644 tests/test_artifact_config.py diff --git a/dataset/bcbench.jsonl b/dataset/bcbench.jsonl index 54796b9fb..6732d4381 100644 --- a/dataset/bcbench.jsonl +++ b/dataset/bcbench.jsonl @@ -99,3 +99,4 @@ {"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": "finance", "image_count": 0, "persona": null}, "instance_id": "microsoftInternal__NAV-246904", "created_at": "2026-05-08", "environment_setup_version": "29.0", "project_paths": ["App\\Internal\\Apps\\ExpenseAgent\\app", "App\\Internal\\Apps\\ExpenseAgent\\test"], "repo": "microsoftInternal/NAV", "base_commit": "0e60e3ef08e47d9a44ff347b8f9f9a0cdf03652d", "patch": "diff --git a/App/Internal/Apps/ExpenseAgent/app/src/Setup/Codeunits/ExpenseAutoPopulation.Codeunit.al b/App/Internal/Apps/ExpenseAgent/app/src/Setup/Codeunits/ExpenseAutoPopulation.Codeunit.al\n--- a/App/Internal/Apps/ExpenseAgent/app/src/Setup/Codeunits/ExpenseAutoPopulation.Codeunit.al\n+++ b/App/Internal/Apps/ExpenseAgent/app/src/Setup/Codeunits/ExpenseAutoPopulation.Codeunit.al\n@@ -356,9 +356,16 @@\n end;\n \n local procedure ApplyDefaultExpenseCalculations(var Expense: Record Expense)\n+ var\n+ ExpenseCurrency: Record Currency;\n begin\n if Expense.\"Expense Detail Required\" = Expense.\"Expense Detail Required\"::Mileage then begin\n- Expense.Validate(Amount, GetEffectiveDistance(Expense.Mileage, Expense.\"Round Trip\") * GetStandardRateOfMileage(Expense.\"Expense Date\", Expense.\"Currency Code\", Expense.\"Currency Factor\", ExpenseAgentSetup.\"Standard Rate of Mileage\"));\n+ if Expense.\"Currency Code\" = '' then\n+ ExpenseCurrency.InitRoundingPrecision()\n+ else\n+ ExpenseCurrency.Get(Expense.\"Currency Code\");\n+\n+ Expense.Validate(Amount, Round(GetEffectiveDistance(Expense.Mileage, Expense.\"Round Trip\") * GetStandardRateOfMileage(Expense.\"Expense Date\", Expense.\"Currency Code\", Expense.\"Currency Factor\", ExpenseAgentSetup.\"Standard Rate of Mileage\"), ExpenseCurrency.\"Amount Rounding Precision\"));\n if Expense.\"Unit of Measure Code\" = '' then\n Expense.Validate(\"Unit of Measure Code\", ExpenseAgentSetup.\"Default Mileage UOM\");\n end;\n@@ -406,9 +413,16 @@\n end;\n \n local procedure ApplyDefaultExpenseReportCalculations(var ExpenseReportLine: Record \"Expense Report Line\")\n+ var\n+ ExpenseCurrency: Record Currency;\n begin\n if IsMileageRule(ExpenseReportLine.\"Expense Detail Required\") then begin\n- ExpenseReportLine.Validate(Amount, GetEffectiveDistance(ExpenseReportLine.Mileage, ExpenseReportLine.\"Round Trip\") * GetStandardRateOfMileage(ExpenseReportLine.\"Expense Date\", ExpenseReportLine.\"Expense Currency Code\", ExpenseReportLine.\"Expense Currency Factor\", ExpenseAgentSetup.\"Standard Rate of Mileage\"));\n+ if ExpenseReportLine.\"Expense Currency Code\" = '' then\n+ ExpenseCurrency.InitRoundingPrecision()\n+ else\n+ ExpenseCurrency.Get(ExpenseReportLine.\"Expense Currency Code\");\n+\n+ ExpenseReportLine.Validate(Amount, Round(GetEffectiveDistance(ExpenseReportLine.Mileage, ExpenseReportLine.\"Round Trip\") * GetStandardRateOfMileage(ExpenseReportLine.\"Expense Date\", ExpenseReportLine.\"Expense Currency Code\", ExpenseReportLine.\"Expense Currency Factor\", ExpenseAgentSetup.\"Standard Rate of Mileage\"), ExpenseCurrency.\"Amount Rounding Precision\"));\n if ExpenseReportLine.\"Unit of Measure Code\" = '' then\n ExpenseReportLine.Validate(\"Unit of Measure Code\", ExpenseAgentSetup.\"Default Mileage UOM\");\n end;\ndiff --git a/App/Internal/Apps/ExpenseAgent/app/src/Setup/Codeunits/ExpenseRuleValidation.Codeunit.al b/App/Internal/Apps/ExpenseAgent/app/src/Setup/Codeunits/ExpenseRuleValidation.Codeunit.al\n--- a/App/Internal/Apps/ExpenseAgent/app/src/Setup/Codeunits/ExpenseRuleValidation.Codeunit.al\n+++ b/App/Internal/Apps/ExpenseAgent/app/src/Setup/Codeunits/ExpenseRuleValidation.Codeunit.al\n@@ -650,14 +650,20 @@\n \n local procedure ValidateMileageAmounts(Expense: Record Expense)\n var\n+ ExpenseCurrency: Record Currency;\n ExpenseRuleViolation: Record \"Expense Rule Violation\";\n StandardRate: Decimal;\n CalculatedAmount: Decimal;\n EffectiveDistance: Decimal;\n begin\n+ if Expense.\"Currency Code\" = '' then\n+ ExpenseCurrency.InitRoundingPrecision()\n+ else\n+ ExpenseCurrency.Get(Expense.\"Currency Code\");\n+\n StandardRate := ExpenseAgentSetup.\"Standard Rate of Mileage\";\n EffectiveDistance := ExpenseAutoPopulation.GetEffectiveDistance(Expense.Mileage, Expense.\"Round Trip\");\n- CalculatedAmount := EffectiveDistance * ExpenseAutoPopulation.GetStandardRateOfMileage(Expense.\"Expense Date\", Expense.\"Currency Code\", Expense.\"Currency Factor\", StandardRate);\n+ CalculatedAmount := Round(EffectiveDistance * ExpenseAutoPopulation.GetStandardRateOfMileage(Expense.\"Expense Date\", Expense.\"Currency Code\", Expense.\"Currency Factor\", StandardRate), ExpenseCurrency.\"Amount Rounding Precision\");\n \n if CalculatedAmount <> Expense.Amount then\n ExpenseRuleViolation.AddRuleViolation(Expense.\"No.\", StrSubstNo(MileageCalculationMismatchErr, EffectiveDistance, StandardRate, CalculatedAmount, Expense.Amount));\n@@ -948,14 +954,20 @@\n \n local procedure ValidateMileageAmountsForReportLine(ExpenseReportLine: Record \"Expense Report Line\")\n var\n+ ExpenseCurrency: Record Currency;\n ExpenseReportRuleViolation: Record \"Expense Report Rule Violation\";\n StandardRate: Decimal;\n CalculatedAmount: Decimal;\n EffectiveDistance: Decimal;\n begin\n+ if ExpenseReportLine.\"Expense Currency Code\" = '' then\n+ ExpenseCurrency.InitRoundingPrecision()\n+ else\n+ ExpenseCurrency.Get(ExpenseReportLine.\"Expense Currency Code\");\n+\n StandardRate := ExpenseAgentSetup.\"Standard Rate of Mileage\";\n EffectiveDistance := ExpenseAutoPopulation.GetEffectiveDistance(ExpenseReportLine.Mileage, ExpenseReportLine.\"Round Trip\");\n- CalculatedAmount := EffectiveDistance * ExpenseAutoPopulation.GetStandardRateOfMileage(ExpenseReportLine.\"Expense Date\", ExpenseReportLine.\"Expense Currency Code\", ExpenseReportLine.\"Expense Currency Factor\", StandardRate);\n+ CalculatedAmount := Round(EffectiveDistance * ExpenseAutoPopulation.GetStandardRateOfMileage(ExpenseReportLine.\"Expense Date\", ExpenseReportLine.\"Expense Currency Code\", ExpenseReportLine.\"Expense Currency Factor\", StandardRate), ExpenseCurrency.\"Amount Rounding Precision\");\n \n if CalculatedAmount <> ExpenseReportLine.Amount then\n ExpenseReportRuleViolation.AddRuleViolation(ExpenseReportLine.\"Document No.\", ExpenseReportLine.\"Line No.\", StrSubstNo(MileageCalculationMismatchErr, EffectiveDistance, StandardRate, CalculatedAmount, ExpenseReportLine.Amount));\n", "FAIL_TO_PASS": [{"codeunitID": 148303, "functionName": ["ExpenseReportCanBePostedWithMileageWithTwoDecimalPlaces"]}], "PASS_TO_PASS": [], "test_patch": "diff --git a/App/Internal/Apps/ExpenseAgent/test/src/ExpenseReportPostingTestII.Codeunit.al b/App/Internal/Apps/ExpenseAgent/test/src/ExpenseReportPostingTestII.Codeunit.al\n--- a/App/Internal/Apps/ExpenseAgent/test/src/ExpenseReportPostingTestII.Codeunit.al\n+++ b/App/Internal/Apps/ExpenseAgent/test/src/ExpenseReportPostingTestII.Codeunit.al\n@@ -1171,6 +1171,62 @@\n \n // [THEN] Verify that Unit Cost is updated in Job Ledger Entry when Expense Report is posted with Job with FCY.\n VerifyPostedExpenseReportWithJob(Expense, ExpenseUser, JobCurrencyCode, JobAmount, ExpectedAmountLCY);\n+ end;\n+\n+ [Test]\n+ [HandlerFunctions('ConfirmHandler,PostedExpenseReportModalPageHandler')]\n+ procedure ExpenseReportCanBePostedWithMileageWithTwoDecimalPlaces()\n+ var\n+ PostCode: Record \"Post Code\";\n+ ExpensePaymentMethod: Record \"Expense Payment Method\";\n+ ExpenseUser: Record \"Expense User\";\n+ ExpenseCategory: Record \"Expense Category\";\n+ ExpenseAgentSetup: Record \"Expense Agent Setup\";\n+ UnitOfMeasure: Record \"Unit of Measure\";\n+ ExpenseReportLine: Record \"Expense Report Line\";\n+ PostedExpenseReportLine: Record \"Posted Expense Report Line\";\n+ ExpenseReportPage: TestPage \"Expense Report\";\n+ begin\n+ // [FEATURE] [AI test 0.4]\n+ // [SCENARIO 634224] Verify that Expense Report can be posted with Mileage with two decimal places.\n+ Initialize();\n+\n+ // [GIVEN] Create Unit of Measure.\n+ LibraryInventory.CreateUnitOfMeasureCode(UnitOfMeasure);\n+\n+ // [GIVEN] Update Standard Rate of Mileage in Expense Agent Setup.\n+ ExpenseAgentSetup.Get();\n+ ExpenseAgentSetup.Validate(\"Standard Rate of Mileage\", 4.32);\n+ ExpenseAgentSetup.Validate(\"Default Mileage UOM\", UnitOfMeasure.Code);\n+ ExpenseAgentSetup.Modify();\n+\n+ // [GIVEN] Find \"Post Code\".\n+ LibraryERM.FindPostCode(PostCode);\n+\n+ // [GIVEN] Find Expense Payment Method.\n+ LibraryExpense.FindExpensePaymentMethod(ExpensePaymentMethod, ExpensePaymentMethod.\"Reimbursement Type\"::\"Company Paid\");\n+\n+ // [GIVEN] Create Expense User.\n+ LibraryExpense.CreateExpenseUser(ExpenseUser);\n+\n+ // [GIVEN] Create Expense Category.\n+ LibraryExpense.CreateExpenseCategory(ExpenseCategory, ExpenseCategory.\"Reimbursement Type\"::\"Company Paid\", ExpenseCategory.\"Expense Detail Required\"::Mileage, ExpensePaymentMethod.Code);\n+\n+ // [GIVEN] Update Expense Account in Employee Posting Group.\n+ UpdateExpenseAccountInEmployeePostingGroup(ExpenseUser, ExpenseCategory.Code, ExpenseUser.\"No.\");\n+\n+ // [GIVEN] Create Expense Report.\n+ ExpenseReportPage.OpenNew();\n+ ExpenseReportPage.\"Expense User No.\".SetValue(ExpenseUser.\"No.\");\n+ ExpenseReportPage.\"Expense Report Subform\".\"Expense Category\".SetValue(ExpenseCategory.Code);\n+ ExpenseReportPage.\"Expense Report Subform\".Mileage.SetValue(LibraryRandom.RandDec(100, 2));\n+\n+ // [WHEN] Post Expense Report.\n+ FindExpenseReportLine(ExpenseReportLine, CopyStr(ExpenseReportPage.\"No.\".Value(), 1, 20));\n+ ExpenseReportPage.Post.Invoke();\n+\n+ // [THEN] Verify that Expense Report is posted successfully.\n+ FindPostedExpenseReportLine(PostedExpenseReportLine, ExpenseReportLine.\"Expense User No.\");\n end;\n \n local procedure Initialize()\n"} diff --git a/dataset/problemstatement/microsoftInternal__NAV-246904/README.md b/dataset/problemstatement/microsoftInternal__NAV-246904/README.md new file mode 100644 index 000000000..c9288b212 --- /dev/null +++ b/dataset/problemstatement/microsoftInternal__NAV-246904/README.md @@ -0,0 +1,29 @@ +# Posting a mileage expense report fails because the calculated amount is not rounded + +## Environment + +- US Business Central 28.1 (Platform 28.0.50017.0, Application 28.1.49838.50112). +- Expense Agent (Preview) is installed and configured. + +## Reproduction steps + +1. Open **Expense Agent Setup**. +2. Set **Standard Rate of Mileage** to `4.32` and select a valid **Default Mileage UOM**. +3. Ensure an expense user exists with a valid employee posting group and expense posting account. +4. Ensure a company-paid expense payment method exists. +5. Create or open an **Expense Category** with **Expense Detail Required** set to **Mileage**, and assign the company-paid payment method. +6. Create a new **Expense Report** for the expense user. +7. Add a line with the mileage expense category. +8. Enter mileage with two decimal places, for example `28.11`, and complete any required trip description or location fields. +9. Submit and approve the expense report. +10. Open the approved expense report and choose **Post**. + +## Expected behavior + +The mileage amount is rounded using the applicable currency amount-rounding precision, and the expense report posts successfully. + +## Actual behavior + +Posting fails because the calculated mileage amount retains excess decimal precision: + +> Amount 121.42 needs to be rounded in Gen. Journal Line Journal Template Name='', Journal Batch Name='', Line No.='0'. diff --git a/scripts/BCBenchUtils.psm1 b/scripts/BCBenchUtils.psm1 index 63da0224d..6b435b7c3 100644 --- a/scripts/BCBenchUtils.psm1 +++ b/scripts/BCBenchUtils.psm1 @@ -469,7 +469,7 @@ function Get-RepoCloneInfo { return @{ Url = 'https://dynamicssmb2.visualstudio.com/Dynamics%20SMB/_git/NAV' Token = $env:ADO_TOKEN - SparseCheckoutPaths = @('App/Apps', 'App/Layers') + SparseCheckoutPaths = @('App/Apps', 'App/Internal/Apps', 'App/Layers') } } } @@ -544,6 +544,14 @@ function Get-BCBenchArtifactConfig { if ($Country -ne 'w1') { throw "Approved BC artifacts are only configured for w1, not $Country." } + [hashtable] $pinnedInsiderUrls = @{ + '29.0' = 'https://bcinsider-fvh2ekdjecfjd6gk.b02.azurefd.net/sandbox/29.0.54011.55007/w1' + '30.0' = 'https://bcinsider-fvh2ekdjecfjd6gk.b02.azurefd.net/sandbox/30.0.55015.0/w1' + } + if ($pinnedInsiderUrls.ContainsKey($Version)) { + return @{ artifactUrl = $pinnedInsiderUrls[$Version]; accept_insiderEula = $true } + } + [hashtable] $pinnedUrls = @{ '24.0' = 'https://bcartifacts-exdbf9fwegejdqak.b02.azurefd.net/sandbox/24.0.16410.31330/w1' '24.2' = 'https://bcartifacts-exdbf9fwegejdqak.b02.azurefd.net/sandbox/24.2.20227.31325/w1' diff --git a/scripts/Download-BCSymbols.ps1 b/scripts/Download-BCSymbols.ps1 index fcd276770..00f684bb5 100644 --- a/scripts/Download-BCSymbols.ps1 +++ b/scripts/Download-BCSymbols.ps1 @@ -39,8 +39,8 @@ Write-Log "Resolved BC version $version for InstanceId $InstanceId" -Level Info Import-Module BcContainerHelper -Force -DisableNameChecking -[string] $artifactUrl = Get-BCArtifactUrl -version $version -country $Country -select 'Latest' -if (-not $artifactUrl) { throw "No BC artifact URL resolved for version $version ($Country)" } +[hashtable] $artifactConfig = Get-BCBenchArtifactConfig -Category $Category -Version $version -Country $Country +[string] $artifactUrl = $artifactConfig.artifactUrl Write-Log "Downloading artifact: $artifactUrl" -Level Info $paths = Download-Artifacts -artifactUrl $artifactUrl -includePlatform diff --git a/tests/test_artifact_config.py b/tests/test_artifact_config.py new file mode 100644 index 000000000..50b3270eb --- /dev/null +++ b/tests/test_artifact_config.py @@ -0,0 +1,52 @@ +import json +import shutil +import subprocess +from pathlib import Path + +import pytest + +ROOT = Path(__file__).parent.parent +UTILS_MODULE = ROOT / "scripts" / "BCBenchUtils.psm1" + + +def get_artifact_config(category: str, version: str) -> dict[str, object]: + pwsh = shutil.which("pwsh") + if not pwsh: + pytest.skip("PowerShell is required") + + command = f"Import-Module '{UTILS_MODULE}' -Force -DisableNameChecking; Get-BCBenchArtifactConfig -Category '{category}' -Version '{version}' | ConvertTo-Json -Compress" + result = subprocess.run( + [pwsh, "-NoProfile", "-Command", command], + capture_output=True, + text=True, + encoding="utf-8", + check=True, + ) + return json.loads(result.stdout) + + +def test_released_bug_fix_uses_pinned_artifact(): + assert get_artifact_config("bug-fix", "27.2") == { + "accept_insiderEula": False, + "artifactUrl": "https://bcartifacts-exdbf9fwegejdqak.b02.azurefd.net/sandbox/27.2.42879.54576/w1", + } + + +@pytest.mark.parametrize( + ("version", "url"), + [ + ("29.0", "https://bcinsider-fvh2ekdjecfjd6gk.b02.azurefd.net/sandbox/29.0.54011.55007/w1"), + ("30.0", "https://bcinsider-fvh2ekdjecfjd6gk.b02.azurefd.net/sandbox/30.0.55015.0/w1"), + ], +) +def test_insider_bug_fix_uses_pinned_artifact(version: str, url: str): + assert get_artifact_config("bug-fix", version) == { + "accept_insiderEula": True, + "artifactUrl": url, + } + + +def test_setup_paths_cover_internal_apps(): + utils_module = UTILS_MODULE.read_text(encoding="utf-8") + + assert "'App/Internal/Apps'" in utils_module From 1e83a5e8f11db28869101d1e88406e73312da5ac Mon Sep 17 00:00:00 2001 From: Alexey Dobriansky Date: Fri, 25 Sep 2026 17:27:38 +0200 Subject: [PATCH 2/3] Remove environment requirements from NAV repro Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d824ab77-41d6-4cfc-9445-9204d1d08988 --- .../problemstatement/microsoftInternal__NAV-246904/README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dataset/problemstatement/microsoftInternal__NAV-246904/README.md b/dataset/problemstatement/microsoftInternal__NAV-246904/README.md index c9288b212..427925cf2 100644 --- a/dataset/problemstatement/microsoftInternal__NAV-246904/README.md +++ b/dataset/problemstatement/microsoftInternal__NAV-246904/README.md @@ -1,10 +1,5 @@ # Posting a mileage expense report fails because the calculated amount is not rounded -## Environment - -- US Business Central 28.1 (Platform 28.0.50017.0, Application 28.1.49838.50112). -- Expense Agent (Preview) is installed and configured. - ## Reproduction steps 1. Open **Expense Agent Setup**. From 9a67f60dfefd0409db45ce3d50925d9317f3593d Mon Sep 17 00:00:00 2001 From: Alexey Dobriansky Date: Fri, 25 Sep 2026 17:28:52 +0200 Subject: [PATCH 3/3] Retain US localization in NAV repro Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d824ab77-41d6-4cfc-9445-9204d1d08988 --- .../problemstatement/microsoftInternal__NAV-246904/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dataset/problemstatement/microsoftInternal__NAV-246904/README.md b/dataset/problemstatement/microsoftInternal__NAV-246904/README.md index 427925cf2..6b84efce6 100644 --- a/dataset/problemstatement/microsoftInternal__NAV-246904/README.md +++ b/dataset/problemstatement/microsoftInternal__NAV-246904/README.md @@ -2,7 +2,7 @@ ## Reproduction steps -1. Open **Expense Agent Setup**. +1. In a US-localized company, open **Expense Agent Setup**. 2. Set **Standard Rate of Mileage** to `4.32` and select a valid **Default Mileage UOM**. 3. Ensure an expense user exists with a valid employee posting group and expense posting account. 4. Ensure a company-paid expense payment method exists.