Browse Source

Merge pull request #266 from Tecnativa/10-contract-optimize

[10.0][IMP] contract: Performance boost 🚀
pull/277/head
Pedro M. Baeza 6 years ago
committed by GitHub
parent
commit
fcf510fae3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      contract/README.rst
  2. 42
      contract/models/account_analytic_account.py

19
contract/README.rst

@ -16,6 +16,25 @@ Configuration
To view discount field set *Discount on lines* in user access rights.
You might find that generating all pending invoices at once takes too much
time and produces some performance problems, mostly in cases where you
generate a lot of invoices in little time (i.e. when invoicing thousands
of contracts yearly, and you get to January 1st of the next year). To avoid
this bottleneck, the trick is to **increase the cron frequence and decrease
the contracts batch size**. The counterpart is that some invoices could not
be generated in the exact day you expected. To configure that:
#. Go to *Settings > Activate the developer mode*.
#. Go to *Settings > Technical > Automation > Scheduled Actions >
Generate Recurring Invoices from Contracts > Edit > Information*.
#. Set a lower interval. For example, change *Interval Unit* to *Hours*.
#. Go to the *Technical Data* tab, and add a batch size in *Arguments*.
For example, it should look like ``(20,)``.
#. Save.
That's it! From now on, only 20 invoices per hour will be generated.
That should take only a few seconds each hour, and shouln't block other users.
Usage
=====

42
contract/models/account_analytic_account.py

@ -255,12 +255,16 @@ class AccountAnalyticAccount(models.Model):
@api.multi
def _create_invoice(self):
self.ensure_one()
invoice_vals = self._prepare_invoice()
invoice = self.env['account.invoice'].create(invoice_vals)
# Re-read contract with correct company
_self = self.with_context(self.get_invoice_context())
invoice_vals = _self._prepare_invoice()
invoice = _self.env['account.invoice'].create(invoice_vals)
# Lines are read from an env where expensive values are precomputed
for line in self.recurring_invoice_line_ids:
invoice_line_vals = self._prepare_invoice_line(line, invoice.id)
self.env['account.invoice.line'].create(invoice_line_vals)
invoice.compute_taxes()
invoice_line_vals = _self._prepare_invoice_line(line, invoice.id)
_self.env['account.invoice.line'].create(invoice_line_vals)
# Update next invoice date for current contract
_self.recurring_next_date = _self.env.context['next_date']
return invoice
@api.multi
@ -287,6 +291,7 @@ class AccountAnalyticAccount(models.Model):
relativedelta(days=1))
date_to = date_start
ctx.update({
'mail_notrack': True,
'next_date': next_date,
'date_format': date_format,
'date_from': date_from,
@ -317,18 +322,21 @@ class AccountAnalyticAccount(models.Model):
:return: invoices created
"""
invoices = self.env['account.invoice']
for contract in self:
if limit and len(invoices) >= limit:
break
if not contract.check_dates_valid():
continue
# Re-read contract with correct company
ctx = contract.get_invoice_context()
invoices |= contract.with_context(ctx)._create_invoice()
contract.write({
'recurring_next_date': fields.Date.to_string(ctx['next_date'])
})
_self = self.with_context(prefetch_fields=False)
invoices = _self.env['account.invoice']
# Precompute expensive computed fields in batch
recurring_lines = _self.mapped("recurring_invoice_line_ids")
recurring_lines._fields["price_unit"].determine_value(recurring_lines)
# Create invoices
with _self.env.norecompute():
for contract in _self:
if limit and len(invoices) >= limit:
break
if not contract.check_dates_valid():
continue
invoices |= contract._create_invoice()
invoices.compute_taxes()
_self.recompute()
return invoices
@api.model

Loading…
Cancel
Save