[FIX] account, sale: create invoice lines in batch
This patch changes the create of `account.invoice.line` to use
`model_create_multi`, which allows the batch creation of multiple
invoice lines while only triggering the recompute of all related fields
once.
It also changes the generation of invoices from a SO to take advantage
of the create multi of `account.invoice.line`.
For a SO of 2000 lines:
Pre-patch:
~417s to generate an Invoice
Post-patch:
~30s to generate an Invoice
closes odoo/odoo#31975
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This commit is contained in:
@@ -1865,12 +1865,12 @@ class AccountInvoiceLine(models.Model):
|
||||
}
|
||||
return data
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('display_type', self.default_get(['display_type'])['display_type']):
|
||||
vals.update(price_unit=0, account_id=False, quantity=0)
|
||||
|
||||
return super(AccountInvoiceLine, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('display_type', self.default_get(['display_type'])['display_type']):
|
||||
vals.update(price_unit=0, account_id=False, quantity=0)
|
||||
return super(AccountInvoiceLine, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
|
||||
@@ -522,6 +522,8 @@ class SaleOrder(models.Model):
|
||||
# We only want to create sections that have at least one invoiceable line
|
||||
pending_section = None
|
||||
|
||||
# Create lines in batch to avoid performance problems
|
||||
line_vals_list = []
|
||||
for line in order.order_line:
|
||||
if line.display_type == 'line_section':
|
||||
pending_section = line
|
||||
@@ -543,14 +545,21 @@ class SaleOrder(models.Model):
|
||||
|
||||
if line.qty_to_invoice > 0 or (line.qty_to_invoice < 0 and final):
|
||||
if pending_section:
|
||||
pending_section.invoice_line_create(invoices[group_key].id, pending_section.qty_to_invoice)
|
||||
line_vals_list.extend(pending_section.invoice_line_create_vals(
|
||||
invoices[group_key].id,
|
||||
pending_section.qty_to_invoice
|
||||
))
|
||||
pending_section = None
|
||||
line.invoice_line_create(invoices[group_key].id, line.qty_to_invoice)
|
||||
line_vals_list.extend(line.invoice_line_create_vals(
|
||||
invoices[group_key].id, line.qty_to_invoice
|
||||
))
|
||||
|
||||
if references.get(invoices.get(group_key)):
|
||||
if order not in references[invoices[group_key]]:
|
||||
references[invoices[group_key]] |= order
|
||||
|
||||
self.env['account.invoice.line'].create(line_vals_list)
|
||||
|
||||
for group_key in invoices:
|
||||
invoices[group_key].write({'name': ', '.join(invoices_name[group_key]),
|
||||
'origin': ', '.join(invoices_origin[group_key])})
|
||||
@@ -1363,18 +1372,34 @@ class SaleOrderLine(models.Model):
|
||||
@api.multi
|
||||
def invoice_line_create(self, invoice_id, qty):
|
||||
""" Create an invoice line. The quantity to invoice can be positive (invoice) or negative (refund).
|
||||
|
||||
.. deprecated:: 12.0
|
||||
Replaced by :func:`invoice_line_create_vals` which can be used for creating
|
||||
`account.invoice.line` records in batch
|
||||
|
||||
:param invoice_id: integer
|
||||
:param qty: float quantity to invoice
|
||||
:returns recordset of account.invoice.line created
|
||||
"""
|
||||
invoice_lines = self.env['account.invoice.line']
|
||||
return self.env['account.invoice.line'].create(
|
||||
self.invoice_line_create_vals(invoice_id, qty))
|
||||
|
||||
def invoice_line_create_vals(self, invoice_id, qty):
|
||||
""" Create an invoice line. The quantity to invoice can be positive (invoice) or negative
|
||||
(refund).
|
||||
|
||||
:param invoice_id: integer
|
||||
:param qty: float quantity to invoice
|
||||
:returns list of dict containing creation values for account.invoice.line records
|
||||
"""
|
||||
vals_list = []
|
||||
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
||||
for line in self:
|
||||
if not float_is_zero(qty, precision_digits=precision) or not line.product_id:
|
||||
vals = line._prepare_invoice_line(qty=qty)
|
||||
vals.update({'invoice_id': invoice_id, 'sale_line_ids': [(6, 0, [line.id])]})
|
||||
invoice_lines |= self.env['account.invoice.line'].create(vals)
|
||||
return invoice_lines
|
||||
vals_list.append(vals)
|
||||
return vals_list
|
||||
|
||||
@api.multi
|
||||
def _prepare_procurement_values(self, group_id=False):
|
||||
|
||||
Reference in New Issue
Block a user