diff --git a/addons/account/models/account_account.py b/addons/account/models/account_account.py index 9b4aed8d787..a559c2cd743 100644 --- a/addons/account/models/account_account.py +++ b/addons/account/models/account_account.py @@ -702,29 +702,37 @@ class AccountGroup(models.Model): The most specific is the one with the longest prefixes and with the starting prefix being smaller than the account code and the ending prefix being greater. """ - if not self and not account_ids: + company_ids = account_ids.company_id.ids if account_ids else self.company_id.ids + account_ids = account_ids.ids if account_ids else [] + if not company_ids and not account_ids: return self.env['account.group'].flush(self.env['account.group']._fields) self.env['account.account'].flush(self.env['account.account']._fields) - query = """ - WITH relation AS ( - SELECT DISTINCT FIRST_VALUE(agroup.id) OVER (PARTITION BY account.id ORDER BY char_length(agroup.code_prefix_start) DESC, agroup.id) AS group_id, - account.id AS account_id - FROM account_group agroup - JOIN account_account account + + account_where_clause = '' + where_params = [tuple(company_ids)] + if account_ids: + account_where_clause = 'AND account.id IN %s' + where_params.append(tuple(account_ids)) + + self._cr.execute(f''' + WITH candidates_account_groups AS ( + SELECT + account.id AS account_id, + ARRAY_AGG(agroup.id ORDER BY char_length(agroup.code_prefix_start) DESC, agroup.id) AS group_ids + FROM account_account account + LEFT JOIN account_group agroup ON agroup.code_prefix_start <= LEFT(account.code, char_length(agroup.code_prefix_start)) - AND agroup.code_prefix_end >= LEFT(account.code, char_length(agroup.code_prefix_end)) - AND agroup.company_id = account.company_id - WHERE account.company_id IN %(company_ids)s {where_account} + AND agroup.code_prefix_end >= LEFT(account.code, char_length(agroup.code_prefix_end)) + AND agroup.company_id = account.company_id + WHERE account.company_id IN %s {account_where_clause} + GROUP BY account.id ) - UPDATE account_account account - SET group_id = relation.group_id - FROM relation - WHERE relation.account_id = account.id; - """.format( - where_account=account_ids and 'AND account.id IN %(account_ids)s' or '' - ) - self.env.cr.execute(query, {'company_ids': tuple((self.company_id or account_ids.company_id).ids), 'account_ids': account_ids and tuple(account_ids.ids)}) + UPDATE account_account + SET group_id = rel.group_ids[1] + FROM candidates_account_groups rel + WHERE account_account.id = rel.account_id + ''', where_params) self.env['account.account'].invalidate_cache(fnames=['group_id']) def _adapt_parent_account_group(self): diff --git a/addons/account/tests/test_account_account.py b/addons/account/tests/test_account_account.py index 277d98ef3b8..f4666e17974 100644 --- a/addons/account/tests/test_account_account.py +++ b/addons/account/tests/test_account_account.py @@ -135,3 +135,21 @@ class TestAccountAccount(AccountTestInvoicingCommon): self.company_data['default_journal_bank'].company_id.account_journal_payment_debit_account_id.reconcile = False with self.assertRaises(ValidationError), self.cr.savepoint(): self.company_data['default_journal_bank'].company_id.account_journal_payment_credit_account_id.reconcile = False + + def test_remove_account_from_account_group(self): + """Test if an account is well removed from account group""" + group = self.env['account.group'].create({ + 'name': 'test_group', + 'code_prefix_start': 401000, + 'code_prefix_end': 402000, + 'company_id': self.env.company.id + }) + + account_1 = self.company_data['default_account_revenue'].copy({'code': 401000}) + account_2 = self.company_data['default_account_revenue'].copy({'code': 402000}) + + self.assertRecordValues(account_1 + account_2, [{'group_id': group.id}] * 2) + + group.code_prefix_end = 401000 + + self.assertRecordValues(account_1 + account_2, [{'group_id': group.id}, {'group_id': False}])