261 lines
9.9 KiB
Python
261 lines
9.9 KiB
Python
#!/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 Role, Permission, UserRole, RolePermission
|
||
from users.business_models import User
|
||
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.CreateTime 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()
|