fix: 模板创建变量名; 客服模板/角色/权限 API
This commit is contained in:
@@ -1546,8 +1546,8 @@ class ShangjiaTianjiaMobanView(APIView):
|
|||||||
TemplateDesc=jieshao,
|
TemplateDesc=jieshao,
|
||||||
Price=jiage_decimal,
|
Price=jiage_decimal,
|
||||||
PublishedCount=0,
|
PublishedCount=0,
|
||||||
CommissionGrabEnabled=yongjin_qiangdan,
|
CommissionGrabEnabled=CommissionGrabEnabled,
|
||||||
CommissionPrice=yongjin_jiage,
|
CommissionPrice=CommissionPrice,
|
||||||
TitleID=cleaned_label_id
|
TitleID=cleaned_label_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ def staff_can_access_order(member, order_id, perm_all='order_view_all', perm_sel
|
|||||||
|
|
||||||
def proxy_merchant_order_view(request, member, view_class, perm_code):
|
def proxy_merchant_order_view(request, member, view_class, perm_code):
|
||||||
"""子客服通过商家 User 代理调用现有 View.post。"""
|
"""子客服通过商家 User 代理调用现有 View.post。"""
|
||||||
|
return proxy_as_merchant_user(request, member, view_class, perm_code)
|
||||||
|
|
||||||
|
|
||||||
|
def proxy_as_merchant_user(request, member, view_class, perm_code):
|
||||||
|
"""子客服以商家身份代理调用任意商家 View(订单/配置等)。"""
|
||||||
if not member_has_perm(member, perm_code):
|
if not member_has_perm(member, perm_code):
|
||||||
raise StaffAuthError(403, f'无权限: {perm_code}')
|
raise StaffAuthError(403, f'无权限: {perm_code}')
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ from django.urls import path
|
|||||||
from merchant_ops.views_manage import (
|
from merchant_ops.views_manage import (
|
||||||
StaffInviteCreateView, StaffInviteListView, StaffInviteRevokeView,
|
StaffInviteCreateView, StaffInviteListView, StaffInviteRevokeView,
|
||||||
StaffMemberListView, StaffMemberUpdateRoleView, StaffMemberRemoveView,
|
StaffMemberListView, StaffMemberUpdateRoleView, StaffMemberRemoveView,
|
||||||
StaffMemberDisableView, StaffRoleListView, StaffRoleSetPermsView,
|
StaffMemberDisableView, StaffMemberUpdatePermsView,
|
||||||
|
StaffRoleListView, StaffRoleCreateView, StaffRoleSetPermsView,
|
||||||
StaffWalletAllocateView, StaffWalletLedgerView, StaffAuditListView,
|
StaffWalletAllocateView, StaffWalletLedgerView, StaffAuditListView,
|
||||||
StaffRankView,
|
StaffRankView,
|
||||||
)
|
)
|
||||||
@@ -13,6 +14,10 @@ from merchant_ops.views_orders import (
|
|||||||
StaffProductTypesView, StaffSettleView, StaffCancelView, StaffRefundView,
|
StaffProductTypesView, StaffSettleView, StaffCancelView, StaffRefundView,
|
||||||
StaffPenaltyApplyView, StaffPenaltyManageView, StaffChangePlayerView,
|
StaffPenaltyApplyView, StaffPenaltyManageView, StaffChangePlayerView,
|
||||||
)
|
)
|
||||||
|
from merchant_ops.views_templates import (
|
||||||
|
StaffTemplateListView, StaffTemplateCreateView, StaffTemplateUpdateView,
|
||||||
|
StaffTemplateDeleteView, StaffLinkGenerateView, StaffLinkListView,
|
||||||
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# 子客服
|
# 子客服
|
||||||
@@ -24,9 +29,11 @@ urlpatterns = [
|
|||||||
path('invite/revoke', StaffInviteRevokeView.as_view()),
|
path('invite/revoke', StaffInviteRevokeView.as_view()),
|
||||||
path('member/list', StaffMemberListView.as_view()),
|
path('member/list', StaffMemberListView.as_view()),
|
||||||
path('member/update-role', StaffMemberUpdateRoleView.as_view()),
|
path('member/update-role', StaffMemberUpdateRoleView.as_view()),
|
||||||
|
path('member/update-perms', StaffMemberUpdatePermsView.as_view()),
|
||||||
path('member/remove', StaffMemberRemoveView.as_view()),
|
path('member/remove', StaffMemberRemoveView.as_view()),
|
||||||
path('member/disable', StaffMemberDisableView.as_view()),
|
path('member/disable', StaffMemberDisableView.as_view()),
|
||||||
path('role/list', StaffRoleListView.as_view()),
|
path('role/list', StaffRoleListView.as_view()),
|
||||||
|
path('role/create', StaffRoleCreateView.as_view()),
|
||||||
path('role/set-perms', StaffRoleSetPermsView.as_view()),
|
path('role/set-perms', StaffRoleSetPermsView.as_view()),
|
||||||
path('wallet/allocate', StaffWalletAllocateView.as_view()),
|
path('wallet/allocate', StaffWalletAllocateView.as_view()),
|
||||||
path('wallet/ledger', StaffWalletLedgerView.as_view()),
|
path('wallet/ledger', StaffWalletLedgerView.as_view()),
|
||||||
@@ -43,4 +50,11 @@ urlpatterns = [
|
|||||||
path('order/penalty-apply', StaffPenaltyApplyView.as_view()),
|
path('order/penalty-apply', StaffPenaltyApplyView.as_view()),
|
||||||
path('order/penalty-manage', StaffPenaltyManageView.as_view()),
|
path('order/penalty-manage', StaffPenaltyManageView.as_view()),
|
||||||
path('order/change-player', StaffChangePlayerView.as_view()),
|
path('order/change-player', StaffChangePlayerView.as_view()),
|
||||||
|
# 子客服模板 / 链接(独立路径,内部代理商家逻辑 + 权限校验)
|
||||||
|
path('template/list', StaffTemplateListView.as_view()),
|
||||||
|
path('template/create', StaffTemplateCreateView.as_view()),
|
||||||
|
path('template/update', StaffTemplateUpdateView.as_view()),
|
||||||
|
path('template/delete', StaffTemplateDeleteView.as_view()),
|
||||||
|
path('link/generate', StaffLinkGenerateView.as_view()),
|
||||||
|
path('link/list', StaffLinkListView.as_view()),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -252,6 +252,72 @@ class StaffRoleSetPermsView(APIView):
|
|||||||
return _err(e)
|
return _err(e)
|
||||||
|
|
||||||
|
|
||||||
|
class StaffRoleCreateView(APIView):
|
||||||
|
"""商家自定义角色(自由勾选权限)。"""
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
try:
|
||||||
|
mid = request.user.UserUID
|
||||||
|
ensure_owner_merchant(mid, request.user)
|
||||||
|
ensure_merchant_roles(mid)
|
||||||
|
role_name = (request.data.get('role_name') or '').strip()
|
||||||
|
if not role_name:
|
||||||
|
return Response({'code': 400, 'msg': '角色名称不能为空', 'data': None})
|
||||||
|
role_code = (request.data.get('role_code') or '').strip()
|
||||||
|
if not role_code:
|
||||||
|
role_code = 'CUSTOM_' + secrets.token_hex(3).upper()
|
||||||
|
if MerchantStaffRole.query.filter(merchant_id=mid, role_code=role_code).exists():
|
||||||
|
return Response({'code': 400, 'msg': '角色码已存在', 'data': None})
|
||||||
|
permissions = request.data.get('permissions', [])
|
||||||
|
role = MerchantStaffRole.objects.create(
|
||||||
|
club_id='xq',
|
||||||
|
merchant_id=mid,
|
||||||
|
role_code=role_code,
|
||||||
|
role_name=role_name,
|
||||||
|
is_system=False,
|
||||||
|
sort_order=50,
|
||||||
|
status=1,
|
||||||
|
)
|
||||||
|
valid = set(MerchantStaffPermission.query.filter(status=1).values_list('perm_code', flat=True))
|
||||||
|
for p in permissions:
|
||||||
|
if p in valid:
|
||||||
|
MerchantStaffRolePermission.objects.create(role=role, perm_code=p)
|
||||||
|
audit_owner(mid, mid, 'ROLE_CREATE', request, resource_id=role.id)
|
||||||
|
return Response({'code': 0, 'msg': '创建成功', 'data': {'id': role.id, 'role_code': role.role_code}})
|
||||||
|
except Exception as e:
|
||||||
|
return _err(e)
|
||||||
|
|
||||||
|
|
||||||
|
class StaffMemberUpdatePermsView(APIView):
|
||||||
|
"""成员级权限加减(覆盖角色默认权限)。"""
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
try:
|
||||||
|
mid = request.user.UserUID
|
||||||
|
ensure_owner_merchant(mid, request.user)
|
||||||
|
member_id = request.data.get('member_id')
|
||||||
|
overrides = request.data.get('overrides', [])
|
||||||
|
m = MerchantStaffMember.query.get(id=member_id, merchant_id=mid, status=MEMBER_STATUS_ACTIVE)
|
||||||
|
MerchantStaffMemberPermission.query.filter(member=m).delete()
|
||||||
|
valid = set(MerchantStaffPermission.query.filter(status=1).values_list('perm_code', flat=True))
|
||||||
|
for item in overrides:
|
||||||
|
if isinstance(item, dict):
|
||||||
|
code = item.get('perm_code')
|
||||||
|
granted = bool(item.get('granted', True))
|
||||||
|
else:
|
||||||
|
code = item
|
||||||
|
granted = True
|
||||||
|
if code not in valid:
|
||||||
|
continue
|
||||||
|
MerchantStaffMemberPermission.objects.create(member=m, perm_code=code, granted=granted)
|
||||||
|
audit_owner(mid, mid, 'MEMBER_SET_PERMS', request, resource_id=member_id)
|
||||||
|
return Response({'code': 0, 'msg': '成员权限已更新', 'data': {'permissions': list(get_member_permissions(m))}})
|
||||||
|
except Exception as e:
|
||||||
|
return _err(e)
|
||||||
|
|
||||||
|
|
||||||
class StaffWalletAllocateView(APIView):
|
class StaffWalletAllocateView(APIView):
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
|||||||
89
merchant_ops/views_templates.py
Normal file
89
merchant_ops/views_templates.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
"""子客服专用:派单模板 / 链接(代理商家 config 接口,校验权限,不修改原 /peizhi/*)。"""
|
||||||
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
|
from config.views import (
|
||||||
|
ShangjiaMobanListView,
|
||||||
|
ShangjiaTianjiaMobanView,
|
||||||
|
ShangjiaGengxinMobanView,
|
||||||
|
ShangjiaShanchuMobanView,
|
||||||
|
ShangjiaGenerateLinkView,
|
||||||
|
ShangjiaLianjieListView,
|
||||||
|
)
|
||||||
|
from merchant_ops.helpers import proxy_as_merchant_user
|
||||||
|
from merchant_ops.services.authz import StaffAuthError, get_active_staff_member, member_has_perm
|
||||||
|
from merchant_ops.views_manage import _err
|
||||||
|
|
||||||
|
|
||||||
|
def _require_staff(request):
|
||||||
|
member = get_active_staff_member(request.user)
|
||||||
|
if not member:
|
||||||
|
raise StaffAuthError(403, '非有效子客服')
|
||||||
|
return member
|
||||||
|
|
||||||
|
|
||||||
|
class StaffTemplateListView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
try:
|
||||||
|
member = _require_staff(request)
|
||||||
|
return proxy_as_merchant_user(request, member, ShangjiaMobanListView, 'template_manage')
|
||||||
|
except Exception as e:
|
||||||
|
return _err(e)
|
||||||
|
|
||||||
|
|
||||||
|
class StaffTemplateCreateView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
try:
|
||||||
|
member = _require_staff(request)
|
||||||
|
return proxy_as_merchant_user(request, member, ShangjiaTianjiaMobanView, 'template_manage')
|
||||||
|
except Exception as e:
|
||||||
|
return _err(e)
|
||||||
|
|
||||||
|
|
||||||
|
class StaffTemplateUpdateView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
try:
|
||||||
|
member = _require_staff(request)
|
||||||
|
return proxy_as_merchant_user(request, member, ShangjiaGengxinMobanView, 'template_manage')
|
||||||
|
except Exception as e:
|
||||||
|
return _err(e)
|
||||||
|
|
||||||
|
|
||||||
|
class StaffTemplateDeleteView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
try:
|
||||||
|
member = _require_staff(request)
|
||||||
|
return proxy_as_merchant_user(request, member, ShangjiaShanchuMobanView, 'template_manage')
|
||||||
|
except Exception as e:
|
||||||
|
return _err(e)
|
||||||
|
|
||||||
|
|
||||||
|
class StaffLinkGenerateView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
try:
|
||||||
|
member = _require_staff(request)
|
||||||
|
return proxy_as_merchant_user(request, member, ShangjiaGenerateLinkView, 'order_dispatch')
|
||||||
|
except Exception as e:
|
||||||
|
return _err(e)
|
||||||
|
|
||||||
|
|
||||||
|
class StaffLinkListView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
try:
|
||||||
|
member = _require_staff(request)
|
||||||
|
return proxy_as_merchant_user(request, member, ShangjiaLianjieListView, 'order_dispatch')
|
||||||
|
except Exception as e:
|
||||||
|
return _err(e)
|
||||||
Reference in New Issue
Block a user