Перейти до основного контенту
База знань · виробничий облік USD41,42 ПДВ20% МЗП8 000

Odoo

Модуль

Multi-currency і курсові різниці — як це працює

Валютні рахунки, currency revaluation, курс НБУ як джерело. Дати в експорті: МД, надходження валюти, баланс — і чому вони не збігаються. ПКУ 21.

Шлях у меню
Бухгалтерія → Налаштування → Валюти
Технічна модель
res.currency, res.currency.rate, account.move (currency_id)
Редакція
2026-05-28

Що це і навіщо

Щойно компанія починає продавати або купувати у валюті — з’являються курсові різниці. Ти підписав інвойс 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 з різницею.

У контексті українського обліку

Що треба налаштувати:

  1. Активувати multi-currency. Settings → Accounting → Multi-currency.
  2. Завантажити валюти. USD, EUR — найчастіше. UAH вже є.
  3. Джерело курсу. currency_provider='nbu' для НБУ. Cron щодня сам підтягує курс.
  4. Валютні рахунки в плані.
    • 362 — Розрахунки з покупцями у валюті.
    • 316 — Розрахунки з іншими дебіторами у валюті.
    • 314 — Поточний рахунок в інвалюті.
    • 5-ті субрахунки для кредитів і кредиторки.
  5. Рахунки курсових різниць.
    • 714 — Дохід від операційної курсової різниці.
    • 945 — Втрати від операційної курсової різниці.
    • 744 — Дохід від неопераційної курсової різниці.
    • 974 — Втрати від неопераційної курсової різниці.
  6. На кожному account.journalcurrency_id. Це валюта операцій журналу. Для валютних — USD/EUR. Для UAH-операцій — UAH або порожнє поле.

Як ми робимо (defense-контекст)

У ТОВ «УкрПром-Тех» валюта рухається трьома напрямами:

  1. Експорт ВТП. Контракти у USD/EUR. Інвойси, платежі. Курсові різниці на 362 і 714/945.
  2. Імпорт компонентів. Закупівля сировини і компонентів за USD/EUR. Платіжки. Курсові на 632 і 714/945.
  3. Валютний кредит. 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.

Дотичне

Де цей модуль зустрічається7