diff --git a/merchant_ops/services/authz.py b/merchant_ops/services/authz.py index 63f3676..d4db512 100644 --- a/merchant_ops/services/authz.py +++ b/merchant_ops/services/authz.py @@ -33,9 +33,7 @@ def get_active_staff_member(user): def require_active_staff_member(user): - """子客服接口鉴权:区分老板误入、未绑定、禁用、移除等场景。""" - if is_merchant_owner(user): - raise StaffAuthError(403, '您是商家老板,请使用商家端原接口') + """子客服接口鉴权:区分未绑定、禁用、移除等场景(已是商家老板也可担任其他店子客服)。""" member = MerchantStaffMember.query.filter( staff_user_id=user.UserUID, ).select_related('role').order_by('-id').first() @@ -132,9 +130,21 @@ def resolve_owner_or_staff(request, perm_code=None): return 'staff', member.merchant_id, member, user.UserUID -def assert_not_merchant_when_bind(user): - if is_merchant_owner(user): - raise StaffAuthError(403, '您已是商家,无法成为子客服') +def assert_not_self_merchant_when_bind(user, invite_merchant_id): + """不能绑定为自己店铺的客服;可以是其他商家的子客服。""" + if invite_merchant_id is not None and str(user.UserUID) == str(invite_merchant_id): + raise StaffAuthError(403, '不能绑定为自己商家的客服') + + +def assert_can_bind_staff(user, invite_merchant_id=None): + assert_not_self_merchant_when_bind(user, invite_merchant_id) + existing = MerchantStaffMember.query.filter( + staff_user_id=user.UserUID, status=MEMBER_STATUS_ACTIVE + ).first() + if existing: + if invite_merchant_id and str(existing.merchant_id) == str(invite_merchant_id): + raise StaffAuthError(400, '您已是该商家客服') + raise StaffAuthError(403, '您已绑定其他商家客服,请先联系原商家解除后再绑定') def assert_no_active_staff_when_merchant_register(user): @@ -144,14 +154,6 @@ def assert_no_active_staff_when_merchant_register(user): raise StaffAuthError(403, '您当前是商家客服,请先联系商家解除后再认证商家') -def assert_can_bind_staff(user): - assert_not_merchant_when_bind(user) - if MerchantStaffMember.query.filter( - staff_user_id=user.UserUID, status=MEMBER_STATUS_ACTIVE - ).exists(): - raise StaffAuthError(403, '您已绑定商家客服,无法重复绑定') - - def get_owner_permissions(): return list(OWNER_ALL_PERMISSIONS) diff --git a/merchant_ops/views_staff.py b/merchant_ops/views_staff.py index 0349376..8992918 100644 --- a/merchant_ops/views_staff.py +++ b/merchant_ops/views_staff.py @@ -35,7 +35,6 @@ class StaffBindView(APIView): def post(self, request): try: - assert_can_bind_staff(request.user) invite_code = str(request.data.get('inviteCode') or request.data.get('invite_code') or '').strip() if not invite_code or invite_code == 'XQKF2026': return Response({'code': 400, 'msg': '请使用商家提供的一次性邀请码', 'data': None}) @@ -44,6 +43,7 @@ class StaffBindView(APIView): inv = MerchantStaffInvite.objects.select_for_update().get( invite_code=invite_code, status=INVITE_STATUS_UNUSED, ) + assert_can_bind_staff(request.user, invite_merchant_id=inv.merchant_id) if inv.expire_at and inv.expire_at < timezone.now(): inv.status = 3 inv.save(update_fields=['status'])