The Problem
Your company operates in USD but invoices a European client in EUR. The invoice amount converts to the wrong USD equivalent, the payment reconciliation creates unexpected exchange differences, or the exchange rate is stuck at an old value. Multi-currency accounting in Odoo is powerful but has many moving parts that can go wrong.
Common Symptoms
- Invoice amount in company currency is wrong
- Exchange rate not updating automatically
- Manual exchange rate entries ignored
- Large unexpected "Exchange Difference" journal entries
- Payment reconciliation showing wrong amounts
- Bank statement import using wrong rate
- Vendor bill converted at invoice date rate instead of payment date
How Odoo Exchange Rates Work
Odoo uses the res.currency.rate model to store exchange rates. Key behaviors:
- Rates are stored as the value of 1 unit of the rate's currency in the company currency
- The rate used depends on the transaction date
- Odoo uses the most recent rate on or before the transaction date
- Automatic rate updates can be configured via a scheduled action
Causes and Fixes
1. Exchange Rate Not Updating
Odoo can fetch rates automatically from providers (ECB, Federal Reserve, etc.), but the scheduled action may not be running.
Fix:
- Go to Accounting > Configuration > Settings > Currencies
- Enable "Automatic Currency Rates"
- Select a rate provider (European Central Bank, Federal Reserve, etc.)
- Set the update frequency (daily recommended)
- Click "Update Now" to test
If auto-update fails:
# Check the scheduled action:
# Settings > Technical > Scheduled Actions
# Search for "Currency Rate Update"
# Check last execution date and any error messages
# Common failures:
# - Firewall blocking outgoing HTTPS to rate provider
# - Rate provider API changed or deprecated
# - SSL certificate issues on the server2. Rate Direction Confusion
Odoo stores rates differently than most people expect. The rate value is how much of the company currency equals 1 unit of the foreign currency.
# If your company currency is USD and you want EUR rate:
# 1 EUR = 1.08 USD
# In Odoo: EUR rate = 1.08 (NOT 0.926)
# If your company currency is EUR and you want USD rate:
# 1 USD = 0.926 EUR
# In Odoo: USD rate = 0.926Fix: Verify rate direction in Accounting > Configuration > Currencies > select currency > Rates tab. The "Company Rate" column shows the rate Odoo uses.
3. Wrong Date Rate Used
Odoo picks the rate based on the document date, not today's date. If an invoice is dated March 1 but you are entering it on March 15, Odoo uses the March 1 rate.
Fix:
- Ensure you have a rate entry for the document date (or earlier)
- If no rate exists for that date, Odoo uses the most recent earlier rate
- Verify: Accounting > Configuration > Currencies > select currency > Rates tab
4. Missing Rate for Currency
If no rate exists at all for a currency, Odoo assumes 1:1, giving wrong conversions.
Fix: Add at least one rate entry:
# Via UI:
# Accounting > Configuration > Currencies > select currency > Rates tab > Add
# Via code/shell:
env['res.currency.rate'].create({
'name': '2026-03-23', # date
'rate': 1.08, # 1 foreign = X company currency
'currency_id': eur_currency_id,
'company_id': company_id,
})5. Exchange Difference Journal Not Configured
When payments are made at a different rate than the invoice, Odoo creates exchange difference entries. If the journal is not configured, these entries fail.
Error: You have to configure the Exchange Difference Journal in your company settings.
Fix: Accounting > Configuration > Settings > Default Accounts section > set "Journal" under "Exchange Difference" and configure the gain/loss accounts.
6. Multi-Company Rate Conflicts
In multi-company setups, each company needs its own set of exchange rates. Rates from Company A do not apply to Company B.
Fix:
- Switch to each company and verify rates exist
- Set up automatic rate updates for each company separately
- Or share rates by leaving company_id blank on rate records
7. Rounding in Converted Amounts
Small rounding differences accumulate over many transactions, creating unexpected exchange difference entries at reconciliation.
Fix:
- This is normal accounting behavior — exchange differences are expected
- Ensure the exchange difference accounts are properly categorized
- Review unrealized exchange gains/losses periodically
- Check currency rounding precision: Accounting > Currencies > Rounding Factor
Debugging Exchange Rate Issues
# Check what rate Odoo will use for a specific date:
SELECT name as date, rate
FROM res_currency_rate
WHERE currency_id = (SELECT id FROM res_currency WHERE name = 'EUR')
AND name <= '2026-03-23'
ORDER BY name DESC
LIMIT 5;
# Check an invoice's exchange rate:
SELECT am.name, am.date, am.currency_id, rc.name as currency,
aml.amount_currency, aml.balance as company_amount
FROM account_move am
JOIN account_move_line aml ON aml.move_id = am.id
JOIN res_currency rc ON rc.id = am.currency_id
WHERE am.id = invoice_id
AND aml.account_id IN (
SELECT id FROM account_account
WHERE account_type = 'asset_receivable'
);
# The effective rate used:
# rate = balance / amount_currencyBest Practices
- Enable automatic rate updates from a reliable provider
- Add manual rates for dates when automatic updates were missed
- Always verify the rate direction (1 foreign = X company currency)
- Configure exchange difference journal and accounts before multi-currency transactions
- Reconcile bank statements promptly to avoid large unrealized differences
- Review exchange difference entries monthly