from odoo import api, fields, models from json import loads as json_loads class SaleOrder(models.Model): _inherit = 'sale.order' amount_total_deposit = fields.Monetary(string='Deposit', compute='_amount_total_deposit') @api.depends('amount_total', 'payment_term_id.deposit_percentage', 'payment_term_id.deposit_flat') def _amount_total_deposit(self): for order in self: percent_deposit = order.amount_total * float(order.payment_term_id.deposit_percentage) / 100.0 flat_deposite = float(order.payment_term_id.deposit_flat) order.amount_total_deposit = percent_deposit + flat_deposite def action_confirm(self): res = super(SaleOrder, self).action_confirm() self._auto_deposit_invoice() return res def _auto_deposit_invoice(self): wizard_model = self.env['sale.advance.payment.inv'].sudo() for sale in self.sudo().filtered(lambda o: not o.invoice_ids and o.amount_total_deposit): # Create Deposit Invoices wizard = wizard_model.create({ 'advance_payment_method': 'fixed', 'amount': sale.amount_total_deposit, }) wizard.with_context(active_ids=sale.ids).create_invoices() # Validate Invoices sale.invoice_ids.filtered(lambda i: i.state == 'draft').action_invoice_open() # Attempt to reconcile sale._auto_deposit_payment_match() def _auto_deposit_payment_match(self): # Attempt to find payments that could be used on this new invoice and reconcile them. # Note that this probably doesn't work for a payment made on the front, see .account.PaymentTransaction aml_model = self.env['account.move.line'].sudo() for sale in self.sudo(): for invoice in sale.invoice_ids.filtered(lambda i: i.state == 'open'): outstanding = json_loads(invoice.outstanding_credits_debits_widget) if isinstance(outstanding, dict) and outstanding.get('content'): for line in outstanding.get('content'): if abs(line.get('amount', 0.0) - invoice.residual) < 0.01 and line.get('id'): aml = aml_model.browse(line.get('id')) aml += invoice.move_id.line_ids.filtered(lambda l: l.account_id == aml.account_id) if aml.reconcile(): break