196 lines
9.1 KiB
Python
196 lines
9.1 KiB
Python
from odoo import models, fields, api
|
||
|
||
class OrderPrepaid(models.Model):
|
||
_name = 'order.prepaid'
|
||
_description = 'Авансовые платежи'
|
||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||
|
||
name = fields.Char(string='Название', default='Draft', copy=False)
|
||
partner_id = fields.Many2one(comodel_name='res.partner', string='Контрагент')
|
||
invoice_partner_display_name = fields.Char(compute='_compute_invoice_partner_display_info', store=True)
|
||
|
||
payment_terms = fields.Char(string='Условия оплаты')
|
||
invoice_date = fields.Date(string='Дата счета', default=fields.Date.context_today, required=True)
|
||
invoice_date_due = fields.Date(string='Срок оплаты', default=fields.Date.context_today, required=True)
|
||
company_id = fields.Many2one(comodel_name='res.company', string='Компания')
|
||
sale_order_id = fields.Many2one(comodel_name='sale.order', string='Заказ продаж')
|
||
advance_type = fields.Selection(selection=[('outbound', 'Исходящий'),('inbound', 'Входящий')],
|
||
string='Тип платежа', default='inbound')
|
||
comment = fields.Text(string='Комментарий')
|
||
state = fields.Selection(selection=[('cancel', 'Отменено'),
|
||
('draft', 'Черновик'),
|
||
('posted', 'Проведено')],
|
||
string='Статус', default='draft')
|
||
prepaid_line = fields.One2many(comodel_name='order.prepaid.line', inverse_name='prepaid_id', string='Строки счета')
|
||
|
||
currency_id = fields.Many2one(comodel_name='res.currency', string='Валюта', tracking=True, required=True, readonly=False,
|
||
compute='_compute_currency_id', inverse='_inverse_currency_id',
|
||
store=True, precompute=True)
|
||
partner_bank_id = fields.Many2one(comodel_name='res.partner.bank', string="Банковский счёт получателя")
|
||
amount = fields.Monetary(currency_field='currency_id', store=True, readonly=False,
|
||
compute='_compute_amount', string='Всего')
|
||
|
||
payment_line_ids = fields.One2many(comodel_name='account.payment', inverse_name='prepaid_id',
|
||
string='Связанные платежи', compute_sudo=True, store=True)
|
||
company_partner_id = fields.Many2one(string='Контакт компании', related='company_id.partner_id')
|
||
|
||
payment_state = fields.Selection(selection=[('not_paid', 'Не оплачен'),
|
||
('in_payment', 'В оплате'),
|
||
('paid', 'Оплачено'),
|
||
('partial', 'Частично оплачено'),
|
||
],
|
||
string="Статус платежа", readonly=True, copy=False, tracking=True,
|
||
compute='_compute_payment_state', store=True)
|
||
payment_id = fields.Many2one(comodel_name='account.payment', string='Платеж')
|
||
payment_amount = fields.Monetary(currency_field='currency_id', compute='_compute_payment_amount', store=True, string='Выплачено')
|
||
amount_sum_line = fields.Monetary(currency_field='currency_id', store=True, readonly=False,
|
||
compute='_compute_amount_sum_line', string='Сумма')
|
||
|
||
amount_residual = fields.Monetary(currency_field='currency_id', store=True, readonly=False,
|
||
compute='_compute_amount_residual', string='Остаток долга', default=0, copy=False)
|
||
|
||
all_total = fields.Monetary(currency_field='currency_id', store=True, readonly=True,
|
||
compute='_compute_all_total', string='Всего', default=0, copy=False)
|
||
|
||
th_field_taxes = fields.Boolean(string='Проверка столбца налогов', compute='_th_field_taxes', store=True)
|
||
|
||
@api.depends('prepaid_line.tax_ids')
|
||
def _th_field_taxes(self):
|
||
for rec in self:
|
||
values = rec.prepaid_line.mapped('tax_ids')
|
||
if values:
|
||
rec.th_field_taxes = True
|
||
else:
|
||
rec.th_field_taxes = False
|
||
|
||
@api.depends('amount')
|
||
def _compute_all_total(self):
|
||
for rec in self:
|
||
if rec.amount > 0:
|
||
rec.all_total = -(rec.amount) if rec.advance_type == 'outbound' else rec.amount
|
||
else:
|
||
rec.all_total = 0
|
||
|
||
@api.depends('partner_id', 'partner_id.display_name')
|
||
def _compute_invoice_partner_display_info(self):
|
||
for record in self:
|
||
vendor_display_name = record.partner_id.display_name if record.partner_id else ''
|
||
record.invoice_partner_display_name = vendor_display_name
|
||
|
||
@api.depends('amount', 'payment_amount', 'state')
|
||
def _compute_amount_residual(self):
|
||
for rec in self:
|
||
if rec.state == 'posted':
|
||
rec.amount_residual = rec.amount - abs(rec.payment_amount)
|
||
else:
|
||
rec.amount_residual = 0
|
||
|
||
@api.depends('prepaid_line', 'prepaid_line.tax_ids')
|
||
def _compute_amount_sum_line(self):
|
||
for rec in self:
|
||
amount = 0
|
||
for el in rec.prepaid_line:
|
||
amount += el.price_subtotal
|
||
rec.amount_sum_line = amount
|
||
|
||
|
||
@api.depends('payment_amount', 'payment_line_ids.reconciled_statement_line_ids')
|
||
def _compute_payment_state(self):
|
||
if not self.payment_line_ids:
|
||
self.payment_state = 'not_paid'
|
||
elif abs(self.payment_amount) != 0:
|
||
if abs(self.payment_amount) >= self.amount:
|
||
bool = True
|
||
for rec in self.payment_line_ids:
|
||
if not rec.reconciled_statement_line_ids:
|
||
bool = False
|
||
break
|
||
self.payment_state = 'paid' if bool else 'in_payment'
|
||
else:
|
||
self.payment_state = 'partial'
|
||
else:
|
||
self.payment_state = 'not_paid'
|
||
|
||
@api.depends('payment_line_ids', 'payment_line_ids.state')
|
||
def _compute_payment_amount(self):
|
||
for rec in self:
|
||
payments = self.env['account.payment'].with_company(rec.company_id)
|
||
records = payments.search([('state', '=', 'posted'),
|
||
('prepaid_id', '=', rec.id),
|
||
('company_id', '=', rec.company_id.id)])
|
||
amount = sum(records.mapped('amount_adv_currency'))
|
||
rec.payment_amount = amount
|
||
|
||
|
||
@api.depends('prepaid_line')
|
||
def _compute_amount(self):
|
||
for rec in self:
|
||
amount = 0
|
||
for el in rec.prepaid_line:
|
||
amount += el.price_unit * el.quantity
|
||
rec.amount = amount
|
||
|
||
@api.depends('company_id')
|
||
def _compute_currency_id(self):
|
||
for invoice in self:
|
||
invoice.currency_id = invoice.company_id.currency_id
|
||
|
||
@api.onchange('currency_id')
|
||
def _inverse_currency_id(self):
|
||
self.currency_id = self.currency_id
|
||
|
||
|
||
def action_post(self):
|
||
if self.name == 'Draft':
|
||
self.name = self.env['ir.sequence'].next_by_code('order.prepaid')
|
||
self.state = 'posted'
|
||
|
||
def button_draft(self):
|
||
self.state = 'draft'
|
||
payments = self.env['account.payment'].with_company(self.company_id)
|
||
records = payments.search([('prepaid_id', '=', self.id), ('company_id', '=', self.company_id.id)])
|
||
if records:
|
||
for el in records:
|
||
el.action_draft()
|
||
el.action_cancel()
|
||
el.unlink()
|
||
|
||
|
||
def button_cancel(self):
|
||
self.state = 'cancel'
|
||
|
||
|
||
def action_register_payment(self):
|
||
journals = self.env['account.journal'].with_company(self.company_id.id)
|
||
journal = journals.search([('type', 'in', ['bank', 'cash']), ('company_id', '=', self.company_id.id)])
|
||
if journal:
|
||
if self.partner_bank_id:
|
||
journal_bank = journal.search([('bank_account_id', '=', self.partner_bank_id.id)], limit=1)
|
||
journal_id = journal_bank.id if journal_bank else journal[0].id
|
||
else:
|
||
journal_id = journal[0].id
|
||
else:
|
||
journal_id = False
|
||
|
||
delta_amount = self.amount - abs(self.payment_amount)
|
||
default_amount = delta_amount if delta_amount > 0 else 0
|
||
|
||
return {
|
||
'name': 'Регистрация платежа',
|
||
'res_model': 'payment.register.prepaid',
|
||
'view_mode': 'form',
|
||
'views': [[False, 'form']],
|
||
'context': {
|
||
'default_prepaid_id': self.id,
|
||
'default_company_id': self.company_id.id,
|
||
'default_communication': self.name,
|
||
'default_amount': default_amount,
|
||
'default_amount_const': default_amount,
|
||
'default_journal_id': journal_id
|
||
},
|
||
'target': 'new',
|
||
'type': 'ir.actions.act_window',
|
||
}
|
||
|
||
|