Files
Django/merchant_ops/views_orders.py

300 lines
11 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""子客服专用订单接口(不修改商家原接口)。"""
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 merchant_ops.models import MerchantOrderDispatch
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()
from orders.services.merchant_order_stats import build_merchant_order_stats
stats_qs = staff_order_ext_qs(member, None)
stats_qs = staff_apply_order_filters(stats_qs, data)
order_stats = build_merchant_order_stats(stats_qs)
can_finance = member_has_perm(member, 'finance_view')
if not can_finance:
for k in list(order_stats.keys()):
if k.endswith('_amount'):
order_stats[k] = '0.00'
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': order_stats['pending_count'],
'pending_amount': order_stats['pending_amount'] if can_finance else '0.00',
'order_stats': order_stats,
'can_view_finance': can_finance,
'view_scope': 'all' if staff_can_view_all_orders(member) else 'self',
},
})
except Exception as e:
return _err(e)
class StaffOrderStatsView(APIView):
"""子客服/老板视角订单统计 POST /yonghu/merchant-staff/order/stats"""
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 or {}
from orders.services.merchant_order_stats import build_merchant_order_stats, filter_by_staff_member
from orders.models import MerchantOrderExt
filter_payload = dict(data)
filter_payload['_merchant_id_filter'] = member.merchant_id
qs = MerchantOrderExt.query.filter(
MerchantID=member.merchant_id,
).select_related('Order')
if not staff_can_view_all_orders(member):
own_ids = list(
MerchantOrderDispatch.query.filter(staff_member_id=member.id).values_list('order_id', flat=True)
)
qs = qs.filter(Order__OrderID__in=own_ids)
elif data.get('staff_member_id'):
qs = filter_by_staff_member(qs, member.merchant_id, data.get('staff_member_id'))
qs = staff_apply_order_filters(qs, filter_payload)
order_stats = build_merchant_order_stats(qs)
can_finance = member_has_perm(member, 'finance_view')
if not can_finance:
for k in list(order_stats.keys()):
if k.endswith('_amount'):
order_stats[k] = '0.00'
return Response({
'code': 0,
'msg': '成功',
'data': {
'order': order_stats,
'can_view_finance': can_finance,
},
})
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)