Files
public/l10n_ru_contract_account/models/account_move.py

127 lines
7.2 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, fields, models, exceptions, _
class AccountMove(models.Model):
_inherit = 'account.move'
mt_contract_id = fields.Many2one(
'partner.contract.customer', string=_('Номер договора'),
compute='_compute_mt_contract_id', store=True, readonly=False)
sf_number = fields.Char(string=_('Номер с/ф'))
osnovanie = fields.Char(string=_('Основание'))
sec_partner_id = fields.Many2one('res.partner', string=_('Контрагент'), store=True, compute='_compute_get_pid')
stamp = fields.Boolean(string=_('Печать и подпись'), related='mt_contract_id.stamp')
@api.depends('partner_id')
def _compute_get_pid(self):
for s in self:
s.sec_partner_id = s.partner_id.parent_id if s.partner_id.parent_id else s.partner_id
@api.depends('partner_id', 'company_id', 'move_type')
def _compute_mt_contract_id(self):
"""Подставить договор клиента по умолчанию.
Подстановка выполняется для документов продаж (счёт/возврат клиента):
берём действующий (signed) клиентский договор партнёра в рамках
компании. Для документов покупки договор не подставляется — профиль
«Основной договор» ориентирован на журнал продаж. Уже выбранный
вручную договор не перезаписываем.
"""
Contract = self.env['partner.contract.customer']
for move in self:
if move.mt_contract_id:
continue
if move.move_type not in ('out_invoice', 'out_refund'):
move.mt_contract_id = False
continue
if not move.partner_id:
move.mt_contract_id = False
continue
partner = move.partner_id.commercial_partner_id or move.partner_id
domain = [
('partner_id', '=', partner.id),
('type', '=', 'customer'),
('is_template', '=', False),
]
if move.company_id:
domain.append(('company_id', '=', move.company_id.id))
contract = Contract.search(
domain + [('state', '=', 'signed')],
order='date_start desc', limit=1,
) or Contract.search(domain, order='date_start desc', limit=1)
move.mt_contract_id = contract.id if contract else False
@api.onchange('mt_contract_id')
def set_ons(self):
"""Синхронизировать поля инвойса с параметрами договора (в UI).
Заполняем основание, журнал и условие оплаты из профиля договора,
чтобы пользователь сразу видел согласованные значения.
"""
for s in self:
if s.mt_contract_id:
s._apply_contract_fields()
def _apply_contract_fields(self):
"""Привести журнал/условие оплаты/основание в соответствие договору.
Вызывается и в onchange (UI), и перед проведением (_post) — чтобы
согласованность не зависела от способа создания инвойса
(вручную, из заказа продаж или программно из демо-данных).
"""
for s in self:
contract = s.mt_contract_id
if not contract:
continue
s.osnovanie = 'Договор № ' + (contract.name or '') + ' от ' + fields.Datetime.from_string(
contract.date_start).strftime("%d.%m.%Y")
profile = contract.profile_id
# Журнал/условие оплаты из профиля договора применяем только к
# документам продаж; для покупок (in_invoice/in_refund) журнал
# определяется типом документа, профиль клиентского договора его
# не переопределяет.
if s.move_type in ('out_invoice', 'out_refund'):
if profile.journal_id and s.journal_id != profile.journal_id:
s.journal_id = profile.journal_id
if profile.payment_term_id and \
s.invoice_payment_term_id != profile.payment_term_id:
s.invoice_payment_term_id = profile.payment_term_id
def _post(self, soft=True):
# Синхронизировать поля с договором до валидации invoice_fields_check.
for move in self:
if move.mt_contract_id and move.state == 'draft':
move._apply_contract_fields()
return super()._post(soft=soft)
@api.constrains('state')
def invoice_fields_check(self):
for s in self:
if s.state == 'posted':
# Сверку с параметрами договора выполняем только для продаж;
# покупки не обязаны совпадать с профилем клиентского договора.
if s.mt_contract_id and s.move_type in (
'out_invoice', 'out_refund'):
errors_list = []
journal_in_contract = s.mt_contract_id.profile_id.journal_id
payment_term_in_contract = s.mt_contract_id.profile_id.payment_term_id
receivable_in_contract = s.mt_contract_id.profile_id.receivable_account_id
if journal_in_contract != s.journal_id:
errors_list.append(f'Отличается Журнал - [{s.journal_id.name}] '
f'и указанный в договоре №{s.mt_contract_id.name} '
f'Журнал - [{journal_in_contract.name}]\n\n')
if payment_term_in_contract != s.invoice_payment_term_id:
errors_list.append(f'Отличается поле "Условие оплаты" в инвойсе '
f'[Условие оплаты - {s.invoice_payment_term_id.name}] '
f'и указанный в договоре №{s.mt_contract_id.name} '
f'[Условие оплаты - {payment_term_in_contract.name}]\n\n')
if receivable_in_contract not in s.line_ids.account_id:
errors_list.append(f'Отличается поле "Счет дебиторской задолженности" в инвойсе '
f'и указанный в договоре №{s.mt_contract_id.name}')
if errors_list:
raise exceptions.ValidationError(''.join(errors_list))