From 7758a3351f49a3ef216cc24c2f2a60594e2e2c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Wed, 9 Sep 2026 16:30:05 +0800 Subject: [PATCH] =?UTF-8?q?docs(management):=20=E6=89=B9=E6=AC=A1A?= =?UTF-8?q?=E7=BB=88=E8=AF=84=E4=BF=AE=E6=AD=A3=E2=80=94=E2=80=94=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E9=A1=BA=E5=BA=8F=E7=90=86=E7=94=B1/data=5Fcomplete?= =?UTF-8?q?=E8=AF=AD=E4=B9=89/=E9=80=9A=E8=AF=9D=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 终评 Approve 后三处文档级修正: - CLI help与DEPLOY的顺序理由改为事实(宽表不读fact,先跑不会出0; 顺序约定保留,fact是批次B评分/下钻数据源) - data_complete 注释改为预留语义待批次B定义(当前恒True) - EmployeeCallDaily 注释通话类型实测值(voice_call/wa_voice_call) --- docs/DEPLOY.md | 5 +++-- yunke-server/app/db/models.py | 8 +++++--- yunke-server/app/sync/cli.py | 6 ++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/docs/DEPLOY.md b/docs/DEPLOY.md index fa2383b..eab3ed8 100644 --- a/docs/DEPLOY.md +++ b/docs/DEPLOY.md @@ -249,8 +249,9 @@ sudo docker compose -f docker-compose.server.yml exec backend python -m app.sync - `first-reply-facts`:跨日精确首响事实表(本地实测 11,020 会话 → 6.8 万行)。 - `employee-metrics`:员工指标宽表 + 通话日小表(本地实测 12,371 宽表行 + - 1,163 通话行);**必须在 first-reply-facts 之后跑**——宽表串类列 - (threads_answered/首响分位)与 fact 表同源,先跑宽表会整体为 0。 + 1,163 通话行);**必须在 first-reply-facts 之后跑**——fact 表是后续评分/ + 下钻的数据源,须先填充(宽表自身从 message 表经同一算法重算串类列, + 不读 fact 表,先跑宽表不会出 0,但 fact 缺失会阻塞后续能力)。 - 两命令均为按日 delete+insert 幂等重建,复跑结果一致,中断重跑无副作用。 ## 8. 本地收尾(部署验证通过后) diff --git a/yunke-server/app/db/models.py b/yunke-server/app/db/models.py index 7849632..2de19a0 100644 --- a/yunke-server/app/db/models.py +++ b/yunke-server/app/db/models.py @@ -1090,7 +1090,8 @@ class EmployeeMetricDaily(Base): reactivated_customer_count: Mapped[int] = mapped_column( Integer, nullable=False, default=0, server_default=sa.text("0") ) - # fact 是否已覆盖当日(宽表生成前置条件;False=串类列可能滞后) + # 预留完整性标记:宽表生成当前恒写 True(串类列与 fact 同一算法直算, + # 不读 fact 表)——真实语义(如校验 fact 覆盖/同步完整)由批次B定义 data_complete: Mapped[bool] = mapped_column( Boolean, nullable=False, default=False, server_default=sa.text("0") ) @@ -1102,8 +1103,9 @@ class EmployeeMetricDaily(Base): class EmployeeCallDaily(Base): """员工×日通话小表(v2 §1.2 #9)——通话无消息渠道维度,独立于宽表。 - phone_call.channel 是通话类型(phone_call/voice_call)非消息渠道, - 塞进 (day,channel,user) 宽表会在 channel=all 聚合时双计。接通 = + phone_call.channel 是通话类型(实测值 voice_call/wa_voice_call, + 无蜂窝 phone_call 行)非消息渠道,塞进 (day,channel,user) 宽表会在 + channel=all 聚合时双计。接通 = call_duration > 0;followup = 通话后 24h 内该员工任一账号对该客户 有消息(Task 0 已核实:1:1 通话可匹配率 100%,@chatroom 群通话除外)。 """ diff --git a/yunke-server/app/sync/cli.py b/yunke-server/app/sync/cli.py index ba5086a..7aa0df4 100644 --- a/yunke-server/app/sync/cli.py +++ b/yunke-server/app/sync/cli.py @@ -157,8 +157,10 @@ def _build_parser() -> argparse.ArgumentParser: description=( "Full rebuild of the management wide table (per-day x channel " "x staff, 1:1 caliber) and the call daily table. Must run " - "AFTER first-reply-facts (thread columns share the same " - "source). Deploy backfill + nightly self-heal. Idempotent." + "AFTER first-reply-facts (the fact table feeds Batch-B " + "scoring and drilldown; both recompute threads from messages " + "via one shared algorithm). Deploy backfill + nightly " + "self-heal. Idempotent." ), )