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

Odoo

Модуль

Fiscal Position — як Odoo підмінює податки

Механізм, що автоматично підмінює ставки ПДВ і рахунки залежно від контрагента, валюти, сценарію. Без нього не запрацюють ні експорт, ні звільнення, ні касовий метод.

Шлях у меню
Бухгалтерія → Налаштування → Фіскальні позиції
Технічна модель
account.fiscal.position, account.fiscal.position.tax, account.fiscal.position.account
Редакція
2026-05-28

Що це і навіщо

Уяви: у тебе є продукт «Кронштейн АА-100», на ньому ставка ПДВ 20% продаж. Продаєш цей кронштейн українському заводу — все добре, 20%. Продаєш литовському — має бути 0% (експорт). Продаєш військовій частині А-1234 — має бути звільнення за п.32 підрозд.2 розд.ХХ ПКУ. Невже на кожен SO бухгалтер вручну редагує ставку?

Ні. Для цього в Odoo є fiscal position — автоматична підміна. По суті це таблиця відповідностей: «у цьому сценарії заміни ставку X на ставку Y, а рахунок A на рахунок B». Прив’язуєш fiscal position до партнера — і щоразу, коли цей партнер з’являється в інвойсі, Odoo підставляє правильні ставки замість стандартних.

При експорті це рятує життя. А якщо налаштувати криво — стає джерелом тонких багів.

Як це працює

Структура моделі:

class AccountFiscalPosition(models.Model):
    _name = 'account.fiscal.position'
    name = fields.Char(required=True)
    tax_ids = fields.One2many('account.fiscal.position.tax', 'position_id')
    account_ids = fields.One2many('account.fiscal.position.account', 'position_id')
    country_id = fields.Many2one('res.country')  # для auto-detect
    auto_apply = fields.Boolean()  # автозастосування за країною/групою

tax_ids — список «з якого податку → на який». Наприклад:

[Експорт]
  20% продаж → 0% продаж — експорт
  7% продаж → 0% продаж — експорт
  20% закупівля → (не заміняти, для постачальника — не наша справа)

account_ids — те саме, тільки для рахунків. Застосовують рідше, але працює: «замість 703 (доходи від реалізації) — на 7029 (доходи від експорту)».

Як це спрацьовує:

  1. Створюєш інвойс. Партнер має property_account_position_id = 'Експорт'.
  2. Додаєш продукт. На продукті стандартна ставка 20% продаж.
  3. Odoo дивиться: «о, fiscal position Експорт каже, що 20% продаж замінити на 0% експорт».
  4. У рядку інвойсу автоматично стає tax_ids = [0% експорт].
# Як побачити, що заміниться
fp = self.env.ref('l10n_ua.fp_export')
for tax_line in fp.tax_ids:
    print(f'{tax_line.tax_src_id.name}{tax_line.tax_dest_id.name}')

Шлях у меню: Accounting → Configuration → Fiscal Positions. Прив’язка до партнера — на формі res.partner → вкладка «Sales & Purchase» → поле «Fiscal Position».

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

Типові fiscal positions для виробничого підприємства:

Fiscal PositionСценарійЗаміняє
ЕкспортПостачання за межі України20% / 7% → 0% експорт
Звільнено 197Операції, звільнені від ПДВ20% / 7% → Без ПДВ — звільнено
Оборона (п.32)Постачання ЗСУ і ВТП20% → 0% — оборонне (тег рядка 3.2)
Поза об’єктом 196Не є об’єктом оподаткування20% → Без ПДВ — необ’єкт
Касовий методПостачальники-комуналки20% → 20% cash basis
Імпорт послугНерезидент-постачальник послуг+ автоматичний 20% умовний продаж

Налаштування auto_apply:

  • За країною партнера. Якщо country_id != UA і fiscal position теж має country_id != UA — вона застосовується сама, щойно ви заводите партнера.
  • За групою партнера. Партнерів можна згрупувати («Військові частини», «Комуналка») і прив’язати FP до групи.

Явне призначення на партнері завжди переважує auto-apply.

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

ТОВ «УкрПром-Тех» має складну матрицю fiscal positions для defense-сценаріїв:

  1. Звичайне постачання військовим частинам. Якщо це продукція оборонного призначення (за переліком КМУ 224, у режимі звільнення п.32 підрозд.2 розд.ХХ) — fiscal position «Оборона-32». Вона заміняє ставку і ставить теги рядка 3.2 у декларації.
  2. Експорт ВТП. Партнер-нерезидент, є дозвіл ДСЕКУ, оформлено МД. Тут окрема fiscal position «Експорт ВТП»: крім 0%, вона додає аналітику експортного контролю.
  3. Безоплатна передача (гуманітарка). На SO ставимо fiscal position «Безоплатно — оподатковуване». Хитрість у тому, що за ст. 188.1 ПКУ безоплатна передача — це постачання за ринковою ціною. Тому ставка лишається 20%, а от рахунок витрат інший (94 «Інші витрати операційної діяльності»).
  4. Внутрішнє постачання між філіями. Fiscal position «Поза об’єктом — внутрішньо»: рух між власними підрозділами не є об’єктом ПДВ.

Server action під час заведення партнера сам визначає fiscal position за такими ознаками:

  • ЄДРПОУ у форматі А-XXXX → «Оборона-32».
  • country_id != UA → «Експорт».
  • у назві «ОСББ» / «ЖЕК» / «Управління» → пропонує «Касовий метод» (бухгалтер підтверджує).

Типові граблі

  • Fiscal position є, але не спрацювала. На FP вказано замінити «20% продаж», а на продукті стоїть «20% продаж UA» — інший tax record. Перевір, чи точно збігаються ID ставок у замінах.
  • FP замінили вручну на інвойсі, потім створили інший SO для того ж партнера — і знову стандартна ставка. FP береться з партнера в момент створення документа. Зміна на одному документі на інші не вплине. Тож або міняй на партнері, або щоразу руками.
  • Експортний інвойс пішов з 20%, ЄРПН прийняв, а декларація неправильна. Так буває, коли забув виставити FP на партнера-нерезидента й одразу підтвердив SO. Виправлення: сторнуй інвойс через credit note (з тією ж кривою ставкою!), потім зроби новий інвойс із правильною FP. На ПН — РК.
  • Auto-apply за країною конфліктує. Дві FP з country_id=UA — Odoo візьме ту, що має найвищий пріоритет. Контролюй sequence.
  • На партнерові-резиденті стоїть «Експорт». Хтось випадково клікнув — і всі продажі цьому партнеру йдуть під 0%. Бухгалтер може не помітити, а аудитор помітить точно. Логуй зміни FP-поля через mail.thread.
  • FP підмінила ставку, але не тег. Якщо в замісній ставці не налаштовані repartition lines, декларація її не побачить. Перевіряй: підставлена ставка має повний набір репартиції з тегами.
  • Cash basis FP без правильного tax_exigibility. Підставив звичайну 20% замість cash-basis 20% — і нараховуєш ПДВ на дату інвойсу, а не платежу. Сенс касового методу втрачено. Замінна ставка має бути саме cash basis.

Дотичне

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