diff --git a/models/account_journal.py b/models/account_journal.py index 5dfe845..f16645e 100644 --- a/models/account_journal.py +++ b/models/account_journal.py @@ -30,13 +30,61 @@ class AccountJournal(models.Model): self.env.context.get('install_mode') ) if not bypass: - allowed_ids = user.sudo().allowed_journal_ids.ids + allowed_ids = list(user.sudo().allowed_journal_ids.ids) + + # When Odoo's fetch() verifies a record it just loaded, it re-runs + # _search with [('id', 'in', [X])]. The record was already cleared + # by _check_access/check_access_rule, so we must honour the explicit + # IDs present in the domain and add them to the allow-list so they + # survive the sudo search. + for leaf in domain: + if ( + isinstance(leaf, (list, tuple)) + and len(leaf) == 3 + and leaf[0] == 'id' + and leaf[1] in ('=', 'in') + ): + value = leaf[2] + if isinstance(value, (list, tuple, set)): + allowed_ids.extend(value) + elif isinstance(value, int): + allowed_ids.append(value) + domain = [('id', 'in', allowed_ids)] + list(domain) # Run the search as sudo to bypass standard multi-company rules return self.sudo()._search(domain, offset=offset, limit=limit, order=order, **kwargs) return super(AccountJournal, self)._search(domain, offset=offset, limit=limit, order=order, **kwargs) + def _check_access(self, operation): + """ + Overridden to bypass multi-company record rules for allowed journals, + and enforce the allowed journals restriction for write, create, and delete operations. + """ + if self.env.su: + return super(AccountJournal, self)._check_access(operation) + + user = self.env.user + allowed_journals = user.sudo().allowed_journal_ids + if allowed_journals: + # Enforce restriction for write, create, and delete operations. + if operation in ('write', 'create', 'unlink'): + forbidden = self.filtered(lambda j: j.id not in allowed_journals.ids) + if forbidden: + import functools + return forbidden, functools.partial(AccessError, _("You do not have access to this journal.")) + + # Read operations are allowed to prevent access errors when loading + # documents (payments/moves) referencing other journals. + if operation == 'read': + return None + + # If all records in self are allowed, bypass standard record rules. + if all(j.id in allowed_journals.ids for j in self): + return None + + return super(AccountJournal, self)._check_access(operation) + def check_access_rule(self, operation): """ Overridden to bypass multi-company record rules for allowed journals, @@ -55,6 +103,9 @@ class AccountJournal(models.Model): if not all(j.id in allowed_journals.ids for j in self): raise AccessError(_("You do not have access to this journal.")) + if operation == 'read': + return + # If all records in self are allowed, bypass standard record rules. if all(j.id in allowed_journals.ids for j in self): return