持有000001且处于当前俱乐部视图时可加余额/押金/可提现;强制目标用户同俱乐部,并在修改记录中写入俱乐部ID。 Co-authored-by: Cursor <cursoragent@cursor.com>
137 lines
5.2 KiB
Python
137 lines
5.2 KiB
Python
"""集团/俱乐部资金处置权限。
|
||
|
||
加余额(及同类增加资金):
|
||
- 系统超管 / 集团高管(GROUP_OWNER、GROUP_SUPER_ADMIN):可按数据范围操作
|
||
- 当前俱乐部超级管理 000001:仅限 SINGLE_CLUB 本店,且目标用户必须属于当前俱乐部
|
||
不再强制「仅集团高管才能加余额」。
|
||
|
||
提现审核:权限码 005bb + 按俱乐部隔离——
|
||
- 子公司视图:持有 005bb 且任职含当前俱乐部 → 可审本俱乐部
|
||
- 集团汇总视图 / 跨俱乐部:须集团资金处置权
|
||
"""
|
||
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
|
||
2) 集团高管:可在 ALL_CLUBS 或任意子公司视图操作
|
||
3) 俱乐部管理员:仅 SINGLE_CLUB 且当前 club 在其任职范围内
|
||
"""
|
||
from backend.utils import 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:
|
||
return None, Response({'code': 403, 'msg': '您无权操作提现审核'})
|
||
|
||
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
|