235 lines
8.7 KiB
Python
235 lines
8.7 KiB
Python
"""子客服专用订单接口(不修改商家原接口)。"""
|
||
import logging
|
||
|
||
from rest_framework import status
|
||
from rest_framework.permissions import IsAuthenticated
|
||
from rest_framework.response import Response
|
||
from rest_framework.views import APIView
|
||
|
||
from backend.utils import pick_order_id
|
||
from merchant_ops.helpers import proxy_merchant_order_view
|
||
from merchant_ops.services.authz import (
|
||
StaffAuthError, require_active_staff_member, member_has_perm, staff_order_read_perm,
|
||
)
|
||
from merchant_ops.services.order_query import (
|
||
staff_apply_order_filters,
|
||
staff_can_view_all_orders,
|
||
staff_order_ext_qs,
|
||
)
|
||
from merchant_ops.services.audit import audit_staff
|
||
from merchant_ops.services.dispatch import staff_dispatch_order
|
||
from merchant_ops.services.stats import bump_cancel_count, bump_penalty_count
|
||
from orders.models import MerchantOrderExt
|
||
from orders.views import (
|
||
ShangjiaDingdanXiangqingView, ShangjiaJiesuanView, ShangjiaChexiaoView,
|
||
ShangjiaTuikuanShenqingView, ShangjiaFakuanApplyView, ShangjiaFakuaiXiugaiView,
|
||
ZxsjghdsView, ShangpinLeixingView,
|
||
)
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def _require_staff(request):
|
||
return require_active_staff_member(request.user)
|
||
|
||
|
||
def _err(e):
|
||
if isinstance(e, StaffAuthError):
|
||
return Response({'code': e.code, 'msg': e.msg, 'data': None})
|
||
logger.exception(e)
|
||
return Response({'code': 500, 'msg': '服务器错误', 'data': None})
|
||
|
||
|
||
class StaffOrderListView(APIView):
|
||
"""
|
||
POST /yonghu/merchant-staff/order/list
|
||
- 有 order_view_all:该商家全部订单
|
||
- 否则:仅 merchant_order_dispatch 中 staff_member_id=本人的订单
|
||
"""
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def post(self, request):
|
||
try:
|
||
member = _require_staff(request)
|
||
if not member_has_perm(member, 'order_view_all') and not member_has_perm(member, 'order_view_self'):
|
||
raise StaffAuthError(403, '无订单查看权限')
|
||
|
||
data = request.data
|
||
zhuangtai_list = data.get('zhuangtai_list', [])
|
||
page = max(1, int(data.get('page', 1)))
|
||
page_size = min(100, max(1, int(data.get('page_size', 10))))
|
||
|
||
if not isinstance(zhuangtai_list, list) or not zhuangtai_list:
|
||
return Response({'code': 3, 'msg': '状态列表不能为空', 'data': None})
|
||
|
||
base_qs = staff_apply_order_filters(
|
||
staff_order_ext_qs(member, zhuangtai_list),
|
||
data,
|
||
)
|
||
|
||
pending_qs = staff_order_ext_qs(member, [8])
|
||
pending_count = pending_qs.count()
|
||
|
||
total_count = base_qs.count()
|
||
start = (page - 1) * page_size
|
||
page_qs = list(base_qs.order_by('-Order__CreateTime')[start:start + page_size])
|
||
|
||
from jituan.services.club_context import resolve_club_id_from_request
|
||
from orders.services.merchant_order_list_enrich import enrich_merchant_order_list_items
|
||
|
||
club_id = resolve_club_id_from_request(request)
|
||
order_list = enrich_merchant_order_list_items(page_qs, club_id=club_id)
|
||
|
||
return Response({
|
||
'code': 0,
|
||
'msg': '成功',
|
||
'data': {
|
||
'list': order_list,
|
||
'has_more': start + len(page_qs) < total_count,
|
||
'total': total_count,
|
||
'pending_count': pending_count,
|
||
'view_scope': 'all' if staff_can_view_all_orders(member) else 'self',
|
||
},
|
||
})
|
||
except Exception as e:
|
||
return _err(e)
|
||
|
||
|
||
class StaffOrderDetailView(APIView):
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def post(self, request):
|
||
try:
|
||
member = _require_staff(request)
|
||
if not member_has_perm(member, 'order_detail'):
|
||
raise StaffAuthError(403, '无权限')
|
||
resp = proxy_merchant_order_view(
|
||
request, member, ShangjiaDingdanXiangqingView, 'order_detail',
|
||
)
|
||
if resp.status_code == 200 and resp.data.get('code') == 0 and resp.data.get('data'):
|
||
from merchant_ops.services.order_enrich import enrich_order_detail_data
|
||
enrich_order_detail_data(resp.data['data'], pick_order_id(request.data))
|
||
return resp
|
||
except Exception as e:
|
||
return _err(e)
|
||
|
||
|
||
class StaffDispatchView(APIView):
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def post(self, request):
|
||
try:
|
||
member = _require_staff(request)
|
||
if not member_has_perm(member, 'order_dispatch'):
|
||
raise StaffAuthError(403, '无派单权限')
|
||
ok, payload = staff_dispatch_order(member, request.user, request.data)
|
||
if ok:
|
||
audit_staff(member, 'DISPATCH', request,
|
||
resource_id=payload.get('data', {}).get('dingdan_id'),
|
||
amount=request.data.get('jiage'))
|
||
code = payload.get('code', 500)
|
||
return Response(payload, status=status.HTTP_200_OK if code in (0, 200) else status.HTTP_400_BAD_REQUEST)
|
||
except Exception as e:
|
||
return _err(e)
|
||
|
||
|
||
class StaffProductTypesView(APIView):
|
||
"""商品类型 — 代理 sjspleixing"""
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def post(self, request):
|
||
try:
|
||
member = _require_staff(request)
|
||
perm = staff_order_read_perm(member)
|
||
if not perm:
|
||
raise StaffAuthError(403, '无权限查看商品类型')
|
||
return proxy_merchant_order_view(request, member, ShangpinLeixingView, perm)
|
||
except Exception as e:
|
||
return _err(e)
|
||
|
||
|
||
class StaffSettleView(APIView):
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def post(self, request):
|
||
try:
|
||
member = _require_staff(request)
|
||
resp = proxy_merchant_order_view(request, member, ShangjiaJiesuanView, 'order_settle')
|
||
if resp.data.get('code') in (0, 200):
|
||
audit_staff(member, 'SETTLE', request, resource_id=pick_order_id(request.data))
|
||
return resp
|
||
except Exception as e:
|
||
return _err(e)
|
||
|
||
|
||
class StaffCancelView(APIView):
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def post(self, request):
|
||
try:
|
||
member = _require_staff(request)
|
||
resp = proxy_merchant_order_view(request, member, ShangjiaChexiaoView, 'order_cancel')
|
||
if resp.data.get('code') in (0, 200):
|
||
audit_staff(member, 'CANCEL', request, resource_id=pick_order_id(request.data))
|
||
bump_cancel_count(member.merchant_id, member)
|
||
return resp
|
||
except Exception as e:
|
||
return _err(e)
|
||
|
||
|
||
class StaffRefundView(APIView):
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def post(self, request):
|
||
try:
|
||
member = _require_staff(request)
|
||
resp = proxy_merchant_order_view(request, member, ShangjiaTuikuanShenqingView, 'order_refund_apply')
|
||
if resp.data.get('code') in (0, 200):
|
||
audit_staff(member, 'REFUND_APPLY', request, resource_id=pick_order_id(request.data))
|
||
return resp
|
||
except Exception as e:
|
||
return _err(e)
|
||
|
||
|
||
class StaffPenaltyApplyView(APIView):
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def post(self, request):
|
||
try:
|
||
member = _require_staff(request)
|
||
resp = proxy_merchant_order_view(request, member, ShangjiaFakuanApplyView, 'penalty_apply')
|
||
if resp.data.get('code') in (0, 200):
|
||
audit_staff(member, 'PENALTY_APPLY', request, resource_id=pick_order_id(request.data))
|
||
bump_penalty_count(member.merchant_id, member)
|
||
return resp
|
||
except Exception as e:
|
||
return _err(e)
|
||
|
||
|
||
class StaffPenaltyManageView(APIView):
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def post(self, request):
|
||
try:
|
||
member = _require_staff(request)
|
||
resp = proxy_merchant_order_view(request, member, ShangjiaFakuaiXiugaiView, 'penalty_manage')
|
||
if resp.data.get('code') in (0, 200):
|
||
audit_staff(member, 'PENALTY_MANAGE', request, resource_id=pick_order_id(request.data))
|
||
return resp
|
||
except Exception as e:
|
||
return _err(e)
|
||
|
||
|
||
class StaffChangePlayerView(APIView):
|
||
permission_classes = [IsAuthenticated]
|
||
|
||
def post(self, request):
|
||
try:
|
||
member = _require_staff(request)
|
||
resp = proxy_merchant_order_view(request, member, ZxsjghdsView, 'order_change_player')
|
||
if resp.data.get('code') in (0, 200):
|
||
audit_staff(member, 'CHANGE_PLAYER', request, resource_id=pick_order_id(request.data))
|
||
return resp
|
||
except Exception as e:
|
||
return _err(e)
|