From 514b77d2b6840c0b19712c67b1919bb7eaa392fa Mon Sep 17 00:00:00 2001 From: Djordje Cenic Date: Wed, 9 Sep 2026 14:05:57 +0200 Subject: [PATCH] [29.0] Backport #11206: [CH] When posting with FCY, VAT G/L Entry stores VAT base amount in Source Currency Amount instead of VAT amount --- .../Posting/GenJnlPostLine.Codeunit.al | 6 +- .../Local/TestSRGLEntriesForeignC.Codeunit.al | 86 +++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/src/Layers/CH/BaseApp/Finance/GeneralLedger/Posting/GenJnlPostLine.Codeunit.al b/src/Layers/CH/BaseApp/Finance/GeneralLedger/Posting/GenJnlPostLine.Codeunit.al index 1baf81c739a..ae7dfa67cd8 100644 --- a/src/Layers/CH/BaseApp/Finance/GeneralLedger/Posting/GenJnlPostLine.Codeunit.al +++ b/src/Layers/CH/BaseApp/Finance/GeneralLedger/Posting/GenJnlPostLine.Codeunit.al @@ -2311,12 +2311,14 @@ codeunit 12 "Gen. Jnl.-Post Line" GLEntry."Source Currency Amount" := AmountSrcCurr; end; + // Net-of-VAT source amount applies only to the account's own line, not to system-created VAT split entries (which already carry their correct source amount). if not (GLAcc."Source Currency Code" in ['', GLSetup."LCY Code"]) and not (GenJnlLine."Currency Code" in ['', GLSetup."LCY Code"]) and not (GenJnlLine."Additional-Currency Posting" = GenJnlLine."Additional-Currency Posting"::"Additional-Currency Amount Only") and - not IsVendorPayableAccount(GLAcc."No.") + not SystemCreatedEntry then - GLEntry."Source Currency Amount" := GenJnlLine.Amount / (1 + GenJnlLine."VAT %" / 100); + if not IsVendorPayableAccount(GLAcc."No.") then + GLEntry."Source Currency Amount" := GenJnlLine.Amount / (1 + GenJnlLine."VAT %" / 100); OnAfterInitGLEntry(GLEntry, GenJnlLine, Amount, AmountAddCurr, UseAmountAddCurr, CurrencyFactor, GLReg); end; diff --git a/src/Layers/CH/Tests/Local/TestSRGLEntriesForeignC.Codeunit.al b/src/Layers/CH/Tests/Local/TestSRGLEntriesForeignC.Codeunit.al index 7311cf8aea8..16e61b80246 100644 --- a/src/Layers/CH/Tests/Local/TestSRGLEntriesForeignC.Codeunit.al +++ b/src/Layers/CH/Tests/Local/TestSRGLEntriesForeignC.Codeunit.al @@ -15,6 +15,8 @@ codeunit 144026 "Test SR G/L Entries Foreign C." LibraryCH: Codeunit "Library - CH"; LibraryERM: Codeunit "Library - ERM"; LibraryCostAccounting: Codeunit "Library - Cost Accounting"; + Assert: Codeunit Assert; + IncorrectSourceCurrencyAmountErr: Label 'Source Currency Amount on G/L entry for account %1 is incorrect.', Comment = '%1 = G/L Account No.'; [Test] [HandlerFunctions('ReportRequestPageHandler,GLAccountCreationMessageHandler')] @@ -86,11 +88,95 @@ codeunit 144026 "Test SR G/L Entries Foreign C." VerifyReportData(GenJournalLine, GLAccountNo); end; + [Test] + [TransactionModel(TransactionModel::AutoCommit)] + [Scope('OnPrem')] + procedure VerifySourceCurrencyVATAmountOnForeignPurchaseVATEntry() + var + GenJournalLine: Record "Gen. Journal Line"; + VATPostingSetup: Record "VAT Posting Setup"; + GeneralPostingSetup: Record "General Posting Setup"; + Currency: Record Currency; + CurrencyCode: Code[10]; + ExpenseAccountNo: Code[20]; + VATPct: Decimal; + GrossAmount: Decimal; + ExpectedNet: Decimal; + ExpectedVAT: Decimal; + begin + // [FEATURE] [AI test 0.4] + // [SCENARIO 647818] Source-currency VAT G/L entry of a foreign-currency purchase must carry the VAT amount, not the net amount. + Initialize(); + + // [GIVEN] A foreign currency (1:1 rate) and source-currency posting on both the expense and the purchase VAT account + VATPct := 25; + GrossAmount := 1000; + CurrencyCode := LibraryERM.CreateCurrencyWithExchangeRate(WorkDate() - 1, 1, 1); + Currency.Get(CurrencyCode); + LibraryERMCountryData.UpdateGeneralLedgerSetup(); + LibraryCH.CreateGeneralPostingSetup(GeneralPostingSetup); + LibraryCH.CreateVATPostingSetup(VATPostingSetup, VATPostingSetup."VAT Calculation Type"::"Normal VAT", '', ''); + VATPostingSetup.Validate("VAT %", VATPct); + VATPostingSetup.Modify(true); + ExpenseAccountNo := CreateGLAccount(GeneralPostingSetup, VATPostingSetup, CurrencyCode); + SetSourceCurrencyPosting(VATPostingSetup."Purchase VAT Account", CurrencyCode); + + // [GIVEN] A purchase general journal line in the foreign currency for a VAT-inclusive amount + CreatePurchaseJnlLineFCY(GenJournalLine, ExpenseAccountNo, CurrencyCode, VATPostingSetup, GrossAmount); + + // [WHEN] The journal line is posted + LibraryERM.PostGeneralJnlLine(GenJournalLine); + + // [THEN] The expense G/L entry keeps the net amount and the VAT G/L entry keeps the VAT amount, both in source currency + ExpectedNet := Round(GrossAmount / (1 + VATPct / 100), Currency."Amount Rounding Precision"); + ExpectedVAT := GrossAmount - ExpectedNet; + VerifySourceCurrencyAmount(GenJournalLine."Document No.", ExpenseAccountNo, ExpectedNet); + VerifySourceCurrencyAmount(GenJournalLine."Document No.", VATPostingSetup."Purchase VAT Account", ExpectedVAT); + end; + local procedure Initialize() begin LibraryVariableStorage.Clear(); end; + local procedure SetSourceCurrencyPosting(GLAccountNo: Code[20]; CurrencyCode: Code[10]) + var + GLAccount: Record "G/L Account"; + begin + GLAccount.Get(GLAccountNo); + GLAccount.Validate("Income/Balance", GLAccount."Income/Balance"::"Balance Sheet"); + GLAccount.Validate("Source Currency Posting", GLAccount."Source Currency Posting"::"Same Currency"); + GLAccount.Validate("Source Currency Code", CurrencyCode); + GLAccount.Modify(true); + end; + + local procedure CreatePurchaseJnlLineFCY(var GenJournalLine: Record "Gen. Journal Line"; ExpenseAccountNo: Code[20]; CurrencyCode: Code[10]; VATPostingSetup: Record "VAT Posting Setup"; GrossAmount: Decimal) + var + GenJournalBatch: Record "Gen. Journal Batch"; + begin + LibraryCostAccounting.SetupGeneralJnlBatch(GenJournalBatch); + LibraryERM.CreateGeneralJnlLine( + GenJournalLine, GenJournalBatch."Journal Template Name", GenJournalBatch.Name, + GenJournalLine."Document Type"::Invoice, GenJournalLine."Account Type"::"G/L Account", ExpenseAccountNo, GrossAmount); + GenJournalLine.Validate("Currency Code", CurrencyCode); + GenJournalLine.Validate("Gen. Posting Type", GenJournalLine."Gen. Posting Type"::Purchase); + GenJournalLine.Validate("VAT Bus. Posting Group", VATPostingSetup."VAT Bus. Posting Group"); + GenJournalLine.Validate("VAT Prod. Posting Group", VATPostingSetup."VAT Prod. Posting Group"); + GenJournalLine.Modify(true); + end; + + local procedure VerifySourceCurrencyAmount(DocumentNo: Code[20]; GLAccountNo: Code[20]; ExpectedSrcCurrAmount: Decimal) + var + GLEntry: Record "G/L Entry"; + begin + GLEntry.SetRange("Document No.", DocumentNo); + GLEntry.SetRange("G/L Account No.", GLAccountNo); + GLEntry.FindFirst(); + Assert.AreEqual( + ExpectedSrcCurrAmount, GLEntry."Source Currency Amount", + StrSubstNo(IncorrectSourceCurrencyAmountErr, GLAccountNo)); + end; + [Normal] local procedure SetupTestData(var GenJournalLine: Record "Gen. Journal Line"; var GLAccountNo: Code[20]) var