diff --git a/jituan/services/club_user.py b/jituan/services/club_user.py index 9c2ffcd..34db884 100644 --- a/jituan/services/club_user.py +++ b/jituan/services/club_user.py @@ -1,5 +1,5 @@ """用户所属俱乐部解析。""" -from django.db import IntegrityError +from django.db import IntegrityError, transaction from jituan.constants import CLUB_ID_DEFAULT from jituan.models import UserWxOpenid @@ -41,27 +41,52 @@ def resolve_invite_party_club(user, request_club_id=None): return None -def find_user_by_wx_openid(club_id, openid): - """按俱乐部 openid 绑定或 legacy OpenID/UserName 定位用户。""" +def _user_querysets(): + """兼容 gvsdsdk User.query 与 Django User.objects。""" from users.business_models import User - if club_id and openid: + seen = set() + for qs in (getattr(User, 'objects', None), getattr(User, 'query', None)): + if qs is None or id(qs) in seen: + continue + seen.add(id(qs)) + yield qs + + +def find_user_by_wx_openid(club_id, openid): + """按俱乐部 openid 绑定或 legacy UserName/OpenID 定位用户。""" + from users.business_models import User + + openid = (openid or '').strip() + if not openid: + return None + + if club_id: binding = UserWxOpenid.query.filter(club_id=club_id, openid=openid).first() if binding: - user = User.query.filter(UserUID=binding.yonghuid).first() + user = User.objects.filter(UserUID=binding.yonghuid).first() if not user: - user = User.objects.filter(UserUID=binding.yonghuid).first() + user = User.query.filter(UserUID=binding.yonghuid).first() if user: return user - user = User.query.filter(OpenID=openid).first() - if not user: - user = User.objects.filter(OpenID=openid).first() - if not user: - user = User.query.filter(UserName=openid).first() - if not user: - user = User.objects.filter(UserName=openid).first() - return user + binding_any = UserWxOpenid.query.filter(openid=openid).order_by('id').first() + if binding_any: + user = User.objects.filter(UserUID=binding_any.yonghuid).first() + if not user: + user = User.query.filter(UserUID=binding_any.yonghuid).first() + if user: + return user + + # 星之界等用户常 UserName=openid 且 OpenID 为空,优先按 UserName 查 + for manager in _user_querysets(): + user = manager.filter(UserName=openid).first() + if user: + return user + user = manager.filter(OpenID=openid).first() + if user: + return user + return None def ensure_wx_openid_binding(club_id, openid, user, unionid=''): @@ -95,23 +120,29 @@ def resolve_or_create_wx_user(club_id, openid, generate_uid, unionid=''): import uuid from users.business_models import User + openid = (openid or '').strip() + if not openid: + raise ValueError('openid 不能为空') + user = find_user_by_wx_openid(club_id, openid) if user: ensure_wx_openid_binding(club_id, openid, user, unionid) return user, False try: - user = User( - UserUUID=uuid.uuid4().bytes, - UserUID=generate_uid(), - UserName=openid, - OpenID=openid if club_id == CLUB_ID_DEFAULT else None, - UnionID=unionid or None, - ClubID='', - ) - user.save() - ensure_wx_openid_binding(club_id, openid, user, unionid) - return user, True + # 嵌套 savepoint:并发注册撞唯一键时只回滚创建,不污染外层 atomic + with transaction.atomic(): + user = User( + UserUUID=uuid.uuid4().bytes, + UserUID=generate_uid(), + UserName=openid, + OpenID=openid if club_id == CLUB_ID_DEFAULT else None, + UnionID=unionid or None, + ClubID='', + ) + user.save() + ensure_wx_openid_binding(club_id, openid, user, unionid) + return user, True except IntegrityError: user = find_user_by_wx_openid(club_id, openid) if not user: