Files
Django/users/services/c_invite.py
XingQue ed627fa6f7 fix: 修复点单商品在多店铺间跳动
扫码绑店参数只消费一次,避免 Tab 返回反复换绑;一人多条脏绑定取最新并在换绑时清理,hqsp 稳定取当前店。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 02:53:34 +08:00

119 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""点单端老板推荐官:按推荐官 UserUID 绑定,店铺跟随。无邀请码。"""
from django.db import transaction
from django.db.models import F
from shop.models import Dianpu
from shop.services.shop_binding import (
clear_user_shop_binding,
get_user_shop_binding,
set_user_shop_binding,
)
from users.models import YonghuCYaoqing
from users.business_models import User
import logging
logger = logging.getLogger(__name__)
def get_or_create_c_yaoqing(user):
"""获取或创建用户的点单端推荐关系记录。"""
profile, _ = YonghuCYaoqing.objects.get_or_create(user=user)
return profile
def sync_shop_from_inviter(invitee_user, inviter_user):
"""
按推荐官店铺同步被推荐人店铺:
- 推荐官有正常店铺 → 被推荐人绑到同一店(一人一店)
- 推荐官无店铺 → 被推荐人解绑店铺(回落平台公共商品逻辑)
须在 transaction.atomic 内调用。
"""
inviter_binding = get_user_shop_binding(inviter_user)
if inviter_binding and inviter_binding.dianpu.zhuangtai == 1:
dianpu = Dianpu.objects.select_for_update().get(id=inviter_binding.dianpu_id)
changed, msg = set_user_shop_binding(invitee_user, dianpu)
return {'shop_synced': True, 'dianpu_id': dianpu.id, 'changed': changed, 'msg': msg}
old_id = clear_user_shop_binding(invitee_user)
return {
'shop_synced': False,
'dianpu_id': None,
'changed': bool(old_id),
'msg': '推荐官未绑定店铺,已解除店铺绑定' if old_id else '推荐官未绑定店铺',
}
def bind_c_inviter_by_uid(invitee_user, inviter_uid):
"""
用推荐官 UserUID 绑定/换绑,并同步店铺。
扫码参数yaoqingren / inviterUid不是邀请码
"""
uid = (inviter_uid or '').strip()
if not uid:
return {'code': 400, 'msg': '推荐官ID不能为空', 'data': None}
if len(uid) > 20:
return {'code': 400, 'msg': '推荐官ID格式错误', 'data': None}
try:
inviter = User.query.get(UserUID=uid)
except User.DoesNotExist:
return {'code': 404, 'msg': '推荐官不存在', 'data': None}
if inviter.UserUID == invitee_user.UserUID:
return {'code': 400, 'msg': '不能绑定自己为推荐官', 'data': None}
with transaction.atomic():
inviter_profile = get_or_create_c_yaoqing(inviter)
invitee_profile = get_or_create_c_yaoqing(invitee_user)
invitee_profile = YonghuCYaoqing.objects.select_for_update().get(pk=invitee_profile.pk)
inviter_profile = YonghuCYaoqing.objects.select_for_update().get(pk=inviter_profile.pk)
old_inviter_uid = (invitee_profile.yaoqingren or '').strip() or None
new_inviter_uid = inviter.UserUID
if old_inviter_uid == new_inviter_uid:
shop_info = sync_shop_from_inviter(invitee_user, inviter)
return {
'code': 200,
'msg': '已绑定该推荐官',
'data': {
'yaoqingren': new_inviter_uid,
'rebinding': False,
'shop': shop_info,
},
}
if old_inviter_uid:
old_p = (
YonghuCYaoqing.objects.select_for_update()
.filter(user__UserUID=old_inviter_uid)
.first()
)
if old_p and old_p.yaogingshuliang > 0:
old_p.yaogingshuliang = F('yaogingshuliang') - 1
old_p.save(update_fields=['yaogingshuliang', 'UpdateTime'])
inviter_profile.yaogingshuliang = F('yaogingshuliang') + 1
inviter_profile.save(update_fields=['yaogingshuliang', 'UpdateTime'])
invitee_profile.yaoqingren = new_inviter_uid
invitee_profile.save(update_fields=['yaoqingren', 'UpdateTime'])
shop_info = sync_shop_from_inviter(invitee_user, inviter)
logger.info(
'点单端推荐官绑定: invitee=%s inviter=%s old=%s shop=%s',
invitee_user.UserUID, new_inviter_uid, old_inviter_uid, shop_info,
)
return {
'code': 200,
'msg': '绑定成功' if not old_inviter_uid else '已换绑推荐官',
'data': {
'yaoqingren': new_inviter_uid,
'rebinding': bool(old_inviter_uid),
'shop': shop_info,
},
}