feat(analytics): 首响时长+回复率数据管道——消息串算法/日汇总扩展列/员工聚合
批1(A1+A2):管理层要看「每个人的响应质量」。 - 迁移 d9e0f1a2b3c4:msg_daily_stats/stat_daily_staff 各加 cust_threads/threads_answered/fr_sum_ms(NOT NULL server_default 0, 幂等守卫照 9b0d0c133035 惯例;models.py 双声明同步) - summary.py _thread_stats:串=客户连续消息不被员工消息打断的段, is_send=None 不参与串判定;fr=员工首条回复−串末条客户消息; 日切近似 v1(日末未闭合串计 threads 不计 answered,口径写进 docstring) - recompute_days/recompute_all 都先按 ts 排序再算串(乱序防护) - staff_summary 聚合三列按账号→员工累加(fr_cnt≡threads_answered 不单列) - 测试 +10:串算法矩阵 9 例+staff 聚合传递;全量 589 绿 - 本地 86 万行回填验证:daily-stats 60s/staff 10s,rollup 总和与 明细完全一致,随机 5 行 SQL 独立复算全对 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -89,6 +89,10 @@ async def recompute_days(
|
||||
MsgDailyStats.peer_id,
|
||||
MsgDailyStats.send_cnt,
|
||||
MsgDailyStats.recv_cnt,
|
||||
# 首响/回复率三列(2026-09-07 批1):同义聚合累加
|
||||
MsgDailyStats.cust_threads,
|
||||
MsgDailyStats.threads_answered,
|
||||
MsgDailyStats.fr_sum_ms,
|
||||
).where(
|
||||
MsgDailyStats.day == day, MsgDailyStats.channel == channel
|
||||
)
|
||||
@@ -102,13 +106,25 @@ async def recompute_days(
|
||||
if not rows:
|
||||
continue
|
||||
agg: dict[str, dict] = {}
|
||||
for owner, kind, peer, s, r in rows:
|
||||
for owner, kind, peer, s, r, t, a_ns, fr in rows:
|
||||
uid = amap.get(owner, owner) # 映射不上按 owner 原值(读侧标注)
|
||||
a = agg.setdefault(
|
||||
uid, {"sent": 0, "recv": 0, "friends": set(), "rooms": set()}
|
||||
uid,
|
||||
{
|
||||
"sent": 0,
|
||||
"recv": 0,
|
||||
"friends": set(),
|
||||
"rooms": set(),
|
||||
"threads": 0,
|
||||
"answered": 0,
|
||||
"fr": 0,
|
||||
},
|
||||
)
|
||||
a["sent"] += int(s or 0)
|
||||
a["recv"] += int(r or 0)
|
||||
a["threads"] += int(t or 0)
|
||||
a["answered"] += int(a_ns or 0)
|
||||
a["fr"] += int(fr or 0)
|
||||
if kind == "friend": # 显式分支:未来新 kind 跳过,不误入 rooms
|
||||
a["friends"].add(peer)
|
||||
elif kind == "room":
|
||||
@@ -123,6 +139,9 @@ async def recompute_days(
|
||||
msg_recv=a["recv"],
|
||||
active_friends=len(a["friends"]),
|
||||
active_rooms=len(a["rooms"]),
|
||||
cust_threads=a["threads"],
|
||||
threads_answered=a["answered"],
|
||||
fr_sum_ms=a["fr"],
|
||||
)
|
||||
)
|
||||
n += 1
|
||||
|
||||
Reference in New Issue
Block a user