fix: 邀请码俱乐部不符时提示两侧 club_id;新增 diagnose_lsx_invite 对齐种子

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-23 22:30:23 +08:00
parent d2d8e37080
commit dcb191ac3a
2 changed files with 132 additions and 1 deletions

View File

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

View File

@@ -31,7 +31,11 @@ def assert_invite_same_club(request, inviter_user, invitee_user=None):
'invite_guard 管事俱乐部不符 inviter=%s inviter_club=%s req_club=%s', 'invite_guard 管事俱乐部不符 inviter=%s inviter_club=%s req_club=%s',
getattr(inviter_user, 'UserUID', '?'), inviter_club, club_id, getattr(inviter_user, 'UserUID', '?'), inviter_club, club_id,
) )
return False, '邀请码不属于当前小程序俱乐部' # 文案带上两侧 club方便排查「种子 ClubID ≠ 小程序 X-Club-Id」
return False, (
f'邀请码不属于当前小程序俱乐部'
f'(邀请人归属={inviter_club or ""},当前小程序={club_id or ""}'
)
if invitee_user is not None: if invitee_user is not None:
invitee_club = resolve_invite_party_club(invitee_user, club_id) invitee_club = resolve_invite_party_club(invitee_user, club_id)