"""子客服专用订单接口(不修改商家原接口)。""" 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, get_active_staff_member, member_has_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.order_enrich import staff_order_list_item 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): member = get_active_staff_member(request.user) if not member: raise StaffAuthError(403, '非有效子客服') return member 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 = base_qs.order_by('-Order__CreateTime')[start:start + page_size] order_list = [staff_order_list_item(ext) for ext in page_qs] return Response({ 'code': 0, 'msg': '成功', 'data': { 'list': order_list, 'has_more': len(page_qs) == page_size and start + page_size < 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) if not member_has_perm(member, 'order_dispatch'): raise StaffAuthError(403, '无权限') return proxy_merchant_order_view(request, member, ShangpinLeixingView, 'order_dispatch') 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)