Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC
This commit is contained in:
116
rsbu_vat_templates/models/account_tax.py
Normal file
116
rsbu_vat_templates/models/account_tax.py
Normal file
@@ -0,0 +1,116 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
# Название налоговой группы НДС (РФ). Общее для всех компаний.
|
||||
TAX_GROUP_NAME = "НДС"
|
||||
|
||||
# Эталонный набор ставок НДС по НК РФ — 1:1 из прежнего account_tax_data.xml.
|
||||
# Способы расчёта:
|
||||
# * «плюс НДС» — налог сверх суммы (amount_type=percent, tax_excluded)
|
||||
# * «в т.ч. НДС» — налог внутри суммы (amount_type=division, tax_included)
|
||||
# Направление: продажа (sale) / покупка (purchase).
|
||||
# «Без НДС» и «НДС 0%» намеренно без «в т.ч.»-вариантов (деление на 0% бессмысленно).
|
||||
# (name, type_tax_use, amount_type, amount, price_include_override)
|
||||
VAT_TAXES = [
|
||||
("Без НДС (продажа)", "sale", "percent", 0.0, "tax_excluded"),
|
||||
("Без НДС (покупка)", "purchase", "percent", 0.0, "tax_excluded"),
|
||||
("НДС 0% (продажа)", "sale", "percent", 0.0, "tax_excluded"),
|
||||
("НДС 0% (покупка)", "purchase", "percent", 0.0, "tax_excluded"),
|
||||
("НДС 5% (продажа)", "sale", "percent", 5.0, "tax_excluded"),
|
||||
("НДС 5% в т.ч. (продажа)", "sale", "division", 5.0, "tax_included"),
|
||||
("НДС 5% (покупка)", "purchase", "percent", 5.0, "tax_excluded"),
|
||||
("НДС 5% в т.ч. (покупка)", "purchase", "division", 5.0, "tax_included"),
|
||||
("НДС 7% (продажа)", "sale", "percent", 7.0, "tax_excluded"),
|
||||
("НДС 7% в т.ч. (продажа)", "sale", "division", 7.0, "tax_included"),
|
||||
("НДС 7% (покупка)", "purchase", "percent", 7.0, "tax_excluded"),
|
||||
("НДС 7% в т.ч. (покупка)", "purchase", "division", 7.0, "tax_included"),
|
||||
("НДС 10% (продажа)", "sale", "percent", 10.0, "tax_excluded"),
|
||||
("НДС 10% в т.ч. (продажа)", "sale", "division", 10.0, "tax_included"),
|
||||
("НДС 10% (покупка)", "purchase", "percent", 10.0, "tax_excluded"),
|
||||
("НДС 10% в т.ч. (покупка)", "purchase", "division", 10.0, "tax_included"),
|
||||
("НДС 22% (продажа)", "sale", "percent", 22.0, "tax_excluded"),
|
||||
("НДС 22% в т.ч. (продажа)", "sale", "division", 22.0, "tax_included"),
|
||||
("НДС 22% (покупка)", "purchase", "percent", 22.0, "tax_excluded"),
|
||||
("НДС 22% в т.ч. (покупка)", "purchase", "division", 22.0, "tax_included"),
|
||||
]
|
||||
|
||||
|
||||
class AccountTax(models.Model):
|
||||
_inherit = "account.tax"
|
||||
|
||||
def _rsbu_ensure_tax_group(self, company, country):
|
||||
"""Найти/создать налоговую группу НДС для компании. Идемпотентно."""
|
||||
Group = self.env['account.tax.group']
|
||||
group = Group.search([
|
||||
('company_id', '=', company.id),
|
||||
('name', '=', TAX_GROUP_NAME),
|
||||
], limit=1)
|
||||
if not group:
|
||||
group = Group.create({
|
||||
'name': TAX_GROUP_NAME,
|
||||
'company_id': company.id,
|
||||
'country_id': country.id if country else False,
|
||||
})
|
||||
return group
|
||||
|
||||
def _rsbu_ensure_vat_taxes(self, company, group, country):
|
||||
"""Создать недостающие ставки НДС для корневой компании. Идемпотентно.
|
||||
|
||||
Дедуп выполняется в границах всей иерархии компании-корня
|
||||
(`company_id child_of root_id`), повторяя область действия штатного
|
||||
ограничения уникальности `account.tax._constrains_name`. Иначе на базах
|
||||
с филиалами (branch) создание ставки с тем же именем вызовет
|
||||
«Tax names must be unique!».
|
||||
"""
|
||||
Tax = self.env['account.tax']
|
||||
created = 0
|
||||
for name, use, atype, amount, incl in VAT_TAXES:
|
||||
exists = Tax.with_context(active_test=False).search([
|
||||
('company_id', 'child_of', company.root_id.id),
|
||||
('name', '=', name),
|
||||
('type_tax_use', '=', use),
|
||||
('country_id', '=', country.id if country else False),
|
||||
], limit=1)
|
||||
if exists:
|
||||
continue
|
||||
Tax.create({
|
||||
'name': name,
|
||||
'type_tax_use': use,
|
||||
'amount_type': atype,
|
||||
'amount': amount,
|
||||
'price_include_override': incl,
|
||||
'tax_group_id': group.id,
|
||||
'country_id': country.id if country else False,
|
||||
'company_id': company.id,
|
||||
})
|
||||
created += 1
|
||||
return created
|
||||
|
||||
@api.model
|
||||
def _rsbu_setup_vat_taxes(self):
|
||||
"""Создать налоговую группу НДС и 20 ставок НДС для каждой КОРНЕВОЙ компании.
|
||||
|
||||
Вызывается через <function> в data при установке И при каждом `-u`.
|
||||
|
||||
Ставки НДС создаются на уровне корневой компании (root_id). Филиалы
|
||||
(branch, parent_id задан) наследуют план счетов и налоги родителя — это
|
||||
штатное поведение бухгалтерии Odoo, и штатное ограничение уникальности
|
||||
`account.tax` запрещает дублировать ставки с тем же именем внутри одной
|
||||
иерархии компании. Поэтому мы перебираем только корневые компании
|
||||
(`parent_id = False`); филиалы получают доступ к ставкам родителя.
|
||||
|
||||
Идемпотентно: дедуп по (иерархия root, name, type_tax_use, country_id),
|
||||
поэтому повторный запуск / установка на новую компанию не создают дублей.
|
||||
"""
|
||||
country = self.env.ref('base.ru', raise_if_not_found=False)
|
||||
root_companies = self.env['res.company'].search([('parent_id', '=', False)])
|
||||
for company in root_companies:
|
||||
group = self._rsbu_ensure_tax_group(company, country)
|
||||
n = self._rsbu_ensure_vat_taxes(company, group, country)
|
||||
_logger.info(
|
||||
"rsbu_vat_templates: корневая компания %s — создано ставок НДС: %s",
|
||||
company.display_name, n)
|
||||
Reference in New Issue
Block a user