from __future__ import annotations from dataclasses import dataclass @dataclass class ClientAccessScope: tenant_id: int branch_id: int | None allow_cross_branch: bool allow_cross_tenant: bool allow_all_clients: bool own_only: bool locked_partner_id: int | None can_assign_partner: bool can_change_branch: bool can_change_tenant: bool def build_scope(request, user, permission_checker): active_tenant_id = int(request.session.get("active_tenant_id") or user.tenant_id) active_branch_value = request.session.get("active_branch_id") active_branch_id = None if active_branch_value in (None, "", 0, "0") else int(active_branch_value) allow_cross_branch = permission_checker("clients.cross_branch") allow_cross_tenant = permission_checker("clients.cross_tenant") can_assign_partner = permission_checker("clients.assign_partner") own_only = permission_checker("clients.view.own_only") allow_all_clients = bool((allow_cross_tenant and allow_cross_branch and not own_only) or permission_checker("clients.view.all")) locked_partner_id = user.id if own_only else None can_change_branch = allow_cross_branch can_change_tenant = allow_cross_tenant return ClientAccessScope( tenant_id=active_tenant_id, branch_id=active_branch_id or getattr(user, "branch_id", None), allow_cross_branch=allow_cross_branch, allow_cross_tenant=allow_cross_tenant, allow_all_clients=allow_all_clients, own_only=own_only, locked_partner_id=locked_partner_id, can_assign_partner=can_assign_partner, can_change_branch=can_change_branch, can_change_tenant=can_change_tenant, ) def effective_partner_id(row: dict): return row.get("assoc_partner_user_id") or row.get("partner_id") def effective_tenant_id(row: dict): return row.get("assoc_firm_tenant_id") or row.get("tenant_id") def effective_branch_id(row: dict): return row.get("branch_id") def can_view_client_row(scope: ClientAccessScope, row: dict, *, user_id: int) -> bool: if scope.allow_all_clients: return True if not scope.allow_cross_tenant and effective_tenant_id(row) != scope.tenant_id: return False branch_id = effective_branch_id(row) if not scope.allow_cross_branch and scope.branch_id and branch_id and branch_id != scope.branch_id: return False if scope.own_only and scope.locked_partner_id and effective_partner_id(row) != scope.locked_partner_id: return False return True