[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#68620
X-original-commit: 5e3f37191a4687b305e2337780c7f10278f6a7aa
Signed-off-by: Ivan Yelizariev // IEL <yelizariev@users.noreply.github.com>
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This commit is contained in:
@@ -193,15 +193,3 @@ class ResConfigSettings(models.TransientModel):
|
||||
# We display the preview button only if the terms_type is html in the setting but also on the company
|
||||
# to avoid landing on an error page (see terms.py controller)
|
||||
setting.preview_ready = self.env.company.terms_type == 'html' and setting.terms_type == 'html'
|
||||
|
||||
@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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user