fix: 打手注册支持默认邀请码回退,修复扫码注册管事重复创建
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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'# 商户密钥,支付功能需要紧急
|
||||
|
||||
95
utils/dashou_register_service.py
Normal file
95
utils/dashou_register_service.py
Normal file
@@ -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)),
|
||||
)
|
||||
145
yonghu/views.py
145
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
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user