Skip to content

NEW Option MULTICURRENCY_PAYMENT_USE_REAL_AMOUNTS: enter the real amounts on multicurrency payments - #39665

Open
Pichinov-Jose wants to merge 1 commit into
Dolibarr:developfrom
Pichinov-Jose:feat/multicurrency-payment-real-amounts
Open

NEW Option MULTICURRENCY_PAYMENT_USE_REAL_AMOUNTS: enter the real amounts on multicurrency payments#39665
Pichinov-Jose wants to merge 1 commit into
Dolibarr:developfrom
Pichinov-Jose:feat/multicurrency-payment-real-amounts

Conversation

@Pichinov-Jose

@Pichinov-Jose Pichinov-Jose commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

What this solves

On a payment for an invoice in a foreign currency, Dolibarr derives one of the two amounts (company currency / invoice currency) from the other at the invoice rate. The amount really paid in the company currency almost always differs from that derivation — the bank applies its own rate on the day of the transfer — so the recorded payment does not match the bank statement, and the reconciliation carries a phantom difference.

What it adds

Everything is gated by a new option MULTICURRENCY_PAYMENT_USE_REAL_AMOUNTS (off by default — behaviour is strictly unchanged without it).

  1. Payment pages (customer and supplier): both the amount in the invoice currency and the real amount in the company currency can be entered; a read-only exchange rate derived live from the two amounts is displayed.
  2. Paiement::create() / PaiementFourn::create(): when both amounts are provided for an invoice, keep them as entered (no derivation), derive the per-invoice exchange rate and store it on the dispatch line. An error is raised when the two amounts have opposite signs, a non-blocking warning when the derived rate differs by more than 50% from the invoice rate (probable swap of the two fields).
  3. Paid status decided on the balance in the invoice currency: settled at the real amounts, a multicurrency invoice keeps a residual amount in company currency — that residual is the exchange-rate difference, it must not keep the invoice open.
  4. Display: in the payments table of the invoice card, each payment shows a sub-line with the amount in the invoice currency and the real rate of that payment (multicurrency_amount / amount), so a rate different from the invoice rate is visible at a glance. The payment tooltip (customer and supplier) and the supplier invoice tooltip show the same information (amount in the invoice currency, rate).
  5. A posteriori fix: a payment whose foreign amount is missing (recorded before the option, or by an import) can be completed from the payment card — gated by the hidden option MULTICURRENCY_PAYMENT_ALLOW_EDIT_REAL_AMOUNT plus admin rights.

Relationship with #38972 (@lvessiller)

The merged fix #38972 stores the invoice currency code/rate on the dispatch line when the caller does not fill the arrays. This PR integrates with it: in real-amounts mode the per-invoice derived rate is set into $this->multicurrency_tx[$key], which that fallback then naturally respects; without the option, the fallback behaviour is unchanged.

Compatibility

Tested

Supplier and customer flows on real USD/TWD invoices: payment recorded with the real amounts, per-invoice derived rate stored, paid status set from the foreign balance, residual company-currency amount visible as the exchange difference.
Here is a screenshot:

pr39665_paiement_montants_reels

Here are the tooltip and sublines orders screenshots:

pr39665_tooltip_facture pr39665_tooltip_paiement

…unts on multicurrency payments

On a payment for an invoice in a foreign currency, Dolibarr derives one of
the two amounts (company currency / invoice currency) from the other at the
invoice rate. The amount really paid in the company currency almost always
differs from that derivation, so the recorded payment does not match the
bank.

Under this option (off by default):
- both the amount in the invoice currency and the real amount in the
  company currency can be entered on the payment pages (customer and
  supplier); a read-only derived exchange rate is displayed live;
- Paiement/PaiementFourn::create() keep both amounts as entered, derive
  the per-invoice exchange rate from them and store it on the dispatch
  line; a warning is raised when the derived rate is far from the invoice
  rate (probable swap), an error when the signs differ;
- the paid status is decided on the balance in the invoice currency: the
  residual amount in company currency is the exchange-rate difference;
- the payment list of the invoice card and the invoice/payment tooltips
  show the amount in the invoice currency and the rate as a sub-line;
- a payment whose foreign amount is missing can be fixed a posteriori from
  the payment card (hidden option MULTICURRENCY_PAYMENT_ALLOW_EDIT_REAL_AMOUNT,
  admin only).
@Pichinov-Jose
Pichinov-Jose force-pushed the feat/multicurrency-payment-real-amounts branch from a02ae67 to c1a2485 Compare August 22, 2026 18:51
@Pichinov-Jose
Pichinov-Jose marked this pull request as ready for review August 22, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant