summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Yelizariev <iel@odoo.com>2021-03-29 14:56:22 +0000
committerRaphael Collet <rco@odoo.com>2021-03-31 09:48:32 +0000
commitdf53e57c009cb2d35cc48d1335b727f3f5fddc73 (patch)
tree8264a9c137975ce1020ae9a67a9d196e0b73f9f2
parent4e5a355f7c2978a6f705e6ca36abdfc51636acfc (diff)
[FIX] core,account: avoid useless recomputations in res.config
User may use Settings menu just to click "Manage Users" buttons. Such simple navigation sends ``create`` request, which may trigger a chain of recomputations. To avoid that we redefine ``create`` method to check if a value is really changed. The previous explicit implementation lacks in v14 two fields at least: * from module `account` ``` qr_code = fields.Boolean(string='Display SEPA QR-code', related='company_id.qr_code', readonly=False) ``` * from module `enterprise/account_reports` ``` account_tax_fiscal_country_id = fields.Many2one(string="Fiscal Country", related="company_id.account_tax_fiscal_country_id", readonly=False) ``` Performance Tests ================= In this test we click "Manage users" and check stats for ``res.config.settings/create`` request. Demo database with eCommerce and Accounting app installed: ``` | | Number of queries | Query time, sec | Remaining time, sec | |--------+-------------------+-----------------+---------------------| | Before | 707 | 0.325 | 0.215 | | After | 382 | 0.283 | 0.174 | ``` The same, but with extra 1400 invoices: ``` | | Number of queries | Query time, sec | Remaining time, sec | |--------+-------------------+-----------------+---------------------| | Before | 715 | 0.459 | 0.349 | | After | 382 | 0.176 | 0.107 | ``` --- opw-2489335 closes odoo/odoo#68486 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
-rw-r--r--addons/account/models/res_config_settings.py12
-rw-r--r--odoo/addons/base/models/res_config.py32
2 files changed, 32 insertions, 12 deletions
diff --git a/addons/account/models/res_config_settings.py b/addons/account/models/res_config_settings.py
index 457c00481b3..18c1ceb012b 100644
--- a/addons/account/models/res_config_settings.py
+++ b/addons/account/models/res_config_settings.py
@@ -162,15 +162,3 @@ class ResConfigSettings(models.TransientModel):
'Modify your taxes first before disabling this setting.')
}
return res
-
- @api.model
- def create(self, values):
- # Optimisation purpose, saving a res_config even without changing any values will trigger the write of all
- # related values, including the currency_id field on res_company. This in turn will trigger the recomputation
- # of account_move_line related field company_currency_id which can be slow depending on the number of entries
- # in the database. Thus, if we do not explicitly change the currency_id, we should not write it on the company
- if ('company_id' in values and 'currency_id' in values):
- company = self.env['res.company'].browse(values.get('company_id'))
- if company.currency_id.id == values.get('currency_id'):
- values.pop('currency_id')
- return super(ResConfigSettings, self).create(values)
diff --git a/odoo/addons/base/models/res_config.py b/odoo/addons/base/models/res_config.py
index fd9ddec2693..1abaf76663e 100644
--- a/odoo/addons/base/models/res_config.py
+++ b/odoo/addons/base/models/res_config.py
@@ -749,3 +749,35 @@ class ResConfigSettings(models.TransientModel, ResConfigModuleInstallationMixin)
if (action_id):
return RedirectWarning(msg % values, action_id, _('Go to the configuration panel'))
return UserError(msg % values)
+
+ @api.model
+ def create(self, values):
+ # Optimisation: saving a res.config.settings even without changing any
+ # values will trigger the write of all related values. This in turn may
+ # trigger chain of further recomputation. To avoid it, delete values
+ # that were not changed.
+ for field in self._fields.values():
+ if not (field.name in values and field.related and not field.readonly):
+ continue
+ # we write on a related field like
+ # qr_code = fields.Boolean(related='company_id.qr_code', readonly=False)
+ fname0 = field.related[0]
+ if fname0 not in values:
+ continue
+
+ # determine the current value
+ field0 = self._fields[fname0]
+ old_value = field0.convert_to_record(
+ field0.convert_to_cache(values[fname0], self), self)
+ for fname in field.related[1:]:
+ old_value = next(iter(old_value), old_value)[fname]
+
+ # determine the new value
+ new_value = field.convert_to_record(
+ field.convert_to_cache(values[field.name], self), self)
+
+ # drop if the value is the same
+ if old_value == new_value:
+ values.pop(field.name)
+
+ return super(ResConfigSettings, self).create(values)