fix(analytics): anomaly回退同人多账号累加+今日无环比断言修正
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -186,10 +186,12 @@ async def anomaly(session: AsyncSession, channel: str) -> dict | None:
|
||||
).all()
|
||||
rows = [(d, amap.get(o, o), v) for d, o, v in raw]
|
||||
|
||||
# 逐 user 显式算(yesterday 量 + prev7 均值),不猜 rows 顺序
|
||||
# 逐 user 显式算(yesterday 量 + prev7 均值),不猜 rows 顺序。
|
||||
# 累加而非覆盖:回退路径同人(多账号映射到同一 user_id)会有多行/日。
|
||||
day_rows: dict[str, dict[int, int]] = {}
|
||||
for day, uid, v in rows:
|
||||
day_rows.setdefault(uid, {})[day] = int(v)
|
||||
by_day = day_rows.setdefault(uid, {})
|
||||
by_day[day] = by_day.get(day, 0) + int(v)
|
||||
|
||||
staff_out = []
|
||||
totals_y, totals_p = 0, 0.0
|
||||
|
||||
@@ -55,7 +55,8 @@ async def test_overview_today(make_client, monkeypatch):
|
||||
assert out["cards"]["active_staff"] == 1
|
||||
assert out["cards"]["call_cnt"] == 1
|
||||
assert out["cards"]["first_contact"] == 1 # t1 全史 MIN(day)=今日;t2 不是
|
||||
assert out["cards"].get("mom_total_delta") is None # 今日无环比
|
||||
assert "msg_total_delta" not in out["cards"] # 今日无环比
|
||||
assert "prev_msg_total" not in out["cards"]
|
||||
|
||||
await make_client(seed)
|
||||
|
||||
@@ -89,3 +90,31 @@ async def test_overview_fallback_when_rollup_empty(make_client, monkeypatch):
|
||||
assert out["cards"]["msg_total"] == 3
|
||||
|
||||
await make_client(seed)
|
||||
|
||||
|
||||
async def test_anomaly_fallback_multi_account(make_client, monkeypatch):
|
||||
"""回退路径同人多账号累加:wx1/wx2 同映射 u1,昨日量必须相加而非覆盖。"""
|
||||
monkeypatch.setattr(metrics, "today_key", lambda: _TODAY)
|
||||
async def seed(session):
|
||||
session.add(WechatAccount(wx_id="wx1", user_id="u1"))
|
||||
session.add(WechatAccount(wx_id="wx2", user_id="u1"))
|
||||
# 不 seed StatDailyStaff → 走 msg_daily_stats 回退路径。
|
||||
# 昨日(20260903)各 100(合计 200);prev7 每天各 50(日均 100)→ 偏离 +100% 触发
|
||||
for day in [20260827, 20260828, 20260829, 20260830,
|
||||
20260831, 20260901, 20260902, 20260903]:
|
||||
sent = 100 if day == 20260903 else 50
|
||||
for wx in ("wx1", "wx2"):
|
||||
session.add(MsgDailyStats(channel="wechat", owner_account_id=wx,
|
||||
peer_kind="friend", peer_id="t1", day=day,
|
||||
send_cnt=sent, recv_cnt=0,
|
||||
last_ts=1788500000000,
|
||||
last_is_send=True))
|
||||
await session.commit()
|
||||
a = await metrics.anomaly(session, channel="wechat")
|
||||
assert a is not None
|
||||
staff = {s["user_id"]: s for s in a["staff"]}
|
||||
# 修复前:后写账号覆盖前写,u1 昨日只剩 100;修复后两账号累加 = 200
|
||||
assert staff["u1"]["yesterday"] == 200
|
||||
assert staff["u1"]["prev7_mean"] == 100.0
|
||||
|
||||
await make_client(seed)
|
||||
|
||||
Reference in New Issue
Block a user