feat: 抢单池/组队角标计数多接口附加字段(兼容旧客户端)

This commit is contained in:
XingQue
2026-07-27 17:19:41 +08:00
parent 9b9203587c
commit 17b38d07a9
5 changed files with 152 additions and 3 deletions

View File

@@ -0,0 +1,100 @@
"""打手端角标计数:抢单池按类型待接单数、组队大厅待加入数。
仅供响应附加字段,不改变原有业务筛选逻辑。
"""
from __future__ import annotations
import logging
from django.db.models import Count
logger = logging.getLogger(__name__)
def grab_pool_type_pending_counts(club_id: str) -> dict[str, int]:
"""
与 /dingdan/ddhq 同口径Status in (1,7) + 抢单俱乐部范围,按 ProductTypeID 聚合。
返回 { \"类型id\": 数量 }key 一律 str方便 JSON / 前端。
"""
club_id = (club_id or '').strip()
if not club_id:
return {}
try:
from django.db.models import Q
from orders.models import Order
from jituan.services.order_grab_share import order_club_q_for_grabber
base = Q(Status__in=[1, 7]) & order_club_q_for_grabber(club_id)
rows = (
Order.query.filter(base)
.exclude(ProductTypeID__isnull=True)
.values('ProductTypeID')
.annotate(cnt=Count('OrderID'))
)
out = {}
for r in rows:
lid = r.get('ProductTypeID')
if lid is None:
continue
out[str(int(lid))] = int(r.get('cnt') or 0)
return out
except Exception as e:
logger.warning('grab_pool_type_pending_counts failed club=%s: %s', club_id, e)
return {}
def team_pending_count(club_id: str) -> int:
"""
与 /zudui/dating 同口径:本俱乐部招募中,且关联订单进行中(Status=2)。
"""
club_id = (club_id or '').strip()
if not club_id:
return 0
try:
from orders.models import Order, TeamRecruit
qs = TeamRecruit.query.filter(
club_id=club_id,
status=TeamRecruit.STATUS_RECRUITING,
)
oids = list(qs.values_list('order_id', flat=True)[:2000])
if not oids:
return 0
valid = set(
Order.query.filter(
OrderID__in=oids,
ClubID=club_id,
Status=2,
).values_list('OrderID', flat=True)
)
return sum(1 for oid in oids if oid in valid)
except Exception as e:
logger.warning('team_pending_count failed club=%s: %s', club_id, e)
return 0
def dashou_badge_fields(club_id: str) -> dict:
"""附加到接口 data 的角标字段(旧字段不受影响)。"""
type_counts = grab_pool_type_pending_counts(club_id)
total = int(sum(type_counts.values()))
return {
'type_pending_counts': type_counts,
'pool_pending_total': total,
'team_pending_count': int(team_pending_count(club_id)),
}
def attach_pending_to_leixing_list(leixing_list: list, type_counts: dict | None) -> list:
"""给类型 list 每项附加 pending_count不改动其它字段。"""
counts = type_counts or {}
out = []
for item in leixing_list or []:
if not isinstance(item, dict):
out.append(item)
continue
row = dict(item)
lid = row.get('id')
key = str(int(lid)) if lid is not None else ''
row['pending_count'] = int(counts.get(key) or 0)
out.append(row)
return out

View File

@@ -233,5 +233,8 @@ def build_fake_order_pool_response(request):
'current_page': page, 'current_page': page,
'page_size': page_size, 'page_size': page_size,
'total_pages': (total + page_size - 1) // page_size if page_size else 0, 'total_pages': (total + page_size - 1) // page_size if page_size else 0,
'type_pending_counts': {},
'pool_pending_total': 0,
'team_pending_count': 0,
}, },
}) })

View File

@@ -382,6 +382,13 @@ class DashouDingdanHuoquView(APIView):
has_more = (page * page_size) < total has_more = (page * page_size) < total
badge = {}
try:
from orders.services.dashou_badges import dashou_badge_fields
badge = dashou_badge_fields(club_id)
except Exception as e:
logger.warning('ddhq 角标附加失败: %s', e)
return Response({ return Response({
'code': 200, 'code': 200,
'msg': '获取成功', 'msg': '获取成功',
@@ -393,6 +400,7 @@ class DashouDingdanHuoquView(APIView):
'page_size': page_size, 'page_size': page_size,
'total_pages': (total + page_size - 1) // page_size, 'total_pages': (total + page_size - 1) // page_size,
'clumber': user_clumber, 'clumber': user_clumber,
**badge,
} }
}) })
@@ -762,13 +770,24 @@ class DashouDingdanHuoquView1(APIView):
if total_count == 0: if total_count == 0:
has_more = False has_more = False
badge = {}
try:
from jituan.services.club_context import resolve_effective_club_id
from orders.services.dashou_badges import dashou_badge_fields
badge = dashou_badge_fields(
resolve_effective_club_id(request, getattr(request, 'user', None))
)
except Exception as e:
logger.warning('dshqdingdan 角标附加失败: %s', e)
return Response({ return Response({
'code': 0, 'code': 0,
'msg': '成功', 'msg': '成功',
'data': { 'data': {
'list': order_list, 'list': order_list,
'has_more': has_more, 'has_more': has_more,
'total': total_count 'total': total_count,
**badge,
} }
}, status=status.HTTP_200_OK) }, status=status.HTTP_200_OK)
@@ -1568,15 +1587,26 @@ class DashouHuoquLeixingView(APIView):
club_id = resolve_effective_club_id(request, request.user) club_id = resolve_effective_club_id(request, request.user)
leixing_list = build_club_leixing_list_for_api(club_id) leixing_list = build_club_leixing_list_for_api(club_id)
badge = {}
try:
from orders.services.dashou_badges import dashou_badge_fields, attach_pending_to_leixing_list
badge = dashou_badge_fields(club_id)
leixing_list = attach_pending_to_leixing_list(
leixing_list, badge.get('type_pending_counts'),
)
except Exception as e:
logger.warning('dsqdhqddlx 角标附加失败: %s', e)
logger.info(f"返回商品类型数据:{len(leixing_list)}条,俱乐部:{club_id} 用户: {request.user.UserUID}") logger.info(f"返回商品类型数据:{len(leixing_list)}条,俱乐部:{club_id} 用户: {request.user.UserUID}")
# 🔴 返回成功响应 # 🔴 返回成功响应
# 注意:保持与前端原数据格式完全一致 # 注意:保持与前端原数据格式完全一致;角标为新增字段,不影响旧客户端
return Response({ return Response({
"code": 200, "code": 200,
"msg": "成功", "msg": "成功",
"data": { "data": {
"list": leixing_list # 🔴 保持原字段名 "list" "list": leixing_list, # 🔴 保持原字段名 "list"
**badge,
} }
}, status=status.HTTP_200_OK) }, status=status.HTTP_200_OK)

View File

@@ -207,6 +207,12 @@ class ZuduiDatingView(APIView):
team_svc.serialize_recruit_public(r, orders.get(r.order_id), include_game_ids=False) team_svc.serialize_recruit_public(r, orders.get(r.order_id), include_game_ids=False)
for r in rows for r in rows
] ]
badge = {}
try:
from orders.services.dashou_badges import dashou_badge_fields
badge = dashou_badge_fields(club)
except Exception:
badge = {}
return Response({ return Response({
'code': 0, 'code': 0,
'msg': 'ok', 'msg': 'ok',
@@ -216,6 +222,7 @@ class ZuduiDatingView(APIView):
'page': page, 'page': page,
'page_size': page_size, 'page_size': page_size,
'has_more': start + len(rows) < total, 'has_more': start + len(rows) < total,
**badge,
}, },
}) })

View File

@@ -459,6 +459,15 @@ class DashouXinxiAPIView(APIView):
'zuijinTixian': str(dashou_profile.jinritixian_jine) if dashou_profile.jinritixian_jine is not None else '0.00', # 最近提现金额(今日已提现) 'zuijinTixian': str(dashou_profile.jinritixian_jine) if dashou_profile.jinritixian_jine is not None else '0.00', # 最近提现金额(今日已提现)
}) })
# 角标附加字段(不影响旧客户端)
try:
from jituan.services.club_context import resolve_effective_club_id
from orders.services.dashou_badges import dashou_badge_fields
cid = resolve_effective_club_id(request, request.user)
data.update(dashou_badge_fields(cid))
except Exception:
pass
# 6. 返回成功响应 # 6. 返回成功响应
return Response({ return Response({
'code': 200, 'code': 200,