feat: 提现审核按俱乐部隔离并加固打款商户号,新增小溪审核目录复制脚本

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-26 01:20:42 +08:00
parent 332c42c85d
commit 280d8742c9
10 changed files with 661 additions and 38 deletions

View File

@@ -0,0 +1,153 @@
"""确保提现审核权限码 005bb并按俱乐部挂到指定角色可重复执行
权限码全局共用;隔离靠 Role.ClubID + 请求头俱乐部。
集团高管仍可跨俱乐部;俱乐部管理员仅本俱乐部。
用法示例:
python manage.py seed_club_withdraw_audit_perm
python manage.py seed_club_withdraw_audit_perm --club-id lxs --role-name 管理员
python manage.py seed_club_withdraw_audit_perm --all-clubs --role-name 管理员
python manage.py seed_club_withdraw_audit_perm --all-clubs --role-name 管理员 --dry-run
"""
import uuid
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.utils import timezone
from gvsdsdk.models import Permission, Role, RolePermission
from jituan.models import Club
WITHDRAW_AUDIT_PERM = '005bb'
WITHDRAW_AUDIT_NAME = '提现审核(按俱乐部)'
WITHDRAW_AUDIT_DESC = (
'审核本俱乐部提现申请(同意/拒绝/自动打款待收款)。'
'跨俱乐部仅集团高管可操作;须配合后台角色 ClubID 与数据范围任职。'
)
WITHDRAW_AUDIT_CATEGORY = '提现管理'
class Command(BaseCommand):
help = '写入 005bb 提现审核权限码,并按俱乐部挂到角色'
def add_arguments(self, parser):
parser.add_argument(
'--club-id', default='', help='仅处理该俱乐部角色(如 lxs / xq',
)
parser.add_argument(
'--all-clubs', action='store_true', help='处理全部启用中的俱乐部',
)
parser.add_argument(
'--role-name', default='',
help='角色名(如「管理员」);为空则只确保权限码存在,不挂角色',
)
parser.add_argument(
'--dry-run', action='store_true', help='只打印不写入',
)
def handle(self, *args, **options):
dry_run = options['dry_run']
club_id = (options.get('club_id') or '').strip()
all_clubs = options.get('all_clubs')
role_name = (options.get('role_name') or '').strip()
sample = Permission.objects.filter(PermStatus=1).first()
tenant_uuid = sample.TenantUUID if sample else uuid.UUID(
'00000000-0000-0000-0000-000000000001'
).bytes
perm = Permission.objects.filter(PermCode=WITHDRAW_AUDIT_PERM).first()
if perm:
self.stdout.write(f' 权限码已存在: {WITHDRAW_AUDIT_PERM}')
if not dry_run and (perm.PermName != WITHDRAW_AUDIT_NAME or not perm.PermDesc):
perm.PermName = WITHDRAW_AUDIT_NAME
perm.PermDesc = WITHDRAW_AUDIT_DESC
perm.PermCategory = WITHDRAW_AUDIT_CATEGORY
perm.save(update_fields=['PermName', 'PermDesc', 'PermCategory'])
self.stdout.write(self.style.SUCCESS(' 已更新 005bb 名称/说明'))
else:
if dry_run:
self.stdout.write(f'would create perm {WITHDRAW_AUDIT_PERM}')
else:
perm = Permission.objects.create(
PermUUID=uuid.uuid4().bytes,
TenantUUID=tenant_uuid,
PermCode=WITHDRAW_AUDIT_PERM,
PermName=WITHDRAW_AUDIT_NAME,
PermDesc=WITHDRAW_AUDIT_DESC,
PermCategory=WITHDRAW_AUDIT_CATEGORY,
PermStatus=1,
CreateTime=timezone.now(),
)
self.stdout.write(self.style.SUCCESS(f' 新增权限: {WITHDRAW_AUDIT_PERM}'))
if not role_name:
self.stdout.write(
self.style.WARNING(
'未指定 --role-name仅确保权限码。'
'给俱乐部挂权请加:--club-id lxs --role-name 管理员'
)
)
return
if not club_id and not all_clubs:
raise CommandError('挂角色时请指定 --club-id 或 --all-clubs')
if all_clubs:
club_ids = list(
Club.query.filter(status=1).values_list('club_id', flat=True)
)
else:
if not Club.query.filter(club_id=club_id, status=1).exists():
raise CommandError(f'俱乐部不存在或未启用: {club_id}')
club_ids = [club_id]
if not perm and dry_run:
self.stdout.write('dry-run: skip role binding (perm not loaded)')
return
linked = 0
missing_roles = 0
with transaction.atomic():
for cid in club_ids:
role = Role.objects.filter(
RoleName=role_name, ClubID=cid, RoleStatus=1,
).first()
if not role:
missing_roles += 1
self.stdout.write(
self.style.WARNING(f' [{cid}] 无角色「{role_name}」,跳过')
)
continue
exists = RolePermission.objects.filter(
RoleUUID=role.RoleUUID, PermUUID=perm.PermUUID,
).exists()
if exists:
self.stdout.write(f' [{cid}] 角色「{role_name}」已有 {WITHDRAW_AUDIT_PERM}')
continue
if dry_run:
self.stdout.write(
f'would link {WITHDRAW_AUDIT_PERM} -> [{cid}] {role_name}'
)
linked += 1
continue
RolePermission.objects.create(
RolePermUUID=uuid.uuid4().bytes,
RoleUUID=role.RoleUUID,
PermUUID=perm.PermUUID,
CreateTime=timezone.now(),
)
linked += 1
self.stdout.write(
self.style.SUCCESS(
f' [{cid}] 已给角色「{role_name}」挂上 {WITHDRAW_AUDIT_PERM}'
)
)
self.stdout.write(
self.style.SUCCESS(
f'完成:挂权 {linked},缺角色 {missing_roles}'
f'另请确认该账号在「数据范围配置」有对应俱乐部 SINGLE_CLUB 任职。'
)
)