diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index 606809690c2..9ca3bf8a20a 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -721,9 +721,37 @@ Reason(s) of this behavior could be: invoice_vals_list = new_invoice_vals_list # 3) Create invoices. + + # As part of the invoice creation, we make sure the sequence of multiple SO do not interfere + # in a single invoice. Example: + # SO 1: + # - Section A (sequence: 10) + # - Product A (sequence: 11) + # SO 2: + # - Section B (sequence: 10) + # - Product B (sequence: 11) + # + # If SO 1 & 2 are grouped in the same invoice, the result will be: + # - Section A (sequence: 10) + # - Section B (sequence: 10) + # - Product A (sequence: 11) + # - Product B (sequence: 11) + # + # Resequencing should be safe, however we resequence only if there are less invoices than + # orders, meaning a grouping might have been done. This could also mean that only a part + # of the selected SO are invoiceable, but resequencing in this case shouldn't be an issue. + if len(invoice_vals_list) < len(self): + SaleOrderLine = self.env['sale.order.line'] + for invoice in invoice_vals_list: + sequence = 1 + for line in invoice['invoice_line_ids']: + line[2]['sequence'] = SaleOrderLine._get_invoice_line_sequence(new=sequence, old=line[2]['sequence']) + sequence += 1 + # Manage the creation of invoices in sudo because a salesperson must be able to generate an invoice from a # sale order without "billing" access rights. However, he should not be able to create an invoice from scratch. moves = self.env['account.move'].sudo().with_context(default_move_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 @@ -1536,6 +1564,18 @@ class SaleOrderLine(models.Model): line.untaxed_amount_to_invoice = amount_to_invoice + def _get_invoice_line_sequence(self, new=0, old=0): + """ + Method intended to be overridden in third-party module if we want to prevent the resequencing + of invoice lines. + + :param int new: the new line sequence + :param int old: the old line sequence + + :return: the sequence of the SO line, by default the new one. + """ + return new or old + def _prepare_invoice_line(self, **optional_values): """ Prepare the dict of values to create the new invoice line for a sales order line.