fix: 抢单/组队卡片成交指标有字段即返回,均时含0样本

商家指标俱乐部兜底;组队大厅附带商家成交率/罚款率/均时。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-27 08:21:33 +08:00
parent 871144b53b
commit 3fe24cbcce
3 changed files with 40 additions and 9 deletions

View File

@@ -208,8 +208,9 @@ def serialize_merchant_stat(row) -> dict:
def pool_merchant_stat_payload(row) -> dict | None:
"""
抢单池展示用:订单样本则不返回
有订单则返回成交率/罚款率;平均成交时长仅有结算样本时返回。
抢单池展示用:订单样本返回
成交率/罚款率有样本即返回;均时仅有结算样本时返回含均时≈0
前端按字段有哪个展示哪个。
"""
if not row:
return None
@@ -224,11 +225,11 @@ def pool_merchant_stat_payload(row) -> dict | None:
'fine_rate_text': f"{round(full['fine_rate'] * 100, 1)}%",
}
sc = int(full.get('settle_duration_sample_count') or 0)
if sc > 0 and full.get('avg_deal_hours'):
h = float(full['avg_deal_hours'])
if sc > 0:
h = float(full.get('avg_deal_hours') or 0)
out['avg_deal_hours'] = h
if h < 1:
out['avg_deal_hours_text'] = f'{max(1, int(round(h * 60)))}分钟'
out['avg_deal_hours_text'] = f'{max(1, int(round(h * 60)))}分钟' if h > 0 else '不足1分钟'
else:
out['avg_deal_hours_text'] = f'{round(h, 1)}小时'
return out
@@ -261,6 +262,7 @@ def batch_pool_merchant_stats(club_id: str, merchant_uids, order_club_map=None)
)
by_key = {(r.club_id, r.merchant_uid): r for r in rows}
out = {}
missing = []
for uid in uids:
prefer = ((order_club_map or {}).get(uid) or default_club or '').strip()
row = by_key.get((prefer, uid))
@@ -269,9 +271,21 @@ def batch_pool_merchant_stats(club_id: str, merchant_uids, order_club_map=None)
row = by_key.get((cid, uid))
if row:
break
if not row:
missing.append(uid)
continue
payload = pool_merchant_stat_payload(row)
if payload:
out[uid] = payload
# 订单俱乐部对不上时,按商家 UID 兜底(取样本最多的一条)
if missing:
for r in MerchantDealStat.query.filter(merchant_uid__in=missing).order_by('-order_count'):
uid = r.merchant_uid
if uid in out:
continue
payload = pool_merchant_stat_payload(r)
if payload:
out[uid] = payload
return out
@@ -306,11 +320,11 @@ def miniapp_merchant_deal_payload(row) -> dict | None:
'fine_rate_text': f"{round(full['fine_rate'] * 100, 1)}%",
}
sc = int(full.get('settle_duration_sample_count') or 0)
if sc > 0 and full.get('avg_deal_hours'):
h = float(full['avg_deal_hours'])
if sc > 0:
h = float(full.get('avg_deal_hours') or 0)
out['avg_deal_hours'] = h
if h < 1:
out['avg_deal_hours_text'] = f'{max(1, int(round(h * 60)))}分钟'
out['avg_deal_hours_text'] = f'{max(1, int(round(h * 60)))}分钟' if h > 0 else '不足1分钟'
else:
out['avg_deal_hours_text'] = f'{round(h, 1)}小时'
return out

View File

@@ -883,6 +883,7 @@ def serialize_recruit_public(rec, order=None, *, include_game_ids=False) -> dict
'sj_avatar': '',
'leader_avatar': '',
'leader_deal_stat': None,
'shangjia_deal_stat': None,
}
if order:
data['fadanpingtai_text'] = '平台单' if order.Platform == 1 else ('商家单' if order.Platform == 2 else '')
@@ -941,6 +942,22 @@ def serialize_recruit_public(rec, order=None, *, include_game_ids=False) -> dict
dashou_row = None
data['leader_deal_stat'] = miniapp_dashou_deal_payload(dashou_row)
# 商家单:附带商家成交率/罚款率/均时(有样本才有;前端有哪个展示哪个)
try:
from jituan.services.deal_stats import miniapp_merchant_deal_payload
from jituan.models import MerchantDealStat
sj_uid = (data.get('shangjia_id') or '').strip()
if sj_uid and club_ids:
m_row = None
for cid in club_ids:
m_row = MerchantDealStat.query.filter(club_id=cid, merchant_uid=sj_uid).first()
if m_row and int(m_row.order_count or 0) > 0:
break
m_row = None
data['shangjia_deal_stat'] = miniapp_merchant_deal_payload(m_row)
except Exception:
data['shangjia_deal_stat'] = None
if include_game_ids:
from orders.models import TeamMember
from users.business_models import User

View File

@@ -289,7 +289,7 @@ class DashouDingdanHuoquView(APIView):
identity_pairs = []
youzhi_map = {}
merchant_uids = set(shangjia_id_map.values())
merchant_uids = {u for u in shangjia_id_map.values() if u}
if merchant_uids:
for sj in UserShangjia.query.filter(
user__UserUID__in=merchant_uids