"""集团/俱乐部资金处置权限。 加余额(及同类增加资金): - 系统超管 / 集团高管(GROUP_OWNER、GROUP_SUPER_ADMIN):可按数据范围操作 - 当前俱乐部超级管理 000001:仅限 SINGLE_CLUB 本店,且目标用户必须属于当前俱乐部 不再强制「仅集团高管才能加余额」。 提现审核:权限码 005bb 或本店超级管理 000001 + 按俱乐部隔离—— - 子公司视图:持有 005bb/000001 且任职含当前俱乐部 → 可审本俱乐部 - 集团汇总视图 / 跨俱乐部:须集团资金处置权 不再强制「必须集团权限才能审本店提现」。 """ from django.db.models import Q from jituan.constants import DATA_SCOPE_ALL from jituan.models import AdminAssignment from jituan.services.admin_context import ( GROUP_MANAGE_ROLES, build_admin_club_context, get_allowed_club_ids, is_system_super_admin, ) MSG_GROUP_FINANCE_REQUIRED = '该操作仅集团高管可执行(需在数据范围配置中为集团级任职)' MSG_BALANCE_ADD_DENIED = ( '无权加余额:需当前俱乐部超级管理权限(000001),或集团高管任职;' '且仅能操作当前俱乐部用户' ) MSG_BALANCE_ADD_CROSS_CLUB = '跨俱乐部加余额仅集团高管可执行,请切换到具体俱乐部后再操作' MSG_BALANCE_ADD_CLUB_DENIED = '无权在该俱乐部加余额' MSG_WITHDRAW_CROSS_CLUB = '跨俱乐部提现审核仅集团高管可执行,请切换到具体俱乐部后再操作' MSG_WITHDRAW_CLUB_DENIED = '无权审核该俱乐部提现' def has_group_finance_exec(user, request=None): """系统超管 / 集团任职(GROUP_OWNER、GROUP_SUPER_ADMIN)。""" if is_system_super_admin(user): return True ctx = build_admin_club_context(user) if ctx.get('is_group_admin') and ctx.get('role_code') in GROUP_MANAGE_ROLES: return True uid = getattr(user, 'UserUID', None) if not uid: return False return AdminAssignment.query.filter( yonghuid=uid, status=1, role_code__in=GROUP_MANAGE_ROLES, ).filter( Q(club_id__isnull=True) | Q(data_scope=DATA_SCOPE_ALL), ).exists() def deny_group_finance_exec(user, request=None): """仅集团高管(旧闸门,保留给非加余额场景如需)。""" from rest_framework.response import Response if has_group_finance_exec(user, request): return None return Response({'code': 403, 'msg': MSG_GROUP_FINANCE_REQUIRED}) def deny_balance_add_exec(request, *, permissions=None, target_user=None): """ 加余额 / 加押金 / 增加可提现等「资金增加」闸门。 放行条件(满足其一): 1) 系统超管或集团高管 2) 当前请求权限含俱乐部超级管理 000001,且为 SINGLE_CLUB, 当前俱乐部在任职范围内 无论哪种身份:若传入 target_user,必须属于当前请求俱乐部数据范围 (集团 ALL_CLUBS 视图下目标校验放行,见 forbid_if_user_out_of_scope)。 """ from rest_framework.response import Response from jituan.services.club_context import resolve_club_id_from_request, resolve_club_scope from jituan.services.club_user_access import forbid_if_user_out_of_scope user = getattr(request, 'user', None) perms = permissions or [] if has_group_finance_exec(user, request): if target_user is not None: denied = forbid_if_user_out_of_scope(request, target_user) if denied: return denied return None if '000001' not in perms: return Response({'code': 403, 'msg': MSG_BALANCE_ADD_DENIED}) scope = resolve_club_scope(request) if scope == DATA_SCOPE_ALL: return Response({'code': 403, 'msg': MSG_BALANCE_ADD_CROSS_CLUB}) club_id = resolve_club_id_from_request(request) allowed = get_allowed_club_ids(user) if not club_id or club_id not in allowed: return Response({'code': 403, 'msg': MSG_BALANCE_ADD_CLUB_DENIED}) if target_user is not None: denied = forbid_if_user_out_of_scope(request, target_user) if denied: return denied return None def require_withdraw_audit_access(request, phone): """ 提现审核访问: 1) 权限码 005bb,或本店超级管理 000001 2) 集团高管:可在 ALL_CLUBS 或任意子公司视图操作 3) 俱乐部侧:仅 SINGLE_CLUB 且当前 club 在其任职范围内(只能审本店) """ from backend.utils import has_club_super_perm, verify_kefu_permission from rest_framework.response import Response from jituan.services.club_context import resolve_club_id_from_request, resolve_club_scope kefu, permissions = verify_kefu_permission(request, phone) if kefu is None: return None, permissions if '005bb' not in permissions and not has_club_super_perm(permissions): return None, Response({'code': 403, 'msg': '您无权操作提现审核(需要 005bb 或本店超级管理 000001)'}) if has_group_finance_exec(request.user, request): return kefu, None scope = resolve_club_scope(request) if scope == DATA_SCOPE_ALL: return None, Response({'code': 403, 'msg': MSG_WITHDRAW_CROSS_CLUB}) club_id = resolve_club_id_from_request(request) allowed = get_allowed_club_ids(request.user) if not club_id or club_id not in allowed: return None, Response({'code': 403, 'msg': MSG_WITHDRAW_CLUB_DENIED}) return kefu, None