128 lines
5.1 KiB
Python
128 lines
5.1 KiB
Python
"""诊断 / 对齐龙先生邀请种子与小程序 club_id。
|
||
|
||
用法:
|
||
python manage.py diagnose_lsx_invite
|
||
python manage.py diagnose_lsx_invite --align-to lsx
|
||
python manage.py diagnose_lsx_invite --align-to-appid
|
||
"""
|
||
from django.core.management.base import BaseCommand, CommandError
|
||
from django.db import transaction
|
||
|
||
from jituan.models import Club
|
||
from users.business_models import User
|
||
from users.models import UserGuanshi, UserZuzhang
|
||
|
||
LSX_APPID = 'wx7ff90e9d024fcdb8'
|
||
SEED_UIDS = ('9910001', '9910002')
|
||
FRONTEND_EXPECT = 'lsx'
|
||
|
||
|
||
class Command(BaseCommand):
|
||
help = '诊断龙先生种子邀请人 ClubID 与小程序是否一致,并可对齐'
|
||
|
||
def add_arguments(self, parser):
|
||
parser.add_argument(
|
||
'--align-to',
|
||
type=str,
|
||
default='',
|
||
help='把种子用户 ClubID 改成指定值(如 lsx)',
|
||
)
|
||
parser.add_argument(
|
||
'--align-to-appid',
|
||
action='store_true',
|
||
help='按 wx_appid=龙先生 找到俱乐部,把种子 ClubID 对齐过去',
|
||
)
|
||
|
||
def handle(self, *args, **options):
|
||
self.stdout.write(self.style.SUCCESS('=' * 60))
|
||
self.stdout.write('前端龙先生小程序默认 X-Club-Id / CLUB_ID = lsx')
|
||
self.stdout.write(f'龙先生 AppID = {LSX_APPID}')
|
||
self.stdout.write('')
|
||
|
||
clubs = list(Club.query.order_by('club_id'))
|
||
self.stdout.write(f'库里俱乐部 {len(clubs)} 个:')
|
||
target_by_app = None
|
||
for c in clubs:
|
||
mark = ''
|
||
if c.club_id == FRONTEND_EXPECT:
|
||
mark = ' ← 前端期望'
|
||
if (c.wx_appid or '') == LSX_APPID:
|
||
mark += ' ← AppID命中'
|
||
target_by_app = c
|
||
if '龙先生' in (c.name or ''):
|
||
mark += ' ← 名称命中'
|
||
self.stdout.write(
|
||
f' club_id={c.club_id!r} name={c.name!r} wx_appid={c.wx_appid or "(空)"}{mark}'
|
||
)
|
||
|
||
self.stdout.write('')
|
||
self.stdout.write('种子用户:')
|
||
for uid in SEED_UIDS:
|
||
user = User.query.filter(UserUID=uid).first()
|
||
if not user:
|
||
self.stdout.write(self.style.WARNING(f' {uid}: 不存在(还没跑 seed_lsx_invite_data?)'))
|
||
continue
|
||
role = []
|
||
try:
|
||
z = user.ZuzhangProfile
|
||
role.append(f'组长码={z.yaoqingma}')
|
||
except Exception:
|
||
pass
|
||
try:
|
||
g = user.GuanshiProfile
|
||
role.append(f'管事码={g.yaoqingma}')
|
||
except Exception:
|
||
pass
|
||
club = (user.ClubID or '').strip()
|
||
ok = club == FRONTEND_EXPECT
|
||
line = f' {uid}: ClubID={club or "(空)"} {" | ".join(role) or "无身份"}'
|
||
if ok:
|
||
self.stdout.write(self.style.SUCCESS(line + ' ✓ 与前端 lsx 一致'))
|
||
else:
|
||
self.stdout.write(self.style.ERROR(
|
||
line + f' ✗ 与前端 lsx 不一致 → 会报「邀请码不属于当前小程序俱乐部」'
|
||
))
|
||
|
||
self.stdout.write('')
|
||
self.stdout.write(self.style.WARNING(
|
||
'结论:这是后端校验(invite_guard),不是前端邀请码输错。\n'
|
||
'小程序发 X-Club-Id=lsx,邀请人 User.ClubID 必须也是 lsx。'
|
||
))
|
||
|
||
align_to = (options.get('align_to') or '').strip()
|
||
if options.get('align_to_appid'):
|
||
if not target_by_app:
|
||
raise CommandError(f'没有 wx_appid={LSX_APPID} 的俱乐部,无法对齐')
|
||
align_to = target_by_app.club_id
|
||
self.stdout.write(f'将按 AppID 对齐到 club_id={align_to!r}')
|
||
|
||
if not align_to:
|
||
self.stdout.write('')
|
||
self.stdout.write('若要修复,任选其一:')
|
||
self.stdout.write(' python manage.py diagnose_lsx_invite --align-to lsx')
|
||
self.stdout.write(' python manage.py diagnose_lsx_invite --align-to-appid')
|
||
self.stdout.write('然后前端 CLUB_ID 必须与种子 ClubID 相同。')
|
||
self.stdout.write(self.style.SUCCESS('=' * 60))
|
||
return
|
||
|
||
if not Club.query.filter(club_id=align_to).exists():
|
||
raise CommandError(f'目标俱乐部 {align_to!r} 不存在,请先在后台创建')
|
||
|
||
with transaction.atomic():
|
||
for uid in SEED_UIDS:
|
||
user = User.query.filter(UserUID=uid).first()
|
||
if not user:
|
||
self.stdout.write(self.style.WARNING(f'跳过不存在用户 {uid}'))
|
||
continue
|
||
old = user.ClubID
|
||
user.ClubID = align_to
|
||
user.save(update_fields=['ClubID'])
|
||
self.stdout.write(self.style.SUCCESS(
|
||
f'已更新 {uid}: ClubID {old!r} → {align_to!r}'
|
||
))
|
||
|
||
self.stdout.write(self.style.SUCCESS(
|
||
f'\n对齐完成。请确认小程序 config/club-config.js 的 CLUB_ID = {align_to!r}'
|
||
))
|
||
self.stdout.write(self.style.SUCCESS('=' * 60))
|