Skip to content

Commit a71866f

Browse files
committed
[PERF] account: improve account merge
Issue --> The final step of the `_action_merge` method updates the `code` field of the account onto which the other accounts are merged. During the write call on `code`, a dependent field `always_tax_exigible` on `account.move` gets added to the compute chain. This causes a fetch of all `account.move` records related to journal items related to the account that is getting updated. This can lead to a MemoryError on databases with large `account.move` tables. Solution --> We delegate the write of the `code` field to SQL. In the account merge wizard, accounts that can be grouped are grouped by the keys --> `'account_type', 'non_trade', 'currency_id', 'reconcile', 'deprecated','name'`. Therefore, the `account_type` does not change after the merge. We can safely assume that any fields dependent on `account_type` do not need recomputation and hence, bypass the ORM for this update. Additional change --> Disable the prefetcher in the write call in `account.account` to optimize memory usage on databases with a large number of journal items/journal entries when writing on `code` or `account_type` in general. opw-4839985 closes odoo#218349 X-original-commit: 8c5bfff Signed-off-by: Thomas Becquevort (thbe) <[email protected]>
1 parent 326531a commit a71866f

File tree

2 files changed

+13
-5
lines changed

2 files changed

+13
-5
lines changed

addons/account/models/account_account.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,7 @@ def write(self, vals):
10851085
if vals.get('deprecated') and self.env["account.tax.repartition.line"].search_count([('account_id', 'in', self.ids)], limit=1):
10861086
raise UserError(_("You cannot deprecate an account that is used in a tax distribution."))
10871087

1088-
res = super(AccountAccount, self.with_context(defer_account_code_checks=True)).write(vals)
1088+
res = super(AccountAccount, self.with_context(defer_account_code_checks=True, prefetch_fields=any(field in vals for field in ['code', 'account_type']))).write(vals)
10891089

10901090
if not self.env.context.get('defer_account_code_checks') and {'company_ids', 'code', 'code_mapping_ids'} & vals.keys():
10911091
self._ensure_code_is_unique()

addons/account/wizard/account_merge_wizard.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,10 @@ def _action_merge(self, accounts):
145145
all_root_companies = self.env['res.company'].sudo().search([('parent_id', '=', False)])
146146
for account in accounts:
147147
for company in account.company_ids & all_root_companies:
148-
code_by_company[company] = account.with_company(company).sudo().code
148+
code_by_company[company.id] = account.with_company(company).sudo().code
149149
for company in all_root_companies - account.company_ids:
150150
if code := account.with_company(company).sudo().code:
151-
code_by_company[company] = code
151+
code_by_company[company.id] = code
152152

153153
account_to_merge_into = accounts[0]
154154
accounts_to_remove = accounts[1:]
@@ -205,10 +205,18 @@ def _action_merge(self, accounts):
205205
self.env.registry.clear_cache()
206206

207207
# Step 5: Write company_ids and codes on the account
208-
for company, code in code_by_company.items():
209-
account_to_merge_into.with_company(company).sudo().code = code
208+
self.env.cr.execute(SQL(
209+
"""
210+
UPDATE account_account
211+
SET code_store = %(code_by_company_json)s
212+
WHERE id = %(account_to_merge_into_id)s
213+
""",
214+
code_by_company_json=json.dumps(code_by_company),
215+
account_to_merge_into_id=account_to_merge_into.id,
216+
))
210217

211218
account_to_merge_into.sudo().company_ids = company_ids_to_write
219+
self.env.add_to_compute(self.env['account.account']._fields['tag_ids'], account_to_merge_into)
212220

213221

214222
class AccountMergeWizardLine(models.TransientModel):

0 commit comments

Comments
 (0)