From a38a5b77fbb23a199a97689628e03365ac608b74 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 13 Oct 2023 16:27:38 +0200 Subject: [PATCH] [FIX] account: make _constrains_code() scale better The code was failing because the domain it generates is too large, which makes the SQL "compilation" reach the recursion limit. closes odoo/odoo#138019 Related: odoo/enterprise#48916 Signed-off-by: Raphael Collet --- addons/account/models/account_account.py | 31 +++++++++++++++--------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/addons/account/models/account_account.py b/addons/account/models/account_account.py index a34158c43ef..1bbf1fac25b 100644 --- a/addons/account/models/account_account.py +++ b/addons/account/models/account_account.py @@ -119,18 +119,25 @@ class AccountAccount(models.Model): @api.constrains('company_id', 'code') def _constrains_code(self): - domains = [] - for record in self: - domains.append([ - ('company_id', 'child_of', record.company_id.root_id.id), - ('code', '=', record.code), - ('id', '!=', record.id), - ]) - if duplicates := self.search(expression.OR(domains)): - raise ValidationError( - _("The code of the account must be unique per company!") - + "\n" + "\n".join(f"- {duplicate.code} in {duplicate.company_id.name}" for duplicate in duplicates) - ) + # check for duplicates in each root company + by_root_company = self.grouped(lambda record: record.company_id.root_id) + for root_company, records in by_root_company.items(): + by_code = records.grouped('code') + if len(by_code) < len(records): + # retrieve duplicates within self + duplicates = next(recs for recs in by_code.values() if len(recs) > 1) + else: + # search for duplicates of self in database + duplicates = self.search([ + ('company_id', 'child_of', root_company.id), + ('code', 'in', list(by_code)), + ('id', 'not in', records.ids), + ]) + if duplicates: + raise ValidationError( + _("The code of the account must be unique per company!") + + "\n" + "\n".join(f"- {duplicate.code} in {duplicate.company_id.name}" for duplicate in duplicates) + ) @api.constrains('reconcile', 'internal_group', 'tax_ids') def _constrains_reconcile(self):