Odoo
МодульFiscal Position — як Odoo підмінює податки
Механізм, що автоматично підмінює ставки ПДВ і рахунки залежно від контрагента, валюти, сценарію. Без нього не запрацюють ні експорт, ні звільнення, ні касовий метод.
Що це і навіщо
Уяви: у тебе є продукт «Кронштейн АА-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 (доходи від експорту)».
Як це спрацьовує:
- Створюєш інвойс. Партнер має
property_account_position_id = 'Експорт'. - Додаєш продукт. На продукті стандартна ставка
20% продаж. - Odoo дивиться: «о, fiscal position Експорт каже, що 20% продаж замінити на 0% експорт».
- У рядку інвойсу автоматично стає
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-сценаріїв:
- Звичайне постачання військовим частинам. Якщо це продукція оборонного призначення (за переліком КМУ 224, у режимі звільнення п.32 підрозд.2 розд.ХХ) — fiscal position «Оборона-32». Вона заміняє ставку і ставить теги рядка 3.2 у декларації.
- Експорт ВТП. Партнер-нерезидент, є дозвіл ДСЕКУ, оформлено МД. Тут окрема fiscal position «Експорт ВТП»: крім 0%, вона додає аналітику експортного контролю.
- Безоплатна передача (гуманітарка). На SO ставимо fiscal position «Безоплатно — оподатковуване». Хитрість у тому, що за ст. 188.1 ПКУ безоплатна передача — це постачання за ринковою ціною. Тому ставка лишається 20%, а от рахунок витрат інший (94 «Інші витрати операційної діяльності»).
- Внутрішнє постачання між філіями. 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.
Дотичне
- Податки UA — налаштування самих ставок
- Касовий метод — окрема механіка касового методу
- Sales — як FP застосовується на SO
- ПН/РК — як FP впливає на тип причини ПН
- Валюта — FP при валютних операціях
- Експорт ГП · 0% — експорт ГП на практиці
Де цей модуль зустрічається8
- ГайдЕкспорт · ПН типу «07»Виставляємо ПН за нульовою ставкою на нерезидента, прив'язуємо до митної декларації ЕК10 і реєструємо в ЄРПН т…
- ГайдКасовий 187.7Налаштовуємо в Odoo сценарій, де ПЗ за постачанням бюджетним установам (в/ч, ДОТ, МО) виникає на дату надходже…
- ГайдFiscal Position для ЗСУНалаштовуємо в Odoo фіскальну позицію «Оборона-197.6», прив'язуємо її до військової частини й одразу отримуємо…
- OdooВалютаВалютні рахунки, currency revaluation, курс НБУ як джерело. Дати в експорті: МД, надходження валюти, баланс — …
- OdooКасовий методЯк налаштувати tax_exigibility='on_payment' для постачальників ЗСУ (ст. 187.7) і комуналок (ст. 187.10). Wizar…
- OdooПодатки UAЯк налаштувати account.tax для ПДВ 20%, 7%, 0%, без ПДВ і звільнення — і як зв'язати ставки з fiscal positions…
- Odool10n_uaБазовий модуль адаптації Odoo до України: план рахунків, ПДВ-ставки, валюта, дати. Що в коробці є, а чого нема…
- OdooSalesЗамовлення покупця як точка входу в Odoo — звідси розгортається ланцюг постачання, виробництва і платежу.