From dfe249a1f0de79fff0a0544e150a752a4ead8d1b Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Thu, 28 May 2026 15:20:20 +0700 Subject: [PATCH] feat: implement bi-directional synchronization of company access between employees and res.users --- models/__init__.py | 1 + models/__pycache__/__init__.cpython-312.pyc | Bin 259 -> 292 bytes .../__pycache__/hr_employee.cpython-312.pyc | Bin 5530 -> 7324 bytes models/hr_employee.py | 30 +++++++ models/res_users.py | 77 ++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 models/res_users.py diff --git a/models/__init__.py b/models/__init__.py index 5242a15..ab87c94 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -1,2 +1,3 @@ from . import hr_employee from . import pos_config +from . import res_users diff --git a/models/__pycache__/__init__.cpython-312.pyc b/models/__pycache__/__init__.cpython-312.pyc index 0863982224bebab2d9ecb04769e4dc9c4754b685..e5fbc03f6a0ad96ddae3f9b6d743ff311ab7818c 100644 GIT binary patch delta 113 zcmZo>TEfJ8nwOW00SJPm#Kqh|;sY}yBja5L$$JbEMeIO60AhCzYybcN diff --git a/models/__pycache__/hr_employee.cpython-312.pyc b/models/__pycache__/hr_employee.cpython-312.pyc index 980ff58f840beb6be55492924b98e30c8a8260ca..cc5ba1dae6c9e82a8a148a10760e4488890af4bc 100644 GIT binary patch delta 2560 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 delta 918 zcmYLHO=uHA6rS15&*p#A#I8x25=E?0(rR0^rP>y;wg=lZ=*1#zLw4Gx-TZVmZLI`R zC|D0d>mU_T(4z=ma`f1X;7LR%E9$uiq0sbF1f91Db(Z~j?|pCHeDmJC>VJ98|Jmnr zBfh)`$~;vz{oD2gM(8p78y#RlJmnA&anHB1U?>!m-*X0*7F)7VQ}Qj8JXY%xp5cJ$$(0J_Y;jf1Yeo*Uj6GcY?z)Kw z!u$}^{hu_2yk?4|xNJI`!K7f?45H7N5-F7R(kdZ_z&9ll?5#~@cRi+C}MAwHcHX_)Q!ryX(b(-a#FT*N6>3GDC!<8r)Y+Kr_$p{7$c zNS5a2k`j$UrWc?SpbOwU2h*{zlBKf-O@ZT5)tsI+3{^EG?kB7@{E%Abbo0plmN7cg z6yMpbewKZa2l>fzFcSX26+XvXsKRp_>xrv&HP|EIUbYxIA)c%{S*E3jeG2)cRRmws zQ@a!XjW0Rr1-`-btCY;&0-U((4Sz0F= 3: + if cmd[0] == 6: + existing_ids.update(cmd[2]) + has_six = True + six_index = idx + elif cmd[0] == 4: + existing_ids.add(cmd[1]) + + if company_id not in existing_ids: + if has_six and six_index != -1: + cmd = list(company_ids_commands[six_index]) + cmd[2] = list(cmd[2]) + [company_id] + company_ids_commands[six_index] = tuple(cmd) + else: + company_ids_commands.append((4, company_id)) + else: + vals['company_ids'] = [(6, 0, [company_id])] + + users = super().create(vals_list) + users.sudo()._sync_employee_company_ids() + return users + + def write(self, vals): + # Pre-process vals to ensure primary company_id is always in allowed company_ids + company_id = vals.get('company_id') + if company_id: + has_company_ids = 'company_ids' in vals + existing_ids = set() + if has_company_ids: + for cmd in vals['company_ids']: + if isinstance(cmd, (list, tuple)) and len(cmd) >= 3: + if cmd[0] == 6: + existing_ids.update(cmd[2]) + elif cmd[0] == 4: + existing_ids.add(cmd[1]) + + for user in self: + user_allowed = set(user.company_ids.ids) + if has_company_ids: + if company_id not in existing_ids: + vals['company_ids'] = list(vals['company_ids']) + [(4, company_id)] + else: + if company_id not in user_allowed: + vals['company_ids'] = [(4, company_id)] + + res = super().write(vals) + if any(f in vals for f in ['company_id', 'company_ids']): + self.sudo()._sync_employee_company_ids() + return res + + def _sync_employee_company_ids(self): + for user in self: + employee_companies = user.employee_ids.mapped('company_ids') + employee_primary_companies = user.employee_ids.mapped('company_id') + companies_to_add = (employee_companies | employee_primary_companies | user.company_id) - user.company_ids + if companies_to_add: + user.write({ + 'company_ids': [(4, cid.id) for cid in companies_to_add] + })