Files
public/rsbu_demo_templates/models/rsbu_demo_templates_loader.py

187 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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,
})