Skip to content
Permalink
Browse files

[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
  • Loading branch information...
Elkasitu committed Mar 20, 2019
1 parent 2942387 commit a881ab6d3c2147edfaba977880d6cfe43a176ec1
Showing with 36 additions and 11 deletions.
  1. +6 −6 addons/account/models/account_invoice.py
  2. +30 −5 addons/sale/models/sale.py
@@ -1857,12 +1857,12 @@ def _prepare_invoice_line(self):
}
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 @@ def action_invoice_create(self, grouped=False, final=False):
# 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 @@ def action_invoice_create(self, grouped=False, final=False):

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 @@ def _prepare_invoice_line(self, qty):
@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):

0 comments on commit a881ab6

Please sign in to comment.
You can’t perform that action at this time.