[APAC] Keep vendor ACY on purchase invoice payables entry - #10168
[APAC] Keep vendor ACY on purchase invoice payables entry#10168Jose Antonio Garcia Garcia (Jose-agg) wants to merge 5 commits into
Conversation
Agentic PR Review - Round 1Recommendation: AcceptWhat this PR doesThis PR fixes the APAC purchase invoice path when Additional Reporting Currency and Vendor GST Amount (ACY) are enabled. It keeps the vendor-rate ACY on the payables G/L entry when the purchase invoice is in LCY, and it calculates Source Currency Amount from LCY instead of reusing ACY. The change is in HandleDtldAdjustment, before the payables G/L entry is initialized. In the vendor path, UseVendExchRate makes GLCalcAddCurrency keep the supplied TotalAmountAddCurr, so the detailed vendor buffer ACY now reaches the balancing entry instead of being posted as a residual entry. The source-currency-equals-ACY branch is unchanged, and the new test checks the expense ACY, payables ACY, source currency amount, total balances, and absence of residual G/L entries. SuggestionsNone. Risk assessment and necessityRisk: This is a financial posting path, so the main risk is wrong G/L amounts for APAC purchase documents with additional reporting currency. The code change is narrow: one InitGLEntry call now passes the already calculated vendor ACY and an independently calculated source currency amount. There are no schema, public API, or event signature changes. Necessity: The linked bug and PR evidence describe a real live-site case where the payables ACY was left at zero and a residual gains/losses entry was created. The fix targets that root cause without restoring the removed global source-currency state, and the added test covers the reported posting result.
|
3f72dc7
| end; | ||
| end; | ||
|
|
||
| local procedure VendorACYExchangeRateApplies(): Boolean |
There was a problem hiding this comment.
VendorACYExchangeRateApplies() (GenJnlPostLine.Codeunit.al, new local procedure) is documented as mirroring GLCalcAddCurrency's vendor-ACY branch, but it omits one of that branch's guard conditions. GLCalcAddCurrency only takes the vendor-ACY path when (AddCurrencyCode <> '') and (GenJnlLine."Additional-Currency Posting" = GenJnlLine."Additional-Currency Posting"::None) AND PurchSetup."Enable Vendor GST Amount (ACY)" and UseVendExchRate; otherwise it falls through to UseVendExchRate := false; exit(OldAddCurrAmount). VendorACYExchangeRateApplies() only checks AddCurrencyCode <> '', UseVendExchRate, and the setup flag — it never checks GenJnlLine."Additional-Currency Posting". When a gen. journal line has "Additional-Currency Posting" <> None (e.g. set to "Amount Only"/"Additional-Currency Amount Only") together with AddCurrencyCode <> '', UseVendExchRate = true and the setup flag enabled, GLCalcAddCurrency would skip the vendor-ACY branch entirely (falling through to the OldAddCurrAmount exit), while the new HandleDtldAdjustment call site will still believe VendorACYExchangeRateApplies() = true and derive the balancing entry's Source Currency Amount via CalcAmountSrcCurr(GenJnlLine, TotalAmountLCY). This diverges from the actual value GLCalcAddCurrency produced for the entry's Additional-Currency Amount, unbalancing the posted document for that posting-rule combination. Add the same "Additional-Currency Posting" = ::None guard to VendorACYExchangeRateApplies() so it truly mirrors GLCalcAddCurrency's condition.
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4
| exit(GetVendGSTAmountACYEnabled()); | ||
| end; | ||
|
|
||
| local procedure GetVendGSTAmountACYEnabled(): Boolean |
There was a problem hiding this comment.
GetVendGSTAmountACYEnabled() caches "Purchases & Payables Setup"."Enable Vendor GST Amount (ACY)" in the new instance-level fields VendGSTAmountACYEnabled/VendGSTAmountACYRead for the lifetime of the codeunit 12 instance, and nothing in the diff ever resets VendGSTAmountACYRead back to false. Codeunit 12 is reused across multiple gen. journal lines/documents within one posting run (this is exactly why UseVendExchRate is defensively reset to false in three separate places in this same codeunit, including one added by this PR). If the setup flag is toggled between documents processed by the same running instance (e.g. an admin change mid-batch, or reuse in a long-running batch/test session), the cached value silently continues driving VendorACYExchangeRateApplies() instead of reflecting the current setup, unlike GLCalcAddCurrency's own PurchSetup.Get() which re-reads on every call. Reset VendGSTAmountACYRead alongside UseVendExchRate at the existing reset points, or drop the cache and read the setup field fresh (as GLCalcAddCurrency already does) since this is a single boolean field.
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4
| PurchasesPayablesSetup.Get(); | ||
| OriginalVendorGSTAmountACY := PurchasesPayablesSetup."Enable Vendor GST Amount (ACY)"; | ||
| PurchasesPayablesSetup."Enable Vendor GST Amount (ACY)" := true; | ||
| PurchasesPayablesSetup.Modify(); |
There was a problem hiding this comment.
This test changes "Purchases & Payables Setup"."Enable Vendor GST Amount (ACY)" without first calling LibrarySetupStorage.Save for that table. If any assertion above fails, the manual restore at the end never runs and later tests inherit the modified setup. Save the setup before the modification so Initialize()/LibrarySetupStorage.Restore() cleans it up even on failure.
| PurchasesPayablesSetup.Get(); | |
| OriginalVendorGSTAmountACY := PurchasesPayablesSetup."Enable Vendor GST Amount (ACY)"; | |
| PurchasesPayablesSetup."Enable Vendor GST Amount (ACY)" := true; | |
| PurchasesPayablesSetup.Modify(); | |
| PurchasesPayablesSetup.Get(); | |
| LibrarySetupStorage.Save(DATABASE::"Purchases & Payables Setup"); | |
| OriginalVendorGSTAmountACY := PurchasesPayablesSetup."Enable Vendor GST Amount (ACY)"; | |
| PurchasesPayablesSetup."Enable Vendor GST Amount (ACY)" := true; | |
| PurchasesPayablesSetup.Modify(); |
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.32.4
What & why
I reproduced this issue in AU with an Additional Reporting Currency enabled,
Enable Vendor GST Amount (ACY)turned on, a blank purchase invoice currency, and a nonzeroVendor Exchange Rate (ACY).The same scenario does not reproduce in W1 because W1 keeps the detailed CV buffer amount as the document/source amount and calculates ACY independently from LCY. APAC uses that buffer differently: it stores the vendor-calculated ACY so the vendor exchange rate is preserved.
The source-currency change from PR 241506 applied the W1 initialization pattern to APAC as well. In this APAC path, that passed zero as the balancing entry's ACY and reused the actual ACY as Source Currency Amount. The posting therefore left the full ACY amount unbalanced and created a separate residual entry.
This change keeps the already-calculated vendor ACY in
Additional-Currency Amountand calculates Source Currency Amount independently from LCY. It does not restore the globalTotalSrcCurrAmountstate removed by PR 241506.Linked work
Fixes AB#641827
How I validated this
What I tested and the outcome
PurchaseInvoiceWithVendorACYPostsACYOnPayablesEntry; the test passes.PurchaseVendorExchangeRateIsUsedForAdditionalCurrencyAmountCalculation; the test passes.1,477.00and vendor ACY rate1.2726.1,477.00, ACY1,879.63.-1,477.00, ACY-1,879.63.Residual caused by roundingentry was created.Risk & compatibility
The change is limited to the APAC layer and does not change W1 behavior, table schemas, or stored data.
The existing branch where Source Currency Code equals ACY remains unchanged. For other APAC entries, source currency and ACY are now calculated independently rather than using the same amount for both fields.