From d22b265e58d78c13cd129a4ab3e0b9bc4d2f07eb Mon Sep 17 00:00:00 2001 From: XingQue Date: Thu, 2 Jul 2026 13:59:11 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=89=93=E6=89=8B=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=BB=98=E8=AE=A4=E9=82=80=E8=AF=B7=E7=A0=81?= =?UTF-8?q?=E5=9B=9E=E9=80=80=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=89=AB=E7=A0=81?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E7=AE=A1=E4=BA=8B=E9=87=8D=E5=A4=8D=E5=88=9B?= =?UTF-8?q?=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- a_long_dianjing/settings.py | 5 ++ utils/dashou_register_service.py | 95 ++++++++++++++++++++ yonghu/views.py | 145 +++++++------------------------ 3 files changed, 130 insertions(+), 115 deletions(-) create mode 100644 utils/dashou_register_service.py diff --git a/a_long_dianjing/settings.py b/a_long_dianjing/settings.py index 5d9a703..a8ace3c 100644 --- a/a_long_dianjing/settings.py +++ b/a_long_dianjing/settings.py @@ -275,6 +275,11 @@ WEIXIN_TEMPLATE_BATCH_SIZE = 100 # 每批发送数量 WEIXIN_BROADCAST_ENABLED = True # 服务号订单广播总开关 WEIXIN_BROADCAST_WORKERS = 30 # Celery 任务内并发推送线程数(勿过大,避免触发微信频控) +# 打手无邀请码一键注册(须与小程序 default-invite-code.js 保持一致) +DASHOU_DEFAULT_INVITE_CODE = '0000008U3Ck4267NmxuY' +# 默认邀请码在库中查不到时,回退到该管事 yonghuid(请确保该账号在库中存在且为管事) +DASHOU_DEFAULT_GUANSHI_YONGHUID = '0000008' + WEIXIN_MCHID = '1746784529' # 商户号,支付功能需要紧急 WEIXIN_SHANGHUMIYAO = 'thgnfbdyhd4536dbvgf7dgfhcvdgfh58'# 商户密钥,支付功能需要紧急 diff --git a/utils/dashou_register_service.py b/utils/dashou_register_service.py new file mode 100644 index 0000000..76f3d4e --- /dev/null +++ b/utils/dashou_register_service.py @@ -0,0 +1,95 @@ +""" +打手注册共用逻辑:邀请码解析、创建打手、管事邀请统计。 +""" +import logging + +from django.conf import settings +from django.db import transaction + +from yonghu.models import UserDashou, UserGuanshi + +logger = logging.getLogger('yonghu.dashouzhuce') + + +def get_default_dashou_invite_code(): + return getattr(settings, 'DASHOU_DEFAULT_INVITE_CODE', '').strip() + + +def resolve_guanshi_for_dashou_register(invite_code): + """ + 根据邀请码查找管事;无邀请码时使用默认码;默认码查不到时按平台管事 yonghuid 回退。 + 返回 (guanshi_profile, error_message) + """ + code = (invite_code or '').strip() + default_code = get_default_dashou_invite_code() + if not code: + code = default_code + if not code: + return None, '邀请码不能为空' + if len(code) > 100: + return None, '邀请码长度超过限制' + + guanshi = UserGuanshi.objects.select_related('user').filter(yaoqingma=code).first() + if guanshi: + return guanshi, None + + if default_code and code == default_code: + fallback_uid = getattr(settings, 'DASHOU_DEFAULT_GUANSHI_YONGHUID', '').strip() + if fallback_uid: + guanshi = UserGuanshi.objects.select_related('user').filter( + user__yonghuid=fallback_uid, + ).first() + if guanshi: + if guanshi.yaoqingma != code: + UserGuanshi.objects.filter(pk=guanshi.pk).update(yaoqingma=code) + guanshi.refresh_from_db() + logger.info('默认邀请码回退到平台管事 yonghuid=%s', fallback_uid) + return guanshi, None + + return None, '邀请码无效或不存在' + + +def create_dashou_for_user(user_main, guanshi_profile): + """为已登录用户创建打手身份,并更新管事邀请统计。返回 dashou_profile。""" + try: + return user_main.dashou_profile + except UserDashou.DoesNotExist: + pass + + guanshi_yonghuid = guanshi_profile.user.yonghuid + with transaction.atomic(): + dashou_profile = UserDashou.objects.create( + user=user_main, + nicheng='大手子', + chenghao='普通大手', + yaoqingren=guanshi_yonghuid, + jifen=5, + ) + locked_guanshi = UserGuanshi.objects.select_for_update().get(pk=guanshi_profile.pk) + locked_guanshi.yaogingshuliang += 1 + locked_guanshi.save(update_fields=['yaogingshuliang']) + + try: + from decimal import Decimal + from houtai.utils import update_guanshi_daily_by_action + update_guanshi_daily_by_action( + yonghuid=guanshi_yonghuid, + action=1, + amount=Decimal('0.00'), + ) + except Exception as stat_err: + logger.warning('管事每日统计更新失败(邀请打手):%s', stat_err) + + return dashou_profile + + +def ensure_guanshi_profile_for_user(user_main): + """扫码注册流程:若用户尚无管事身份则创建(已存在则跳过)。""" + if UserGuanshi.objects.filter(user=user_main).exists(): + return UserGuanshi.objects.get(user=user_main) + + from utils.yaoqingma_utils import chuangjianYaoqingma + return UserGuanshi.objects.create( + user=user_main, + yaoqingma=chuangjianYaoqingma(str(user_main.yonghuid)), + ) diff --git a/yonghu/views.py b/yonghu/views.py index 82f47c8..8341a36 100644 --- a/yonghu/views.py +++ b/yonghu/views.py @@ -1370,22 +1370,20 @@ class DashouZhuceView(APIView): yonghuid = getattr(current_user, 'yonghuid', '') try: - # 1. 获取并验证邀请码参数 - yaoqingma = request.data.get('inviteCode') - if not yaoqingma: - return Response({ - 'code': 400, - 'message': '邀请码不能为空', - 'data': None - }, status=status.HTTP_400_BAD_REQUEST) + from utils.dashou_register_service import ( + create_dashou_for_user, + resolve_guanshi_for_dashou_register, + ) - yaoqingma = yaoqingma.strip() - if len(yaoqingma) > 100: + # 1. 解析邀请码(支持无邀请码走默认码) + yaoqingma = request.data.get('inviteCode', '') + guanshi_profile, invite_err = resolve_guanshi_for_dashou_register(yaoqingma) + if invite_err: return Response({ - 'code': 400, - 'message': '邀请码长度超过限制', + 'code': 404, + 'message': invite_err, 'data': None - }, status=status.HTTP_400_BAD_REQUEST) + }, status=status.HTTP_404_NOT_FOUND) # 2. 检查用户是否已是打手 (使用反向查询,性能最优) try: @@ -1396,54 +1394,10 @@ class DashouZhuceView(APIView): # 用户不是打手,继续注册流程 pass - # 3. 根据邀请码查找对应的管事 - try: - guanshi_profile = UserGuanshi.objects.select_related('user').get(yaoqingma=yaoqingma) - except UserGuanshi.DoesNotExist: - return Response({ - 'code': 404, - 'message': '邀请码无效或不存在', - 'data': None - }, status=status.HTTP_404_NOT_FOUND) + # 3. 创建打手身份 + dashou_profile = create_dashou_for_user(current_user, guanshi_profile) - # 4. 验证管事状态 - '''if guanshi_profile.zhuangtai != 1: - return Response({ - 'code': 403, - 'message': '该邀请码对应的管事账号已被禁用', - 'data': None - }, status=status.HTTP_403_FORBIDDEN)''' - - # 5. 核心:在数据库事务中创建用户的所有身份 - with transaction.atomic(): - guanshi_yonghuid = guanshi_profile.user.yonghuid - - dashou_profile = UserDashou.objects.create( - user=current_user, - nicheng='大手子', - chenghao='普通大手', - yaoqingren=guanshi_yonghuid, - jifen = 5 - ) - - locked_guanshi = UserGuanshi.objects.select_for_update().get(pk=guanshi_profile.pk) - locked_guanshi.yaogingshuliang += 1 - locked_guanshi.save() - - # 管事每日统计(邀请打手)— 失败不影响注册主流程 - try: - from decimal import Decimal - from houtai.utils import update_guanshi_daily_by_action - update_guanshi_daily_by_action( - yonghuid=guanshi_yonghuid, - action=1, - amount=Decimal('0.00') - ) - _dashou_zhuce_logger.info('管事每日统计更新成功(邀请打手):管事%s', guanshi_yonghuid) - except Exception as stat_err: - _dashou_zhuce_logger.warning('管事每日统计更新失败(邀请打手):%s', stat_err) - - # 6. 注册成功,返回信息 + # 4. 注册成功,返回信息 fanhui_data = self.zhuangbeiFanhuiShuju(dashou_profile, current_user, is_new=True) return Response({ 'code': 200, @@ -1504,6 +1458,9 @@ class DashouZhuceView(APIView): }) data['clumber'] = huiyuan_goumai_list + data['dashoustatus'] = 1 + data['guanshistatus'] = 1 if UserGuanshi.objects.filter(user=current_user).exists() else 0 + data['shangjiastatus'] = 1 if UserShangjia.objects.filter(user=current_user).exists() else 0 return data @@ -6590,6 +6547,12 @@ class WechatLoginAndDashouRegisterView(APIView): 处理微信登录并注册打手请求 """ try: + from utils.dashou_register_service import ( + create_dashou_for_user, + ensure_guanshi_profile_for_user, + resolve_guanshi_for_dashou_register, + ) + # 1. 获取并验证参数 code = request.data.get('code', '').strip() yaoqingma = request.data.get('inviteCode', '').strip() @@ -6601,17 +6564,11 @@ class WechatLoginAndDashouRegisterView(APIView): 'data': None }, status=status.HTTP_400_BAD_REQUEST) - if not yaoqingma: + guanshi_profile, invite_err = resolve_guanshi_for_dashou_register(yaoqingma) + if invite_err: return Response({ 'code': 2, - 'msg': '邀请码不能为空', - 'data': None - }, status=status.HTTP_400_BAD_REQUEST) - - if len(yaoqingma) > 100: - return Response({ - 'code': 3, - 'msg': '邀请码长度超过限制', + 'msg': invite_err, 'data': None }, status=status.HTTP_400_BAD_REQUEST) @@ -6639,61 +6596,19 @@ class WechatLoginAndDashouRegisterView(APIView): # 新用户:创建老板扩展表 UserBoss.objects.create(user=user_main, nickname='微信用户') - # 4.2 验证邀请码对应的管事(注册逻辑) - try: - # 使用select_related获取管事及其关联的主表用户信息 - guanshi_profile = UserGuanshi.objects.select_related('user').get(yaoqingma=yaoqingma) - except UserGuanshi.DoesNotExist: - # 邀请码无效,但用户已登录,可以返回登录成功但注册失败 - # 这里我们继续执行,但只返回登录信息 - return self.fanhuiZhihouDengluXinxi(user_main, yaoqingma_wuxiao=True) - # 验证管事状态 if guanshi_profile.zhuangtai != 1: - # 管事账号已被禁用 return self.fanhuiZhihouDengluXinxi(user_main, guanshi_jinyong=True) # 4.3 检查用户是否已是打手 dashou_exists = UserDashou.objects.filter(user=user_main).exists() if dashou_exists: - # 用户已是打手,直接返回信息 dashou_profile = UserDashou.objects.get(user=user_main) return self.fanhuiDengluZhuceshuju(user_main, dashou_profile) - # 4.4 核心:为用户创建所有身份(打手、商家、管事) - guanshi_yonghuid = guanshi_profile.user.yonghuid - - # 创建打手扩展表 - dashou_profile = UserDashou.objects.create( - user=user_main, - nicheng='大手子', - chenghao='普通大手', - yaoqingren=guanshi_yonghuid, - jifen = 5 - # 其他字段使用模型默认值 - ) - - # 创建商家扩展表 - # 商家昵称需要唯一,这里用 用户ID + "的店铺" 来确保唯一性 - '''shangjia_nicheng = f"{user_main.yonghuid}的店铺" - UserShangjia.objects.create( - user=user_main, - nicheng=shangjia_nicheng, - # 其他字段使用默认值 - )''' - - # 创建管事扩展表 - guanshi_yaoqingma = chuangjianYaoqingma(str(user_main.yonghuid)) - new_guanshi_profile = UserGuanshi.objects.create( - user=user_main, - yaoqingma=guanshi_yaoqingma, - # 其他字段使用默认值 - ) - - # 更新原管事的邀请数量 - locked_guanshi = UserGuanshi.objects.select_for_update().get(pk=guanshi_profile.pk) - locked_guanshi.yaogingshuliang += 1 - locked_guanshi.save() + # 4.4 创建打手;扫码流程顺带开通管事(已存在则跳过) + dashou_profile = create_dashou_for_user(user_main, guanshi_profile) + ensure_guanshi_profile_for_user(user_main) # 5. 生成JWT token refresh = RefreshToken.for_user(user_main) @@ -6870,7 +6785,7 @@ class WechatLoginAndDashouRegisterView(APIView): msg = '登录成功' return Response({ - 'code': 0, + 'code': 5, 'msg': msg, 'data': response_data })