Odoo
МодульMulti-currency і курсові різниці — як це працює
Валютні рахунки, currency revaluation, курс НБУ як джерело. Дати в експорті: МД, надходження валюти, баланс — і чому вони не збігаються. ПКУ 21.
Що це і навіщо
Щойно компанія починає продавати або купувати у валюті — з’являються курсові різниці. Ти підписав інвойс 1 червня на $10 000, курс 41,2. Гроші прийшли 15 червня, курс 41,8. Різниця — $10 000 × (41,8 − 41,2) = 6 000 ₴ — і вона має десь у бухобліку осісти. Бо у звіті про фінрезультати твій реальний дохід не $10 000, а конкретна гривнева сума. Бо в Балансі рахунок 362 (валюта) оцінюється за курсом на дату балансу.
ПКУ 21 каже: курсові різниці визнають у тому періоді, коли вони виникли. УПСБО 21 — приблизно те саме плюс правила перерахунку. У Odoo за це відповідає механізм multi-currency з автоматичною курсовою переоцінкою. Налаштуєш правильно — усе рахується без бухгалтера. Налаштуєш криво — місяць закриватиметься з матюками.
Як це працює
Базові поняття:
res.currency— валюта. UAH, USD, EUR.res.currency.rate— курс на конкретну дату.company.currency_id— основна валюта компанії (UAH).account.move.currency_id— валюта документа (може відрізнятися від company).account.move.line.amount_currency— сума у валюті документа.account.move.line.debit/credit— сума в основній валюті (UAH).
Принцип: кожна сума зберігається в базі одразу у двох валютах. UAH-сума — за курсом на дату документа.
# Створюємо інвойс у USD
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': partner.id,
'currency_id': self.env.ref('base.USD').id,
'invoice_date': '2026-06-01',
'invoice_line_ids': [(0, 0, {
'name': 'Експортна продукція',
'price_unit': 10000,
'quantity': 1,
})],
})
# На дату 2026-06-01 курс = 41.20
invoice.action_post()
# DR 362 (валюта): debit=412000 (UAH), amount_currency=10000 (USD)
# CR 703: credit=412000 (UAH), amount_currency=10000 (USD)
Коли 15 червня надходить платіж за курсом 41.80:
DR Bank (USD) amount_currency=10000 debit=418000
CR 362 amount_currency=10000 credit=412000
CR Gain on FX amount_currency=0 credit=6000
Останній рядок — курсова різниця. Її формує payment matching автоматично, але спершу треба прописати рахунки income_currency_exchange_account_id (для прибутку, рахунок 714) і expense_currency_exchange_account_id (для збитку, рахунок 945).
Currency revaluation — окремий процес. На дату балансу (31 числа) усі валютні залишки (на 362, 316 — закордонні рахунки) переоцінюють за курсом НБУ. Запуск — через Accounting → Operations → Unrealized Currency Gains/Losses. Створює окремий misc move з різницею.
У контексті українського обліку
Що треба налаштувати:
- Активувати multi-currency. Settings → Accounting → Multi-currency.
- Завантажити валюти. USD, EUR — найчастіше. UAH вже є.
- Джерело курсу.
currency_provider='nbu'для НБУ. Cron щодня сам підтягує курс. - Валютні рахунки в плані.
- 362 — Розрахунки з покупцями у валюті.
- 316 — Розрахунки з іншими дебіторами у валюті.
- 314 — Поточний рахунок в інвалюті.
- 5-ті субрахунки для кредитів і кредиторки.
- Рахунки курсових різниць.
- 714 — Дохід від операційної курсової різниці.
- 945 — Втрати від операційної курсової різниці.
- 744 — Дохід від неопераційної курсової різниці.
- 974 — Втрати від неопераційної курсової різниці.
- На кожному
account.journal—currency_id. Це валюта операцій журналу. Для валютних — USD/EUR. Для UAH-операцій — UAH або порожнє поле.
Як ми робимо (defense-контекст)
У ТОВ «УкрПром-Тех» валюта рухається трьома напрямами:
- Експорт ВТП. Контракти у USD/EUR. Інвойси, платежі. Курсові різниці на 362 і 714/945.
- Імпорт компонентів. Закупівля сировини і компонентів за USD/EUR. Платіжки. Курсові на 632 і 714/945.
- Валютний кредит. EUR-кредит на R&D. Регулярні платежі тіла і %, переоцінка на дату балансу.
Підступна дата експорту. За ПКУ 187.1 і ст. 28 МКУ для експортних операцій момент виникнення ПДВ — це оформлення МД, а не надходження валюти. Тобто:
- 1 червня — підписали SO, курс 41.2 — інвойс на $10 000 = 412 000 UAH.
- 5 червня — оформили МД, курс 41.5 — ПЗ декларуємо за курсом МД, рядок 2.1 на 415 000 UAH. (Не у звичайну колонку, а в окрему графу для експорту.)
- 15 червня — отримали валюту, курс 41.8. Сальдо 362 закривається. Курсова різниця — 6 000 (проти 1 червня), і вона вже потрапила у звіт за рік.
- 30 червня — переоцінка балансу. Якщо на 362 лишився залишок — переоцінюємо станом на 30.06.
У Odoo цю логіку доведеться винести в окремий модуль експорту: він фіксує курс МД в окремому полі, окремо пише курсові за датою МД для декларації, окремо — за датою платежу для бухгалтерії.
Типові граблі
- Курс НБУ не оновлюється. Cron вимкнено або токен прострочено. Перевір Settings → Technical → Scheduled Actions → Update Currency Rate. Frequency = daily.
- Курс узято на одну дату, а інвойс — на іншу. Користувач створив інвойс заднім числом, курсу на ту дату немає — Odoo бере найближчий доступний. Звіти попливуть. Якщо треба точно — завантаж історичні курси.
- Експорт у рядок 2.1 — за курсом надходження валюти. Неправильно: тільки за курсом МД. Залишиш «як з коробки» — отримаєш помилку в декларації. Потрібна окрема логіка.
- Currency revaluation не запускається сама. За замовчуванням це ручна операція. Забув запустити перед закриттям місяця — і Баланс «п’яний» (валютні залишки не переоцінені). Внеси в monthly closing checklist.
- Курсову враховано на дату платежу, але не на дату закриття. Платіж пройшов, gain/loss зафіксовано — а потім переоцінка балансу дала ще одну різницю. Подвійний рахунок? Ні, тут хитро: revaluation створює тимчасові entries, які сторнуються 1 числа наступного періоду. Не плутай їх з фіналізованими.
amount_currency≠ debit за курсом. Виправляєш move-лінію вручну — ризикуєш порушити консистентність. Odoo попередить. Не ігноруй.- Рахунок без
currency_id, але рух у валюті. Тодіamount_currencyпорожній, рух іде тільки в UAH. На валютному рахунку 362 безcurrency_idправильної валютної аналітики не буде. Перевір план: на 362, 316, 314 —currency_id=False(для multi), на 36-х субрахунках —currency_id=USDабоEUR(для жорсткого). - На партнерові не виставлено валюту контракту. Інвойс автоматично піде в UAH, навіть якщо за договором USD. Типову валюту партнера задають поля
property_purchase_currency_id/ sale.
Дотичне
- Accounting — multi-валютність на рівні account.move
- Fiscal Position — валютні fiscal positions (експорт)
- Cron — автоматичне оновлення курсу
- Декларація ПДВ — як експорт у валюті потрапляє у декларацію
- Експорт ГП · 0% — експорт з 0%
Де цей модуль зустрічається7
- ГайдЕкспорт · ПН типу «07»Виставляємо ПН за нульовою ставкою на нерезидента, прив'язуємо до митної декларації ЕК10 і реєструємо в ЄРПН т…
- ГайдЗакриття місяця · чеклистПокрокова процедура місячного циклу від перевірки первинки до Lock Date. Для головбуха ТОВ «УкрПром-Тех» на Od…
- ГайдІмпорт: МД + ПДВЯк оформити надходження імпортних компонентів через МД, врахувати мито й акциз у собівартості і визнати ПДВ за…
- ГайдКурсові на дату балансуПерерахунок монетарних статей у валюті на 31 число за курсом НБУ. Що таке монетарна стаття за П(С)БО 21, які р…
- OdooAccountingЯк Odoo веде подвійний запис: account.move як універсальний документ-проводка, журнали як шафи, account.move.l…
- OdooCronir.cron, model_id, function_id. Які стандартні cron важливі. Як писати власні — для перевірки ЄРПН-статусу, на…
- OdooFiscal PositionМеханізм, що автоматично підмінює ставки ПДВ і рахунки залежно від контрагента, валюти, сценарію. Без нього не…