From c3c5a07ec904c2c9892569e1285b47ed0f87d494 Mon Sep 17 00:00:00 2001 From: Alessandro Uffreduzzi Date: Thu, 4 Jan 2024 16:25:52 +0100 Subject: [PATCH] [FIX] operating_unit: default operating unit more multi-company friendly This PR fixes an issue with the method operating_unit_default_get where it would return an operating unit even for a company that was not active, which would cause all sorts of issues Steps to reproduce on runboat, taking as example purchase_operating_unit: - User has a default ou belonging to Company 1 - Switch to Company 2 (make sure Company 1 is not active at all) - Try to create a Purchase Order The issue arises because the operating_unit field is pre-compiled on the PO with an Operating Unit whose company is inactive, and the onchanges cannot find or access related data. --- operating_unit/models/res_users.py | 14 ++++++- operating_unit/tests/test_operating_unit.py | 42 ++++++++++++++++++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/operating_unit/models/res_users.py b/operating_unit/models/res_users.py index 2b71506a86..34e1e57570 100644 --- a/operating_unit/models/res_users.py +++ b/operating_unit/models/res_users.py @@ -14,7 +14,19 @@ def operating_unit_default_get(self, uid2=False): if not uid2: uid2 = self.env.user.id user = self.env["res.users"].browse(uid2) - return user.default_operating_unit_id + # check if the company of the default OU is active + if user.default_operating_unit_id.sudo().company_id in self.env.companies: + return user.default_operating_unit_id + else: + # find an OU of the main active company + for ou in user.assigned_operating_unit_ids: + if ou.sudo().company_id in self.env.company: + return ou + # find an OU of any active company + for ou in user.assigned_operating_unit_ids: + if ou.sudo().company_id in self.env.companies: + return ou + return False @api.model def _default_operating_unit(self): diff --git a/operating_unit/tests/test_operating_unit.py b/operating_unit/tests/test_operating_unit.py index 2665b006ca..c7e1ca3ce2 100644 --- a/operating_unit/tests/test_operating_unit.py +++ b/operating_unit/tests/test_operating_unit.py @@ -18,6 +18,7 @@ def setUp(self): self.grp_ou_multi = self.env.ref("operating_unit.group_multi_operating_unit") # Company self.company = self.env.ref("base.main_company") + self.company_2 = self.env["res.company"].create({"name": "Second company"}) # Main Operating Unit self.ou1 = self.env.ref("operating_unit.main_operating_unit") # B2C Operating Unit @@ -50,12 +51,21 @@ def _create_user(self, login, group, company, operating_units, context=None): ) return user - def _create_operating_unit(self, uid, name, code): + def _create_operating_unit(self, uid, name, code, company_id=None): """Create Operating Unit""" + if company_id is None: + company_id = self.company ou = ( self.env["operating.unit"] .with_user(uid) - .create({"name": name, "code": code, "partner_id": self.company.id}) + .create( + { + "name": name, + "code": code, + "partner_id": company_id.partner_id.id, + "company_id": company_id.id, + } + ) ) return ou @@ -138,3 +148,31 @@ def test_02_operating_unit(self): line.code = "007" user_form.name = "Test Customer" user_form.login = "test2" + + def test_03_operating_unit(self): + """ + The method operating_unit_default_get should not return + operating units belonging to a company that is not active + """ + self.assertEqual( + self.res_users_model.operating_unit_default_get(uid2=self.user1.id), + self.ou1, + ) + self.assertEqual( + self.res_users_model.with_company( + self.company_2 + ).operating_unit_default_get(uid2=self.user1.id), + False, + ) + + self.user1.company_ids += self.company_2 + ou_company_2 = self._create_operating_unit( + self.user1.id, "Test Company", "TESTC", self.company_2 + ) + self.user1.assigned_operating_unit_ids += ou_company_2 + self.assertEqual( + self.res_users_model.with_company( + self.company_2 + ).operating_unit_default_get(uid2=self.user1.id), + ou_company_2, + )