From 1344bea13a9a4866f8dec522d504bbffe85345c8 Mon Sep 17 00:00:00 2001 From: v-nesinghal Date: Mon, 7 Sep 2026 22:24:12 +0530 Subject: [PATCH 1/2] Fix and Automation --- .../Currency/ExchRateAdjmtLedgEntries.Page.al | 3 + .../Currency/ExchRateAdjmtProcess.Codeunit.al | 6 +- .../ERMExchRateAdjustment.Codeunit.al | 94 ++++++++++++++++++- 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/src/Layers/W1/BaseApp/Finance/Currency/ExchRateAdjmtLedgEntries.Page.al b/src/Layers/W1/BaseApp/Finance/Currency/ExchRateAdjmtLedgEntries.Page.al index 76d6ad1a00d..20f58e8b378 100644 --- a/src/Layers/W1/BaseApp/Finance/Currency/ExchRateAdjmtLedgEntries.Page.al +++ b/src/Layers/W1/BaseApp/Finance/Currency/ExchRateAdjmtLedgEntries.Page.al @@ -65,6 +65,7 @@ page 186 "Exch.Rate Adjmt. Ledg.Entries" field("Currency Factor"; Rec."Currency Factor") { ApplicationArea = Suite; + DecimalPlaces = 4 : 5; } field("Base Amount"; Rec."Base Amount") { @@ -82,11 +83,13 @@ page 186 "Exch.Rate Adjmt. Ledg.Entries" field("Register No."; Rec."Register No.") { ApplicationArea = Basic, Suite; + Caption = 'Register No.'; Visible = false; } field("Detailed Ledger Entry No."; Rec."Detailed Ledger Entry No.") { ApplicationArea = Basic, Suite; + DecimalPlaces = 0 : 0; Visible = false; } } diff --git a/src/Layers/W1/BaseApp/Finance/Currency/ExchRateAdjmtProcess.Codeunit.al b/src/Layers/W1/BaseApp/Finance/Currency/ExchRateAdjmtProcess.Codeunit.al index 16ffddd2649..5766dfff2f2 100644 --- a/src/Layers/W1/BaseApp/Finance/Currency/ExchRateAdjmtProcess.Codeunit.al +++ b/src/Layers/W1/BaseApp/Finance/Currency/ExchRateAdjmtProcess.Codeunit.al @@ -2863,7 +2863,7 @@ codeunit 699 "Exch. Rate Adjmt. Process" TempExchRateAdjmtLedgEntry."Currency Factor" := CustLedgerEntry."Adjusted Currency Factor"; TempExchRateAdjmtLedgEntry."Base Amount" := CustLedgerEntry."Remaining Amount"; TempExchRateAdjmtLedgEntry."Base Amount (LCY)" := CustLedgerEntry."Remaining Amt. (LCY)"; - TempExchRateAdjmtLedgEntry."Adjustment Amount" := CurrAdjAmount; + TempExchRateAdjmtLedgEntry."Adjustment Amount" := DetailedCustLedgEntry2."Amount (LCY)"; TempExchRateAdjmtLedgEntry.Insert(); end; @@ -2884,7 +2884,7 @@ codeunit 699 "Exch. Rate Adjmt. Process" TempExchRateAdjmtLedgEntry."Currency Factor" := VendorLedgerEntry."Adjusted Currency Factor"; TempExchRateAdjmtLedgEntry."Base Amount" := VendorLedgerEntry."Remaining Amount"; TempExchRateAdjmtLedgEntry."Base Amount (LCY)" := VendorLedgerEntry."Remaining Amt. (LCY)"; - TempExchRateAdjmtLedgEntry."Adjustment Amount" := CurrAdjAmount; + TempExchRateAdjmtLedgEntry."Adjustment Amount" := DetailedVendorLedgEntry2."Amount (LCY)"; TempExchRateAdjmtLedgEntry.Insert(); end; @@ -2905,7 +2905,7 @@ codeunit 699 "Exch. Rate Adjmt. Process" TempExchRateAdjmtLedgEntry."Currency Factor" := Currency."Currency Factor"; TempExchRateAdjmtLedgEntry."Base Amount" := EmplLedgEntry."Remaining Amount"; TempExchRateAdjmtLedgEntry."Base Amount (LCY)" := EmplLedgEntry."Remaining Amt. (LCY)"; - TempExchRateAdjmtLedgEntry."Adjustment Amount" := CurrAdjAmount; + TempExchRateAdjmtLedgEntry."Adjustment Amount" := DtldEmplLedgEntry."Amount (LCY)"; TempExchRateAdjmtLedgEntry.Insert(); end; diff --git a/src/Layers/W1/Tests/ERM-Finance/ERMExchRateAdjustment.Codeunit.al b/src/Layers/W1/Tests/ERM-Finance/ERMExchRateAdjustment.Codeunit.al index 8c039bbac87..7b769ab9e5b 100644 --- a/src/Layers/W1/Tests/ERM-Finance/ERMExchRateAdjustment.Codeunit.al +++ b/src/Layers/W1/Tests/ERM-Finance/ERMExchRateAdjustment.Codeunit.al @@ -17,7 +17,9 @@ codeunit 134883 "ERM Exch. Rate Adjustment" LibraryInventory: Codeunit "Library - Inventory"; LibraryPurchase: Codeunit "Library - Purchase"; LibrarySales: Codeunit "Library - Sales"; + LibraryUtility: Codeunit "Library - Utility"; IsInitialized: Boolean; + AdjustmentAmountMismatchErr: Label 'Adjustment Amount %1 must equal Amount (LCY) %2 for detailed vendor ledger entry %3.', Comment = '%1 = Adjustment Amount, %2 = Amount (LCY), %3 = Detailed Vendor Ledger Entry No.'; ExpectNoAdjustmentErr: Label 'Expect no adjustment for entries before %1'; ExchangeRateAdjmtTxt: Label 'Exchange Rate Adjmt. of %1 %2'; @@ -171,6 +173,40 @@ codeunit 134883 "ERM Exch. Rate Adjustment" VerifyExchRateAdjmtRegisterSync(CurrencyExchangeRate."Currency Code"); end; + [Test] + procedure VendorGainReversedToHigherLossLedgerAmountsMatchDetailedEntries() + var + CurrencyExchangeRate: Record "Currency Exchange Rate"; + Vendor: Record Vendor; + CurrencyCode: Code[10]; + PostingDate: Date; + begin + // [FEATURE] [AI test 0.4] [Purchase] + // [SCENARIO 643352] When an unrealized gain reverses into a higher loss, each vendor ledger entry Adjustment Amount matches its own detailed ledger entry Amount (LCY). + Initialize(); + + // [GIVEN] Create Currency with exchange rate and Vendor. + CreateCurrencyWithExchangeRate(CurrencyExchangeRate); + UpdateExchangeRate(CurrencyExchangeRate, 1, 1); + CurrencyCode := CurrencyExchangeRate."Currency Code"; + PostingDate := WorkDate(); + CreateVendorWithCurrency(Vendor, CurrencyCode); + + // [GIVEN] Posted purchase invoice with exchange rate. + PostVendorInvoice(Vendor."No.", CurrencyCode, PostingDate, -1000); + + // [GIVEN] Exchange rate lowered to create an unrealized gain and the adjustment is run. + UpdateExchangeRate(CurrencyExchangeRate, 1, 0.8); + RunExchRateAdjustmentForVendor(CurrencyCode, Vendor."No."); + + // [WHEN] Exchange rate raised to reverse the gain into a higher loss and the adjustment is run again. + UpdateExchangeRate(CurrencyExchangeRate, 1, 1.4); + RunExchRateAdjustmentForVendor(CurrencyCode, Vendor."No."); + + // [THEN] Verify Each ledger entry shows the amount of its own linked detailed ledger entry. + VerifyVendorAdjustmentAmountsMatchDetailedEntries(Vendor."No."); + end; + local procedure Initialize() var LibraryERMCountryData: Codeunit "Library - ERM Country Data"; @@ -387,5 +423,61 @@ codeunit 134883 "ERM Exch. Rate Adjustment" until ExchRateAdjmtReg.Next() = 0; end; -} + local procedure CreateVendorWithCurrency(var Vendor: Record Vendor; CurrencyCode: Code[10]) + begin + LibraryPurchase.CreateVendor(Vendor); + Vendor.Validate("Currency Code", CurrencyCode); + Vendor.Modify(true); + end; + + local procedure PostVendorInvoice(VendorNo: Code[20]; CurrencyCode: Code[10]; PostingDate: Date; Amount: Decimal) + var + GenJournalLine: Record "Gen. Journal Line"; + GenJournalBatch: Record "Gen. Journal Batch"; + begin + LibraryERM.SelectGenJnlBatch(GenJournalBatch); + LibraryERM.ClearGenJournalLines(GenJournalBatch); + LibraryERM.CreateGeneralJnlLine( + GenJournalLine, GenJournalBatch."Journal Template Name", GenJournalBatch.Name, + GenJournalLine."Document Type"::Invoice, GenJournalLine."Account Type"::Vendor, VendorNo, Amount); + GenJournalLine.Validate("Currency Code", CurrencyCode); + GenJournalLine.Validate("Posting Date", PostingDate); + GenJournalLine.Modify(true); + LibraryERM.PostGeneralJnlLine(GenJournalLine); + end; + + local procedure RunExchRateAdjustmentForVendor(CurrencyCode: Code[10]; VendorNo: Code[20]) + var + Currency: Record Currency; + Vendor: Record Vendor; + ExchRateAdjustment: Report "Exch. Rate Adjustment"; + begin + Currency.SetRange(Code, CurrencyCode); + Vendor.SetRange("No.", VendorNo); + ExchRateAdjustment.SetTableView(Currency); + ExchRateAdjustment.SetTableView(Vendor); + ExchRateAdjustment.InitializeRequest2(0D, WorkDate(), 'Test', WorkDate(), LibraryUtility.GenerateGUID(), true, false); + ExchRateAdjustment.UseRequestPage(false); + ExchRateAdjustment.SetHideUI(true); + ExchRateAdjustment.Run(); + end; + + local procedure VerifyVendorAdjustmentAmountsMatchDetailedEntries(VendorNo: Code[20]) + var + DetailedVendorLedgEntry: Record "Detailed Vendor Ledg. Entry"; + ExchRateAdjmtLedgEntry: Record "Exch. Rate Adjmt. Ledg. Entry"; + begin + ExchRateAdjmtLedgEntry.SetRange("Account Type", ExchRateAdjmtLedgEntry."Account Type"::Vendor); + ExchRateAdjmtLedgEntry.SetRange("Account No.", VendorNo); + Assert.IsTrue(ExchRateAdjmtLedgEntry.FindSet(), 'Expected exch. rate adjmt. ledger entries for the vendor.'); + repeat + DetailedVendorLedgEntry.Get(ExchRateAdjmtLedgEntry."Detailed Ledger Entry No."); + Assert.AreEqual( + DetailedVendorLedgEntry."Amount (LCY)", ExchRateAdjmtLedgEntry."Adjustment Amount", + StrSubstNo( + AdjustmentAmountMismatchErr, ExchRateAdjmtLedgEntry."Adjustment Amount", + DetailedVendorLedgEntry."Amount (LCY)", DetailedVendorLedgEntry."Entry No.")); + until ExchRateAdjmtLedgEntry.Next() = 0; + end; +} \ No newline at end of file From 81fa8efddafccc447f3120def3d526a0315a2e4b Mon Sep 17 00:00:00 2001 From: v-nesinghal Date: Mon, 7 Sep 2026 22:28:10 +0530 Subject: [PATCH 2/2] Miapp --- .../Finance/Currency/ExchRateAdjmtProcess.Codeunit.al | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Layers/RU/BaseApp/Finance/Currency/ExchRateAdjmtProcess.Codeunit.al b/src/Layers/RU/BaseApp/Finance/Currency/ExchRateAdjmtProcess.Codeunit.al index 40114166069..411da4c7e8d 100644 --- a/src/Layers/RU/BaseApp/Finance/Currency/ExchRateAdjmtProcess.Codeunit.al +++ b/src/Layers/RU/BaseApp/Finance/Currency/ExchRateAdjmtProcess.Codeunit.al @@ -3114,7 +3114,7 @@ codeunit 699 "Exch. Rate Adjmt. Process" TempExchRateAdjmtLedgEntry."Currency Factor" := CustLedgerEntry."Adjusted Currency Factor"; TempExchRateAdjmtLedgEntry."Base Amount" := CustLedgerEntry."Remaining Amount"; TempExchRateAdjmtLedgEntry."Base Amount (LCY)" := CustLedgerEntry."Remaining Amt. (LCY)"; - TempExchRateAdjmtLedgEntry."Adjustment Amount" := CurrAdjAmount; + TempExchRateAdjmtLedgEntry."Adjustment Amount" := DetailedCustLedgEntry2."Amount (LCY)"; TempExchRateAdjmtLedgEntry.Insert(); end; @@ -3135,7 +3135,7 @@ codeunit 699 "Exch. Rate Adjmt. Process" TempExchRateAdjmtLedgEntry."Currency Factor" := VendorLedgerEntry."Adjusted Currency Factor"; TempExchRateAdjmtLedgEntry."Base Amount" := VendorLedgerEntry."Remaining Amount"; TempExchRateAdjmtLedgEntry."Base Amount (LCY)" := VendorLedgerEntry."Remaining Amt. (LCY)"; - TempExchRateAdjmtLedgEntry."Adjustment Amount" := CurrAdjAmount; + TempExchRateAdjmtLedgEntry."Adjustment Amount" := DetailedVendorLedgEntry2."Amount (LCY)"; TempExchRateAdjmtLedgEntry.Insert(); end; @@ -3156,7 +3156,7 @@ codeunit 699 "Exch. Rate Adjmt. Process" TempExchRateAdjmtLedgEntry."Currency Factor" := Currency."Currency Factor"; TempExchRateAdjmtLedgEntry."Base Amount" := EmplLedgEntry."Remaining Amount"; TempExchRateAdjmtLedgEntry."Base Amount (LCY)" := EmplLedgEntry."Remaining Amt. (LCY)"; - TempExchRateAdjmtLedgEntry."Adjustment Amount" := CurrAdjAmount; + TempExchRateAdjmtLedgEntry."Adjustment Amount" := DtldEmplLedgEntry."Amount (LCY)"; TempExchRateAdjmtLedgEntry.Insert(); end;