Odoo 19 Manual Exchange Rate Suite by Plennix — Take Control of Multi-Currency Accounting

If your company books transactions in one currency but reports in another — or sits in a market where the official, bank, and negotiated rates are three different numbers — you have already met the limits of Odoo's automatic exchange rate. The system pulls one rate per dayand applies it everywhere: invoices, payments, asset depreciation, and stock valuations. That works in stable currency zones. It breaks down in regulated, dollarised, or volatile economies where the rate on the invoice is not the rate on the payment, and every percentage point of drift becomes a reconciliation problem at month-end.

The Plennix Manual Exchange Rate suite for Odoo 19 closes that gap — a coordinated set of four add-ons that let your finance team override the automatic rate at every accounting touchpoint and have those overrides flow consistently through the entire chain, from sales order to depreciation board, with zero drift.

Why automatic exchange rates fail multi-currency businesses

Odoo's standard FX engine assumes one rate per currency per day. Multi-currency businesses live with several at once: a central bank rate for statutory reporting, a bank rate that hits the operating account, a negotiated rate locked in with a key vendor or customer, and sometimes a board-approved rate for inventory or asset valuation. In MENA markets — Lebanon, Egypt, and across the region — these routinely diverge by 5%, 10%, or more.

An invoice posted at the official rate and paid at the bank rate is not a rounding issue. It is a structural difference of exchange (DOE) that needs to be captured deliberately, in the right journal, at the right time. Forcing the automatic rate everywhere hides the DOE in the wrong accounts and makes AR, AP, and inventory valuations impossible to reconcile against bank statements. The Plennix approach: let users specify the rate that actually applied”, propagate it consistently through every downstream document, and post the gap to a dedicated Exchange Difference journal.

The three-currency architecture underneath

The suite sits on top of `plnx_account`, the Plennix core that adds a second and third currency to every Odoo company. Out of the box, Odoo tracks one company currency; with `plnx_account`, every journal entry, invoice line, payment, asset, and budget line tracks amounts in three currencies simultaneously — for example EGP as primary statutory currency, USD as the operational reporting currency, and EUR as a third reference.

 Every Plennix `account.move` carries three rate fields — `main_rate`, `secondary_rate`, `third_rate`, stored at six-decimal precision (`digits=(12, 6)`). The Manual Exchange Rate suite gives accountants direct control over those fields, with propagation rules that ensure overrides survive every downstream operation.

The four modules in the suite

1. Plennix Multi-Currency Accounting Manual Exchange Rate (foundation)

Module: `plnx_account_manual_exchange_rate`.

The foundation adds an **Apply Manual Exchange** checkbox — gated by an `is_exchange` Boolean on `account.move` — to invoices, vendor bills, journal entries, sales orders, purchase orders, and HR expenses. When unchecked, Odoo behaves as standard: the automatic rate of the document date applies. When checked, three editable rate fields appear, pre-populated with the current standard rate.

```python
class AccountMove(models.Model):
 _inherit = "account.move"
is_exchange = fields.Boolean(string="Apply Manual Exchange", tracking=True)
main_rate      = fields.Float(digits=(12, 6), default=1.0, tracking=True)
secondary_rate = fields.Float(digits=(12, 6), default=1.0, tracking=True)
third_rate     = fields.Float(digits=(12, 6), default=1.0, tracking=True)
```

Three details make this production-grade rather than a quick hack:

Counter-value labelling: The field next to each rate dynamically reads "USD to EGP" or "EUR to EGP" depending on the document currency. Entering the inverse (`0.0202` instead of `49.50`) is the single most common user error; the dynamic label removes that confusion.

Identity-conversion safety: A rate field whose target equals the document currency is an identity conversion. The module skips validation on those, so a readonly identity field never blocks confirmation.

Propagation hooks. A manual rate set on a sales or purchase order automatically forwards to the invoice or bill created from it. Credit notes and Odoo's deferred revenue/expense entries inherit the originating document's rates, so partial recognition over twelve months stays consistent with the booking rate.

2. Plennix Accounting Multi Payment Manual Exchange Rate

Module: `plnx_account_payment_manual_exchange_rate`.

Payments are where multi-currency accounting normally falls apart. A customer invoice booked at 49.50 EGP/USD on the 1st gets paid at 50.50 EGP/USD on the 15th — the AR line has to close exactly in USD while the EGP gap posts cleanly to the Exchange Difference Journal as a realised FX gain or loss.

This module extends the multi-line payment workflow  so each payment line carries its own `is_exchange` flag and its own three rates — important when one register batch covers several invoices in different currencies, or one bank deposit splits across customers at different negotiated rates. Automatic counter-value inversion lets accountants type the human-readable number ("1 USD = 50.50 EGP") without worrying which way Odoo stores it. Past draft state, the rate columns lock for audit. At reconciliation, the “EGP gap posts as a DOE through the Exchange Difference Journal” while the AR or AP line closes to zero in the transaction currency.

3. Plennix Multi-Currency Accounting Asset Manual Exchange Rate

 Module: `plnx_account_manual_exchange_rate_asset`.

Fixed assets are the most subtle place where automatic rates cause problems. An asset is bought once but depreciated over months or years. If each depreciation entry is posted at the period-end automatic rate, the sum of twelve monthly EGP depreciations will not equal the original asset value in EGP — even though the asset is fully written down in USD. That residual sits forever on the depreciation expense account, or worse, on Prepaid Insurance for a deferred expense.

This bridge module solves that with what we call the zero-drift property.

```python
class AccountAsset(models.Model):
_inherit = "account.asset"
is_exchange = fields.Boolean(string="Apply Manual Exchange", tracking=True)
bill_currency_id = fields.Many2one("res.currency", string="Bill Currency", readonly=True)
main_rate      = fields.Float(digits=(12, 6), default=1.0)
secondary_rate = fields.Float(digits=(12, 6), default=1.0)
third_rate     = fields.Float(digits=(12, 6), default=1.0)
```

When a vendor bill carrying a manual rate is linked to an asset, the rates propagate automatically from the bill to the asset record. The asset's gross EGP value is computed as *USD amount × bill's `main_rate` not the asset-creation-date auto rate. Every subsequent depreciation JE — for the whole life of the asset — uses the asset's stored rate.

 The mathematical consequence: the sum of N periods of EGP depreciation equals gross EGP exactly. Same for EUR. The same logic covers Odoo's deferred expense and deferred revenue records — Prepaid Insurance closes to zero across a year of EGP weakening instead of carrying a stranded FX residual on the balance sheet.

4. Plennix Stock Landed Cost Manual Exchange Rate

Module: `plnx_custom_landed_cost`.

Import-heavy businesses face a parallel problem on the inventory side. A container clears customs in EGP, but the supplier bill is in USD, freight is in EUR, and insurance is in AED. Standard landed cost applies a single rate; reality requires several. This module adds a complementary capability

Multi-currency fee conversion with manual rate support: When a charge line is linked to a vendor bill that uses a manual rate, the landed cost respects that rate instead of recomputing from the daily auto rate. The Charges sub-table converts every fee to primary, secondary, and third currency consistently with the source documents.

The practical promise: a customs broker invoice paid at a negotiated bank rate gets allocated into stock valuation at that same negotiated rate, not at the central bank rate of the GRN date. Inventory cost matches what hit the bank account.


How the four modules work together

The suite is more than the sum of its parts. The propagation chain runs end-to-end: an accountant ticks Apply Manual Exchange on a sales or purchase order; the rate flows to the invoice or bill, then into the payment wizard via `default_get` and onto both `account.payment` and its synchronised `account.move` (outstanding receipts/payments lines freeze at the payment's rate). At reconciliation, matching AR or AP lines from documents with different manual rates posts the EGP gap to the Exchange Difference Journal — with pro-rata computed on `amount_currency` so the third-currency leg stays mathematically consistent regardless of how USD-EUR moved across the period. For assets and deferred entries, the bill's rate propagates to the asset record and to every recognition JE, producing zero drift. For landed costs, fees linked to manual-rate vendor bills convert at the source rate.

The connecting thread is the `is_exchange` flag: one Boolean that gates rate behaviour consistently across `account.move`, `account.payment`, `account.asset`, and stock charges.

Concrete scenarios this solves

The suite ships with a 17-case QA scenario document. A few representative flows:

Invoice and payment at different rates (realised FX gain). A USD vendor bill posted at 49.50 EGP/USD, paid two weeks later at 50.50. AP closes to zero in USD; the 2,000 EGP gap posts as an FX loss in the Exchange Difference Journal, dated to the later move.

Customer advance applied to a later invoice: A customer prepays 1,000 USD at 49.00; an invoice is issued three weeks later at 50.50. The leftover advance retains its original EGP balance at the prepayment rate; the matched portion produces a correct DOE in EGP with the secondary currency leg cleanly identity-zero.

One payment covers two invoices at different rates: Per-allocation DOE is computed against each invoice's own rate — the bank journal closes in USD while two distinct DOE lines hit the EGP P&L.

Bill → fixed asset, depreciated over twelve months:  An 11,111 USD asset depreciated monthly. With manual exchange rate on the bill, the sum of twelve EGP depreciations equals gross EGP exactly, and the EUR column closes to zero as well.

Bill → deferred expense: A 12,000 USD prepaid insurance recognised monthly. Without manual rate, Prepaid Insurance carries a 7,800 EGP stranded residual at year-end. With manual rate, it closes to zero.

Container import with customs and freight in three currencies: Stock valuation reconciles to the purchase ledger penny-for-penny.

These are not edge cases — they are the daily reality of month-end close in multi-currency markets.

Who this is for

 The Plennix Manual Exchange Rate suite is built for:

 Importers, exporters, and distributors working across hard-currency and local-currency environments.

Regional groups running Odoo across Lebanon, Egypt, the Gulf, and broader MENA markets where official, bank, and contract rates routinely diverge.

Finance teams that need to capture FX gains and losses deliberately, not bury them in misallocated expense lines.

CFOs and controllers who need their balance sheet to close cleanly in all three currencies at month-end, with a defensible audit trail of every rate override.

Get the suite

 The four modules — ` Plennix Multi-Currency Accounting Manual Exchange Rate`, ` Plennix Accounting Multi Payment Manual Exchange Rate`, ` Plennix Multi-Currency Accounting Asset Manual Exchange Rate `, and `Plennix Stock Landed Cost Manual Exchange Rate ` — are part of the Plennix Accounting suite for Odoo 19: 30+ engineered add-ons that extend Odoo's accounting for genuine multi-currency operation.

 Plennix Technologies is an Odoo Gold Partner with offices in Lebanon, UAE, and Egypt, and 70+ multilingual professionals serving live references across wholesale, retail, manufacturing, IT, finance, hospitality, energy, construction, and logistics etc..

 To see the suite in action, request a demo, or scope an implementation, visit https://plennix.com/contactus  or contact your regional Plennix office.

Multi-currency accounting in Odoo 19 does not have to be a reconciliation headache — with the right rate controls in place, it becomes a tool you can rely on.


Strategic CFO Guide to Odoo Accounting in MENA