#!/usr/bin/env python3 """ migrate_to_gvsdsdk_user.py — 将 UserMain 用户体系迁移到 gvsdsdk.User + RBAC 使用方式: cd /opt/.../django python manage.py shell < migrate_to_gvsdsdk_user.py 或: python manage.py shell >>> exec(open('migrate_to_gvsdsdk_user.py').read()) """ import uuid import datetime from django.db import transaction from django.conf import settings # === 配置 === TENANT_UUID = uuid.uuid4().bytes # 本租户 UUID(所有角色共用) COMPANY_UUID = uuid.uuid4().bytes # 默认公司 UUID # 角色映射:user_type → (RoleName, RoleDesc) ROLE_MAP = { 'normal': ('消费者', '普通消费者/老板'), 'dashou': ('打手', '接单打手'), 'shop': ('商家', '发布订单的商家'), 'guanshi': ('负责人', '管事/负责人'), 'admin': ('管理员', '系统管理员'), 'kefu': ('客服', '客服人员'), 'zuzhang': ('组长', '组长'), 'shenheguan': ('审核官', '审核官'), } # 权限映射:每个角色拥有的权限码 PERMISSION_MAP = { '消费者': ['view_orders', 'create_order', 'view_own_profile'], '打手': ['view_orders', 'accept_order', 'view_own_profile', 'withdraw'], '商家': ['view_orders', 'create_order', 'view_own_profile', 'withdraw', 'manage_own_orders'], '负责人': ['view_orders', 'view_own_profile', 'withdraw', 'invite_dashou', 'view_dashou_stats'], '管理员': ['admin_access', 'manage_users', 'view_all_orders', 'manage_orders', 'view_stats', 'manage_fines'], '客服': ['kefu_access', 'view_orders', 'manage_orders', 'apply_fine', 'view_stats'], '组长': ['view_orders', 'view_own_profile', 'withdraw', 'invite_dashou'], '审核官': ['view_orders', 'review_orders', 'view_own_profile', 'withdraw'], } def run_migration(): from gvsdsdk.models import User, Role, Permission, UserRole, RolePermission from users.models import ( UserMain, UserBoss, UserDashou, UserShangjia, UserGuanshi, UserZuzhang, UserShenheguan, AdminProfile, UserKefu, UserSensitiveData ) print("=" * 60) print("开始迁移 UserMain → gvsdsdk.User + RBAC") print("=" * 60) # ========== 第1步:创建租户下的角色和权限 ========== print("\n[1/6] 创建角色和权限...") created_roles = {} created_perms = {} for user_type, (role_name, role_desc) in ROLE_MAP.items(): # 创建角色 role, created = Role.objects.get_or_create( RoleName=role_name, TenantUUID=TENANT_UUID, defaults={ 'RoleUUID': uuid.uuid4().bytes, 'RoleDesc': role_desc, 'RoleStatus': 1, 'AssignScope': 0, } ) if created: print(f" 创建角色: {role_name}") created_roles[user_type] = role # 创建该角色的权限 perm_codes = PERMISSION_MAP.get(role_name, []) for perm_code in perm_codes: perm, perm_created = Permission.objects.get_or_create( PermCode=perm_code, TenantUUID=TENANT_UUID, defaults={ 'PermUUID': uuid.uuid4().bytes, 'PermName': perm_code, 'PermCategory': role_name, 'PermStatus': 1, } ) if perm_created: print(f" 创建权限: {perm_code}") created_perms[perm_code] = perm # 关联角色-权限 RolePermission.objects.get_or_create( RoleUUID=role.RoleUUID, PermUUID=perm.PermUUID, defaults={ 'RolePermUUID': uuid.uuid4().bytes, } ) # ========== 第2步:迁移用户 ========== print("\n[2/6] 迁移用户数据...") user_main_qs = UserMain.objects.all() total = user_main_qs.count() print(f" 共 {total} 个用户待迁移") # 构建 yonghuid → UserUUID 映射 uid_map = {} # yonghuid → UserUUID (bytes) for i, um in enumerate(user_main_qs): if (i + 1) % 100 == 0: print(f" 进度: {i+1}/{total}") user_uuid = uuid.uuid4().bytes # 创建 gvsdsdk User user = User.objects.create( UserUUID=user_uuid, UserName=um.yonghuid, # 用 yonghuid 作为用户名 UserUID=um.yonghuid, OpenID=um.openid or '', UnionID=um.unionid or '', Avatar=um.avatar or 'a_long/morentouxiang.jpg', Phone=um.phone or '', PhoneVerified=um.shoujihao_renzheng or False, IP=um.ip or '', UserAccountLicense=1, UserPositionStatus=0, UserCreateTime=um.create_time or datetime.datetime.utcnow(), UserLastLoginDate=um.last_login_time or datetime.datetime.utcnow(), IsStaff=(um.user_type == 'admin'), IsSuperuser=(um.user_type == 'admin'), ) uid_map[um.yonghuid] = user_uuid # 创建 UserRole user_type = um.user_type or 'normal' role = created_roles.get(user_type) if role: UserRole.objects.create( UserRoleUUID=uuid.uuid4().bytes, UserUUID=user_uuid, RoleUUID=role.RoleUUID, CompanyUUID=COMPANY_UUID, ) # 创建 UserSensitiveData UserSensitiveData.objects.create( user_uuid_id=user_uuid, password=um.password or '', zhifu=um.zhifu or '', skzhanghao=um.skzhanghao or '', shoujihao_renzheng=um.shoujihao_renzheng or False, ) print(f" 用户迁移完成: {len(uid_map)} 个") # ========== 第3步:迁移扩展表 FK ========== print("\n[3/6] 迁移扩展表 FK...") ext_tables = [ ('UserBoss', UserBoss, 'boss_profile'), ('UserDashou', UserDashou, 'dashou_profile'), ('UserShangjia', UserShangjia, 'shop_profile'), ('UserGuanshi', UserGuanshi, 'guanshi_profile'), ('UserZuzhang', UserZuzhang, 'zuzhang_profile'), ('UserShenheguan', UserShenheguan, 'shenheguan_profile'), ('AdminProfile', AdminProfile, 'admin_profile'), ('UserKefu', UserKefu, 'kefu_profile'), ] for table_name, model, _ in ext_tables: count = 0 for obj in model.objects.all(): old_user_id = obj.user_id # 旧 FK (UserMain.id) # 通过旧 UserMain 查找 yonghuid → 新 UserUUID try: old_user = UserMain.objects.get(id=old_user_id) new_uuid = uid_map.get(old_user.yonghuid) if new_uuid: obj.user_id = new_uuid # 更新 FK 为新 UserUUID obj.save(update_fields=['user_id']) count += 1 except UserMain.DoesNotExist: pass print(f" {table_name}: 迁移 {count} 条") # ========== 第4步:迁移其他引用 yonghuid 的表 ========== print("\n[4/6] 迁移其他表的 yonghuid 引用...") # Tixianjilu, TixianShenheJilu, TixianAutoRecord, Xiugaijilu, RankingRecord # 这些表使用 yonghuid 字符串字段,不需要修改(UserUID 保留相同值) print(" 这些表使用 yonghuid 字符串字段,值不变,无需迁移") # ========== 第5步:迁移 backend.UserRole ========== print("\n[5/6] 迁移 backend.UserRole...") from backend.models import UserRole as BackendUserRole count = 0 for bur in BackendUserRole.objects.all(): # account_id 是手机号,查找对应的 UserMain → 新 UserUUID try: um = UserMain.objects.get(phone=bur.account_id) new_uuid = uid_map.get(um.yonghuid) if new_uuid: # 查找对应的新角色 old_role = bur.role # 尝试匹配角色名 role_name_map = { '客服': 'kefu', '打手': 'dashou', '商家': 'shop', '管事': 'guanshi', '管理员': 'admin', '组长': 'zuzhang', '审核官': 'shenheguan', '消费者': 'normal', } new_role = None for ut, r in created_roles.items(): if old_role.role_name in r.RoleName or old_role.role_code in ut: new_role = r break if new_role: UserRole.objects.get_or_create( UserUUID=new_uuid, RoleUUID=new_role.RoleUUID, CompanyUUID=COMPANY_UUID, defaults={'UserRoleUUID': uuid.uuid4().bytes} ) count += 1 except UserMain.DoesNotExist: pass print(f" 迁移 {count} 条 backend.UserRole") # ========== 第6步:验证 ========== print("\n[6/6] 验证迁移结果...") new_user_count = User.objects.count() new_role_count = Role.objects.filter(TenantUUID=TENANT_UUID).count() new_perm_count = Permission.objects.filter(TenantUUID=TENANT_UUID).count() new_ur_count = UserRole.objects.count() print(f" gvsdsdk.User: {new_user_count}") print(f" Role: {new_role_count}") print(f" Permission: {new_perm_count}") print(f" UserRole: {new_ur_count}") print(f" UserSensitiveData: {UserSensitiveData.objects.count()}") print("\n" + "=" * 60) print("迁移完成!") print(f"TENANT_UUID = {uuid.UUID(bytes=TENANT_UUID)}") print(f"COMPANY_UUID = {uuid.UUID(bytes=COMPANY_UUID)}") print("请将这两个 UUID 保存到 settings.py 中") print("=" * 60) if __name__ == '__main__': run_migration()