"""诊断 / 对齐龙先生邀请种子与小程序 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))