Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC

This commit is contained in:
CI Publish Bot
2026-11-01 22:54:30 +00:00
commit 26250aa580
2492 changed files with 664277 additions and 0 deletions

View File

@@ -0,0 +1,186 @@
from odoo import api, models
# Определения демо-шаблонов.
# Формат: code -> dict(name, resolver_key, usn_recognition, is_refund,
# roles={role: account_code})
TEMPLATES = {
# --- Инвойсы ---
'DEMO_SALE': {
'name': 'Продажа клиенту',
'resolver_key': 'shipment_upd',
'usn_recognition': 'none', # доход по УСН признаётся по оплате
'is_refund': False,
'roles': {
'receivable': '62.01',
'revenue': '90.01',
'revenue_vat': '90.03',
'vat_output': '68.НДС',
# роли для зачёта аванса и вычета авансового НДС при отгрузке
'advance_received': '62.АВ',
'vat_advance': '76.АВ',
},
},
'DEMO_SALE_REFUND': {
'name': 'Возврат от клиента (кредит-нота)',
'resolver_key': 'sale_credit_note',
'usn_recognition': 'none',
'is_refund': True,
'roles': {
'receivable': '62.01',
'revenue': '90.01',
'revenue_vat': '90.03',
'vat_output': '68.НДС',
},
},
'DEMO_PURCHASE': {
'name': 'Счёт поставщика',
'resolver_key': 'purchase_bill',
'usn_recognition': 'none', # расход по УСН признаётся по оплате
'is_refund': False,
'roles': {
'expense': '44',
'payable': '60',
},
},
'DEMO_PURCHASE_REFUND': {
'name': 'Возврат поставщику (кредит-нота)',
'resolver_key': 'purchase_credit_note',
'usn_recognition': 'none',
'is_refund': True,
'roles': {
'expense': '44',
'payable': '60',
},
},
# --- Платежи ---
'DEMO_PAY_CUSTOMER': {
'name': 'Оплата от клиента',
'resolver_key': 'customer_payment',
'usn_recognition': 'income',
'is_refund': False,
'roles': {
'bank': '51',
'receivable': '62.01',
'advance_received': '62.АВ',
'vat_advance': '76.АВ',
'vat_output': '68.НДС',
},
},
'DEMO_REFUND_CUSTOMER': {
'name': 'Возврат клиенту',
'resolver_key': 'advance_refund',
'usn_recognition': 'refund_customer',
'is_refund': True,
'roles': {
'bank': '51',
'advance_received': '62.АВ',
'vat_advance': '76.АВ',
'vat_output': '68.НДС',
},
},
'DEMO_PAY_SUPPLIER': {
'name': 'Оплата поставщику',
'resolver_key': 'supplier_payment',
'usn_recognition': 'expense',
'is_refund': False,
'roles': {
'bank': '51',
'payable': '60',
},
},
'DEMO_REFUND_SUPPLIER': {
'name': 'Возврат от поставщика',
'resolver_key': 'supplier_refund',
'usn_recognition': 'refund_supplier',
'is_refund': True,
'roles': {
'bank': '51',
'payable': '60',
},
},
}
# Правила матрицы: (name, doc_kind, partner_kind, has_advance, template_code, priority)
MATRIX = [
('Продажа клиенту', 'out_invoice', 'any', 'any', 'DEMO_SALE', 10),
('Возврат от клиента', 'out_refund', 'any', 'any', 'DEMO_SALE_REFUND', 10),
('Счёт поставщика', 'in_invoice', 'any', 'any', 'DEMO_PURCHASE', 10),
('Возврат поставщику', 'in_refund', 'any', 'any', 'DEMO_PURCHASE_REFUND', 10),
('Оплата от клиента', 'payment_inbound', 'customer', 'any',
'DEMO_PAY_CUSTOMER', 10),
('Возврат клиенту', 'payment_outbound', 'customer', 'any',
'DEMO_REFUND_CUSTOMER', 10),
('Оплата поставщику', 'payment_outbound', 'supplier', 'any',
'DEMO_PAY_SUPPLIER', 10),
('Возврат от поставщика', 'payment_inbound', 'supplier', 'any',
'DEMO_REFUND_SUPPLIER', 10),
]
class RsbuDemoTemplatesLoader(models.AbstractModel):
"""Загрузчик демо-шаблонов и матрицы связности по компаниям."""
_name = 'rsbu.demo.templates.loader'
_description = 'РСБУ — Загрузчик демо-шаблонов'
@api.model
def _account(self, company, code):
return self.env['rsbu.account'].search([
('company_id', '=', company.id),
('code', '=', code)], limit=1)
@api.model
def load_for_company(self, company):
Template = self.env['rsbu.operation.template']
Matrix = self.env['rsbu.operation.matrix']
code_to_tmpl = {}
for code, spec in TEMPLATES.items():
existing = Template.search([
('code', '=', code),
('company_id', '=', company.id)], limit=1)
if existing:
code_to_tmpl[code] = existing
continue
role_cmds = []
skip = False
for role, acc_code in spec['roles'].items():
account = self._account(company, acc_code)
if not account:
skip = True
break
role_cmds.append((0, 0, {
'role': role, 'account_id': account.id}))
if skip:
continue
tmpl = Template.create({
'code': code,
'name': spec['name'],
'resolver_key': spec['resolver_key'],
'usn_recognition': spec['usn_recognition'],
'is_refund': spec['is_refund'],
'company_id': company.id,
'role_ids': role_cmds,
})
code_to_tmpl[code] = tmpl
for name, doc_kind, partner_kind, has_advance, tmpl_code, prio \
in MATRIX:
tmpl = code_to_tmpl.get(tmpl_code)
if not tmpl:
continue
exists = Matrix.search([
('company_id', '=', company.id),
('doc_kind', '=', doc_kind),
('partner_kind', '=', partner_kind),
('template_id', '=', tmpl.id)], limit=1)
if exists:
continue
Matrix.create({
'name': name,
'doc_kind': doc_kind,
'partner_kind': partner_kind,
'has_advance': has_advance,
'template_id': tmpl.id,
'priority': prio,
'company_id': company.id,
})