商家订单列表支持时间段筛选并修正分页has_more
This commit is contained in:
@@ -1,10 +1,9 @@
|
|||||||
"""子客服订单查询:按权限隔离,不返回商家全量(除非 order_view_all)。"""
|
"""子客服订单查询:按权限隔离,不返回商家全量(除非 order_view_all)。"""
|
||||||
from django.db.models import Q
|
from backend.utils import fmt_datetime
|
||||||
|
|
||||||
from backend.utils import fmt_datetime, pick_leixing_id
|
|
||||||
from merchant_ops.models import MerchantOrderDispatch
|
from merchant_ops.models import MerchantOrderDispatch
|
||||||
from merchant_ops.services.authz import member_has_perm
|
from merchant_ops.services.authz import member_has_perm
|
||||||
from orders.models import MerchantOrderExt
|
from orders.models import MerchantOrderExt
|
||||||
|
from orders.services.merchant_order_list_filters import apply_merchant_order_list_filters
|
||||||
|
|
||||||
|
|
||||||
def staff_can_view_all_orders(member):
|
def staff_can_view_all_orders(member):
|
||||||
@@ -27,18 +26,7 @@ def staff_order_ext_qs(member, zhuangtai_list=None):
|
|||||||
|
|
||||||
|
|
||||||
def staff_apply_order_filters(qs, data):
|
def staff_apply_order_filters(qs, data):
|
||||||
leixing_id = pick_leixing_id(data)
|
return apply_merchant_order_list_filters(qs, data)
|
||||||
keyword = str(data.get('keyword', '')).strip()
|
|
||||||
if leixing_id is not None:
|
|
||||||
qs = qs.filter(Order__ProductTypeID=leixing_id)
|
|
||||||
if keyword:
|
|
||||||
qs = qs.filter(
|
|
||||||
Q(Order__OrderID__exact=keyword)
|
|
||||||
| Q(Order__Description__icontains=keyword)
|
|
||||||
| Q(Order__Nickname__icontains=keyword)
|
|
||||||
| Q(Order__PlayerID__exact=keyword)
|
|
||||||
)
|
|
||||||
return qs
|
|
||||||
|
|
||||||
|
|
||||||
def staff_order_to_dict(ext):
|
def staff_order_to_dict(ext):
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class StaffOrderListView(APIView):
|
|||||||
'msg': '成功',
|
'msg': '成功',
|
||||||
'data': {
|
'data': {
|
||||||
'list': order_list,
|
'list': order_list,
|
||||||
'has_more': len(page_qs) == page_size and start + page_size < total_count,
|
'has_more': start + len(page_qs) < total_count,
|
||||||
'total': total_count,
|
'total': total_count,
|
||||||
'pending_count': pending_count,
|
'pending_count': pending_count,
|
||||||
'view_scope': 'all' if staff_can_view_all_orders(member) else 'self',
|
'view_scope': 'all' if staff_can_view_all_orders(member) else 'self',
|
||||||
|
|||||||
75
orders/services/merchant_order_list_filters.py
Normal file
75
orders/services/merchant_order_list_filters.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
"""商家订单列表通用筛选(商家老板接口 + 子客服列表共用)。"""
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from django.db.models import Q
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.utils.dateparse import parse_datetime
|
||||||
|
|
||||||
|
from backend.utils import pick_leixing_id
|
||||||
|
|
||||||
|
|
||||||
|
def _aware_dt(dt):
|
||||||
|
if dt is None:
|
||||||
|
return None
|
||||||
|
if timezone.is_naive(dt):
|
||||||
|
return timezone.make_aware(dt, timezone.get_current_timezone())
|
||||||
|
return dt
|
||||||
|
|
||||||
|
|
||||||
|
def parse_order_list_bound(value, is_end=False):
|
||||||
|
"""解析列表时间边界;仅日期时开始取 00:00:00,结束取 23:59:59。"""
|
||||||
|
if not value:
|
||||||
|
return None
|
||||||
|
raw = str(value).strip()
|
||||||
|
if not raw:
|
||||||
|
return None
|
||||||
|
if len(raw) <= 10:
|
||||||
|
try:
|
||||||
|
base = datetime.strptime(raw[:10], '%Y-%m-%d')
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
if is_end:
|
||||||
|
base = base.replace(hour=23, minute=59, second=59)
|
||||||
|
return _aware_dt(base)
|
||||||
|
dt = parse_datetime(raw.replace(' ', 'T', 1) if ' ' in raw and 'T' not in raw else raw)
|
||||||
|
if dt is None:
|
||||||
|
try:
|
||||||
|
base = datetime.strptime(raw[:19], '%Y-%m-%d %H:%M:%S')
|
||||||
|
return _aware_dt(base)
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
return _aware_dt(dt)
|
||||||
|
|
||||||
|
|
||||||
|
def apply_merchant_order_list_filters(qs, data):
|
||||||
|
"""在 MerchantOrderExt 查询集上应用类型/关键字/时间段筛选。"""
|
||||||
|
leixing_id = pick_leixing_id(data)
|
||||||
|
keyword = str(data.get('keyword', '')).strip()
|
||||||
|
waibu_dingdan_id = str(data.get('waibuDingdanId') or data.get('waibu_dingdan_id') or '').strip()
|
||||||
|
|
||||||
|
start_raw = data.get('start_time') or data.get('time_start') or data.get('create_time_start')
|
||||||
|
end_raw = data.get('end_time') or data.get('time_end') or data.get('create_time_end')
|
||||||
|
|
||||||
|
if leixing_id is not None:
|
||||||
|
qs = qs.filter(Order__ProductTypeID=leixing_id)
|
||||||
|
|
||||||
|
start_dt = parse_order_list_bound(start_raw, is_end=False)
|
||||||
|
end_dt = parse_order_list_bound(end_raw, is_end=True)
|
||||||
|
if start_dt and end_dt and start_dt > end_dt:
|
||||||
|
start_dt, end_dt = end_dt, start_dt
|
||||||
|
if start_dt:
|
||||||
|
qs = qs.filter(Order__CreateTime__gte=start_dt)
|
||||||
|
if end_dt:
|
||||||
|
qs = qs.filter(Order__CreateTime__lte=end_dt)
|
||||||
|
|
||||||
|
if waibu_dingdan_id:
|
||||||
|
qs = qs.filter(Order__ExternalOrderID__exact=waibu_dingdan_id)
|
||||||
|
elif keyword:
|
||||||
|
qs = qs.filter(
|
||||||
|
Q(Order__OrderID__exact=keyword)
|
||||||
|
| Q(Order__Description__icontains=keyword)
|
||||||
|
| Q(Order__Nickname__icontains=keyword)
|
||||||
|
| Q(Order__PlayerID__exact=keyword)
|
||||||
|
| Q(Order__ExternalOrderID__exact=keyword)
|
||||||
|
)
|
||||||
|
return qs
|
||||||
@@ -2058,12 +2058,7 @@ class ShangjiaDingdanHuoquView(APIView):
|
|||||||
page = max(1, int(data.get('page', 1)))
|
page = max(1, int(data.get('page', 1)))
|
||||||
page_size = min(100, max(1, int(data.get('page_size', 10))))
|
page_size = min(100, max(1, int(data.get('page_size', 10))))
|
||||||
|
|
||||||
# 🆕 商品类型筛选(兼容 leixing_id / ProductTypeID)
|
# 商品类型 / 关键字 / 时间段等见 apply_merchant_order_list_filters
|
||||||
leixing_id = pick_leixing_id(data)
|
|
||||||
|
|
||||||
# 🆕 模糊搜索关键字(支持订单ID、订单介绍、游戏昵称、打手ID、拼多多订单号)
|
|
||||||
keyword = data.get('keyword', '').strip()
|
|
||||||
waibu_dingdan_id = str(data.get('waibuDingdanId') or '').strip()
|
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
return Response({
|
return Response({
|
||||||
'code': 2,
|
'code': 2,
|
||||||
@@ -2080,6 +2075,8 @@ class ShangjiaDingdanHuoquView(APIView):
|
|||||||
}, status=status.HTTP_400_BAD_REQUEST)
|
}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
from orders.services.merchant_order_list_filters import apply_merchant_order_list_filters
|
||||||
|
|
||||||
# 4. 构建基础查询(该商家的所有订单)
|
# 4. 构建基础查询(该商家的所有订单)
|
||||||
base_qs = MerchantOrderExt.query.filter(
|
base_qs = MerchantOrderExt.query.filter(
|
||||||
MerchantID=yonghuid
|
MerchantID=yonghuid
|
||||||
@@ -2088,28 +2085,8 @@ class ShangjiaDingdanHuoquView(APIView):
|
|||||||
# 5. 状态过滤
|
# 5. 状态过滤
|
||||||
base_qs = base_qs.filter(Order__Status__in=zhuangtai_list)
|
base_qs = base_qs.filter(Order__Status__in=zhuangtai_list)
|
||||||
|
|
||||||
# 6. 商品类型筛选
|
# 6–7. 类型 / 关键字 / 时间段
|
||||||
if leixing_id is not None:
|
base_qs = apply_merchant_order_list_filters(base_qs, data)
|
||||||
base_qs = base_qs.filter(Order__ProductTypeID=leixing_id)
|
|
||||||
|
|
||||||
# 7. 模糊搜索(支持订单ID、订单介绍、游戏昵称、打手ID、拼多多订单号)
|
|
||||||
if waibu_dingdan_id:
|
|
||||||
base_qs = base_qs.filter(Order__ExternalOrderID__exact=waibu_dingdan_id)
|
|
||||||
elif keyword:
|
|
||||||
# 订单ID精确匹配(dingdan_id有唯一索引,先用精确匹配)
|
|
||||||
dingdan_id_match = Q(Order__OrderID__exact=keyword)
|
|
||||||
# 订单介绍模糊匹配
|
|
||||||
jieshao_match = Q(Order__Description__icontains=keyword)
|
|
||||||
# 游戏昵称模糊匹配
|
|
||||||
nicheng_match = Q(Order__Nickname__icontains=keyword)
|
|
||||||
# 打手ID精确匹配
|
|
||||||
dashou_match = Q(Order__PlayerID__exact=keyword)
|
|
||||||
# 拼多多订单号精确匹配
|
|
||||||
waibu_match = Q(Order__ExternalOrderID__exact=keyword)
|
|
||||||
|
|
||||||
base_qs = base_qs.filter(
|
|
||||||
dingdan_id_match | jieshao_match | nicheng_match | dashou_match | waibu_match
|
|
||||||
)
|
|
||||||
|
|
||||||
# 8. 计算待结算订单数量(状态为8)
|
# 8. 计算待结算订单数量(状态为8)
|
||||||
pending_count = MerchantOrderExt.query.filter(
|
pending_count = MerchantOrderExt.query.filter(
|
||||||
@@ -2131,7 +2108,7 @@ class ShangjiaDingdanHuoquView(APIView):
|
|||||||
|
|
||||||
# 11. 判断是否还有更多
|
# 11. 判断是否还有更多
|
||||||
current_page_count = len(current_page_orders)
|
current_page_count = len(current_page_orders)
|
||||||
has_more = current_page_count == page_size and end_index < total_count
|
has_more = start_index + current_page_count < total_count
|
||||||
|
|
||||||
return Response({
|
return Response({
|
||||||
'code': 0,
|
'code': 0,
|
||||||
|
|||||||
Reference in New Issue
Block a user