summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Martinelli <nim@odoo.com>2019-01-25 12:16:01 +0000
committerNicolas Martinelli <nim@odoo.com>2019-01-28 12:51:50 +0000
commitc8ac1b40f258a2de72437ada292ec7256db36c3f (patch)
tree89176898bb6f0b253faa503987d168c580282ff5
parente7bbdf884fa113bda1c7dd9d16ac17ac6429a013 (diff)
[FIX] account: dashboard performance
When thousands of invoices are in a different currency than their corresponding journals, a large number of calls are performed to `_get_conversion_rate`, and therefore `_select_companies_rates`. Despite the fact that the query itself is optimized, the impact of performances on the dashboard loading time is not negligible. In order to avoid unnecessary queries, we create a cache dictionary to store the rate values. This way, we avoid any unnecessary query. opw-1920188 closes odoo/odoo#30552
-rw-r--r--addons/account/models/account_journal_dashboard.py25
1 files changed, 19 insertions, 6 deletions
diff --git a/addons/account/models/account_journal_dashboard.py b/addons/account/models/account_journal_dashboard.py
index c24b1be061d..ee8087a33b0 100644
--- a/addons/account/models/account_journal_dashboard.py
+++ b/addons/account/models/account_journal_dashboard.py
@@ -189,9 +189,10 @@ class account_journal(models.Model):
query = """SELECT residual_signed as amount_total, currency_id AS currency, type, date_invoice, company_id FROM account_invoice WHERE journal_id = %s AND date <= %s AND state = 'open';"""
self.env.cr.execute(query, (self.id, today))
late_query_results = self.env.cr.dictfetchall()
- (number_waiting, sum_waiting) = self._count_results_and_sum_amounts(query_results_to_pay, currency)
- (number_draft, sum_draft) = self._count_results_and_sum_amounts(query_results_drafts, currency)
- (number_late, sum_late) = self._count_results_and_sum_amounts(late_query_results, currency)
+ curr_cache = {}
+ (number_waiting, sum_waiting) = self._count_results_and_sum_amounts(query_results_to_pay, currency, curr_cache=curr_cache)
+ (number_draft, sum_draft) = self._count_results_and_sum_amounts(query_results_drafts, currency, curr_cache=curr_cache)
+ (number_late, sum_late) = self._count_results_and_sum_amounts(late_query_results, currency, curr_cache=curr_cache)
difference = currency.round(last_balance-account_sum) + 0.0
return {
@@ -239,20 +240,32 @@ class account_journal(models.Model):
FROM account_invoice inv
WHERE journal_id = %(journal_id)s AND state = 'draft';""", {'journal_id':self.id})
- def _count_results_and_sum_amounts(self, results_dict, target_currency):
+ def _count_results_and_sum_amounts(self, results_dict, target_currency, curr_cache=None):
""" Loops on a query result to count the total number of invoices and sum
their amount_total field (expressed in the given target currency).
amount_total must be signed !
"""
rslt_count = 0
rslt_sum = 0.0
+ # Create a cache with currency rates to avoid unnecessary SQL requests. Do not copy
+ # curr_cache on purpose, so the dictionary is modified and can be re-used for subsequent
+ # calls of the method.
+ curr_cache = {} if curr_cache is None else curr_cache
for result in results_dict:
cur = self.env['res.currency'].browse(result.get('currency'))
company = self.env['res.company'].browse(result.get('company_id')) or self.env.user.company_id
rslt_count += 1
+ date = result.get('date_invoice') or fields.Date.today()
+
amount = result.get('amount_total', 0)
- rslt_sum += cur._convert(
- amount, target_currency, company, result.get('date_invoice') or fields.Date.today())
+ if cur != target_currency:
+ key = (cur, target_currency, company, date)
+ # Using setdefault will call _get_conversion_rate, so we explicitly check the
+ # existence of the key in the cache instead.
+ if key not in curr_cache:
+ curr_cache[key] = self.env['res.currency']._get_conversion_rate(*key)
+ amount *= curr_cache[key]
+ rslt_sum += target_currency.round(amount)
return (rslt_count, rslt_sum)
@api.multi