From 49232b7697fb9d8a2e29790049efcd7d1a365ac4 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Tue, 18 Oct 2022 12:26:28 +0000 Subject: [PATCH] [FIX] base: prevent to disable companies still used by users The initial bug report was the ability to disable all companies at once and messing up the whole database when you do so. However, forcing administrators to choose a new company for active users before archiving a company seems relevant, and solve the above reported issue in the same time. closes odoo/odoo#104112 X-original-commit: 786ed3c7a688a662767abfb6e74e7f6dbc938f2e Signed-off-by: Vincent Schippefilt (vsc) Signed-off-by: Denis Ledoux (dle) --- odoo/addons/base/i18n/base.pot | 8 +++++ odoo/addons/base/models/res_company.py | 17 +++++++++ odoo/addons/base/models/res_users.py | 4 +-- odoo/addons/base/tests/__init__.py | 1 + odoo/addons/base/tests/test_res_company.py | 40 ++++++++++++++++++++++ 5 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 odoo/addons/base/tests/test_res_company.py diff --git a/odoo/addons/base/i18n/base.pot b/odoo/addons/base/i18n/base.pot index a341f0381e7..f932534116d 100644 --- a/odoo/addons/base/i18n/base.pot +++ b/odoo/addons/base/i18n/base.pot @@ -26693,6 +26693,14 @@ msgstr "" msgid "The combination Account Number/Partner must be unique." msgstr "" +#. module: base +#: code:addons/base/models/res_company.py:0 +#, python-format +msgid "" +"The company %(company_name)s cannot be archived because it is still used as " +"the default company of %(active_users)s users." +msgstr "" + #. module: base #: model:ir.model.constraint,message:base.constraint_res_company_name_uniq msgid "The company name must be unique !" diff --git a/odoo/addons/base/models/res_company.py b/odoo/addons/base/models/res_company.py index 913db9016f5..84c203756df 100644 --- a/odoo/addons/base/models/res_company.py +++ b/odoo/addons/base/models/res_company.py @@ -258,6 +258,23 @@ class Company(models.Model): self.invalidate_model(company_address_fields) return res + @api.constrains('active') + def _check_active(self): + for company in self: + if not company.active: + company_active_users = self.env['res.users'].search_count([ + ('company_id', '=', company.id), + ('active', '=', True), + ]) + if company_active_users: + # You cannot disable companies with active users + raise ValidationError(_( + 'The company %(company_name)s cannot be archived because it is still used ' + 'as the default company of %(active_users)s users.', + company_name=company.name, + active_users=company_active_users, + )) + @api.constrains('parent_id') def _check_parent_id(self): if not self._check_recursion(): diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py index 04dfdf9daa7..58bea3bb662 100644 --- a/odoo/addons/base/models/res_users.py +++ b/odoo/addons/base/models/res_users.py @@ -472,9 +472,9 @@ class Users(models.Model): # skip SpecialValue (e.g. for missing record or access right) pass - @api.constrains('company_id', 'company_ids') + @api.constrains('company_id', 'company_ids', 'active') def _check_company(self): - for user in self: + for user in self.filtered(lambda u: u.active): if user.company_id not in user.company_ids: raise ValidationError( _('Company %(company_name)s is not in the allowed companies for user %(user_name)s (%(company_allowed)s).', diff --git a/odoo/addons/base/tests/__init__.py b/odoo/addons/base/tests/__init__.py index c711ac74b39..5585e8fb400 100644 --- a/odoo/addons/base/tests/__init__.py +++ b/odoo/addons/base/tests/__init__.py @@ -43,6 +43,7 @@ from . import test_translate from . import test_user_has_group from . import test_views from . import test_xmlrpc +from . import test_res_company from . import test_res_partner from . import test_res_partner_bank from . import test_res_users diff --git a/odoo/addons/base/tests/test_res_company.py b/odoo/addons/base/tests/test_res_company.py new file mode 100644 index 00000000000..caf6d785c89 --- /dev/null +++ b/odoo/addons/base/tests/test_res_company.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.exceptions import ValidationError +from odoo.tests.common import TransactionCase + + +class TestCompany(TransactionCase): + + def test_check_active(self): + """Tests the ability to archive a company whether or not it still has active users. + Tests an archived user in an archived company cannot be unarchived + without changing its company to an active company.""" + company = self.env['res.company'].create({'name': 'foo'}) + user = self.env['res.users'].create({ + 'name': 'foo', + 'login': 'foo', + 'company_id': company.id, + 'company_ids': company.ids, + }) + + # The company cannot be archived because it still has active users + with self.assertRaisesRegex(ValidationError, 'The company foo cannot be archived'): + company.action_archive() + + # The company can be archived because it has no active users + user.action_archive() + company.action_archive() + + # The user cannot be unarchived because it's default company is archived + with self.assertRaisesRegex(ValidationError, 'Company foo is not in the allowed companies'): + user.action_unarchive() + + # The user can be unarchived once we set another, active, company + main_company = self.env.ref('base.main_company') + user.write({ + 'company_id': main_company.id, + 'company_ids': main_company.ids, + }) + user.action_unarchive()