[FIX] sale: take taxes into account during invoices -> refund switch
Before this commit, the invoice creation flow of a sales order checked if the amount of the generated invoice was positive or negative - if it was negative, then the invoice would be converted to a refund instead. Unfortunately, this check was done before the move was actually created \- meaning that the only way to compute the total of the move was to multiply the quantities and unit prices of what was about to be included in the move - ignoring taxes altogether. Since taxes would then be applied during the move's creation, you could in fact have a refund that ended up being negative because some products would end up with different taxes. A simple (although weird) example would happen if you registered a down payment that was actually greater than the subtotal of your quote (but lower than the total with taxes included). Example: Create a quote for a 100$ product with 15% tax Register a downpayment of 105$ and validate that invoice Invoice the rest: => you end up with a refund of -10$, while you should have a 10$ invoice instead. Since the downpayment did not have taxes, the second invoice was computed as being negative (100$ for the product - 105$ to deduce the down payment), even though after the 15% tax gets applied on the product (but not on the downpayment), the invoice is actually positive. This commits moves the switch from invoice to refund to *after* the move actually gets created, ensuring taxes are taken into account. X-original-commit: eefe27b112e2ffd35a834f03a188625a5d6ea5f2
This commit is contained in:
@@ -635,31 +635,13 @@ class SaleOrder(models.Model):
|
||||
new_invoice_vals_list.append(ref_invoice_vals)
|
||||
invoice_vals_list = new_invoice_vals_list
|
||||
|
||||
# 3) Manage 'final' parameter: transform out_invoice to out_refund if negative.
|
||||
out_invoice_vals_list = []
|
||||
refund_invoice_vals_list = []
|
||||
# 3) Create invoices.
|
||||
moves = self.env['account.move'].with_context(default_type='out_invoice').create(invoice_vals_list)
|
||||
# 4) Some moves might actually be refunds: convert them if the total amount is negative
|
||||
# We do this after the moves have been created since we need taxes, etc. to know if the total
|
||||
# is actually negative or not
|
||||
if final:
|
||||
for invoice_vals in invoice_vals_list:
|
||||
if sum(l[2]['quantity'] * l[2]['price_unit'] for l in invoice_vals['invoice_line_ids']) < 0:
|
||||
for l in invoice_vals['invoice_line_ids']:
|
||||
l[2]['quantity'] = -l[2]['quantity']
|
||||
invoice_vals['type'] = 'out_refund'
|
||||
refund_invoice_vals_list.append(invoice_vals)
|
||||
else:
|
||||
out_invoice_vals_list.append(invoice_vals)
|
||||
else:
|
||||
out_invoice_vals_list = invoice_vals_list
|
||||
|
||||
if invoice_vals['type'] in self.env['account.move'].get_outbound_types():
|
||||
invoice_bank_id = self.partner_id.bank_ids[:1]
|
||||
else:
|
||||
invoice_bank_id = self.company_id.partner_id.bank_ids[:1]
|
||||
|
||||
invoice_vals['invoice_partner_bank_id'] = invoice_bank_id
|
||||
|
||||
# Create invoices.
|
||||
moves = self.env['account.move'].with_context(default_type='out_invoice').create(out_invoice_vals_list)
|
||||
moves += self.env['account.move'].with_context(default_type='out_refund').create(refund_invoice_vals_list)
|
||||
moves.filtered(lambda m: m.amount_total < 0).action_switch_invoice_into_refund_credit_note()
|
||||
for move in moves:
|
||||
move.message_post_with_view('mail.message_origin_link',
|
||||
values={'self': move, 'origin': move.line_ids.mapped('sale_line_ids.order_id')},
|
||||
|
||||
Reference in New Issue
Block a user