Payment Entry Calculates Wrong Amount After Changing Mode of Payment

Hello everyone,

I am facing an issue with a multi-currency Payment Entry in ERPNext.

Company currency is USD, and the Sales Invoice currency is EUR.

Sales Invoice:

Invoice Amount: 10,000 EUR
Exchange Rate: 1 EUR = 1.1658 USD
Grand Total / Outstanding: 11,658 USD

The Payment Entry is created from:

Sales Invoice > Create > Payment

At first, the invoice reference is correct:

Grand Total: 11,658 USD
Outstanding: 11,658 USD
Allocated: 11,658 USD

But when I change the Mode of Payment, ERPNext recalculates the amounts incorrectly:

Paid Amount: 15,844.27 USD
Received Amount: 13,590.90 EUR
Target Exchange Rate: 1.1658

It also adds a Forex Gain/Loss row with:

Amount: -15,844.27 USD

Expected result should remain:

Paid Amount: 11,658 USD
Received Amount: 10,000 EUR
Allocated Amount: 11,658 USD
Difference Amount: 0

Is this expected behavior because of the selected Mode of Payment account/currency, or could it be a bug in the recalculation after changing Mode of Payment?

Any guidance on the correct setup would be appreciated.

Changing mode of payment can change the bank account. Have confirmed the correct bank account has the expected currency?

My experience (in V15 but a persistent issue from earlier versions) is that a few things are broken if the following things are true, one of them being the payment value set on the Mode of Payment for a POS SINV (another being the check for paid amount/outstanding amount)

a) Currency is ‘foreign’ currency

b) Debit To account is in company currency

c) Mode of Payment is in ‘foreign’ currency

d) Usually seems to happen on returns

It’s something to do with incorrect assumptions when doc.currency != doc.party_account_currency (with the latter coming from the ‘debit to’ account). We use a single ‘debtors’ account (in company currency) for all SINVs; we could create (for example) a ‘Debtors EUR’ account but instead I’ve got a hacky ‘set the party account currency to the currency when running calculate_taxes_and_totals’ thing which is not ideal and has just broken because of equivalent code in the frontend.