chore(docs): cash-plan-alerts 手册回填 F4b commit 哈希 (dama-cashplan-zombie-alert-cleanup-20260913)

This commit is contained in:
wecom-fullstack
2026-09-13 07:39:06 +08:00
parent e159db058a
commit 53c642b644
+17 -5
View File
@@ -16,13 +16,19 @@
- 余额快照批次口径开关(环境变量,改后需重启后端):
- `CMA_CASH_SNAPSHOT_MODE` = `skip`(默认,批次行不生成逐户预警)| `aggregate`(按批次聚合 1 条)| `per_customer`(旧行为,逐户)
- `CMA_CASH_SNAPSHOT_SOURCES` = 逗号分隔的 source 名单(覆盖内置名单)
- **展示口径 = 落库口径(F4b)**:`POST /api/cma/admin/alerts/check` 响应里 `cash.details[*].summary` 的
`overdue_receive_count/amount` 与写库同源(快照批次按 mode 处理),并附
`overdue_receive_count_raw/amount_raw`(全集)、`snapshot_rows_excluded(_amount)`(被剔除量)、
`snapshot_batches`(批次明细)、`snapshot_mode` ⇒ 读数字不必再猜「为什么写入 0 条却显示 216 笔」。
## ③ 验证路径
- **自动脚本**:`backend/scripts/verify_cashplan_alert_engine_fix.py`(43 项验收电池)
- **自动脚本**:`backend/scripts/verify_cashplan_alert_engine_fix.py`(**51 项**验收电池;F4b 后由 43 增至 51)
- 在**生产库副本**(mysqldump → `cma_cashvfy`)上跑,零生产写入;唯一生产访问是只读计数;跑完自动删副本。
- 覆盖:KPI 归属(433/434)/兜底 ORDER BY 确定性/entity_id 归属/去重刷新/快照批次三档开关/端点 401 与 entity 过滤。
- **期望输出**:`汇总: 43/43 PASS` + `[cleanup] cma_cashvfy 已删除`,退出码 0。
- **已测基线**:2026-09-13 → 43/43 PASS(副本);生产端点实测 `?entity_id=2` 200 且 `new_alerts=0`。
- 覆盖:KPI 归属(433/434)/兜底 ORDER BY 确定性/entity_id 归属/去重刷新/快照批次三档开关/端点 401 与 entity 过滤/**F4b 展示=落库口径(count=new_alerts、raw/excluded/batches 可见)**。
- **pytest 断言**:`backend/tests/test_cash_summary_snapshot_alignment_20260913.py`(11 项,SQLite 内存库,无需生产库)
- skip/per_customer/aggregate 三档口径矩阵 + suggestions 文案 + upcoming_7d 同源 + 实体隔离。
- **期望输出**:`汇总: 51/51 PASS` + `[cleanup] cma_cashvfy 已删除`,退出码 0。
- **已测基线**:2026-09-13 → 43/43 PASS(副本,F1-F5)、**51/51 PASS(含 F4b)**、pytest 11/11;生产端点实测 `?entity_id=2` 200、`new_alerts=0`、`summary.overdue_receive_count=0 / raw=216 / excluded=216`。
- **手工复核 SQL**(只读):
```sql
-- 博海 pending 红色"到期未收款"应为 0
@@ -36,6 +42,8 @@
- **entity_id 必须显式写**:`KPIAlert(entity_id=...)`。该列 default=1,漏传会把博海的预警挂到酣客工作台(2026-09-10 实测 589/590)。
- **去重键 = suggestion.plan_id**(不是 alert_message,后者含动态"已逾期X天")。命中后必须**刷新**文本/等级/天数/归属,不能 `continue`。
- **余额快照批次**(source ∈ bohai_ar_20260630 / bohai_ap_20260630 / bohai_prepay_20260630 / receivables_migrate):plan_date 是**导入基准日**(期末日),不是到期日 → 逐户生成就会永远 overdue(伪逾期)。默认 `skip` 不逐户生成。
- **展示与落库必须同源**:`forecast_cash_flow_with_plans()` 的 summary/suggestions/upcoming 与 `check_cash_alerts()` 写库路径**共用** `split_snapshot_plans()`。
任何一侧新增过滤条件,另一侧必须同步修改,否则同一次响应会出现「写入 0 条 / 展示 N 笔」自相矛盾(F4b 修的就是这个)。
- **skip 模式不接管存量快照预警**:历史遗留的 pending 快照预警需财务手工置 resolved(引擎不会自动改它们的状态)。
- **⚠️ 易踩点**:
- `LAST_INSERT_ID()` 是**连接级**的——用「新连接」的 raw 查询取不到刚插入的自增 id(验证脚本曾因此把 plan_id 记成 0)。
@@ -47,12 +55,16 @@
| 日期 | 修改人 | 改动 | commit | 影响 |
|------|--------|------|--------|------|
| 2026-09-13 | wecom-fullstack | 手册创建;F1 显式写 entity_id(引擎2处+deviation_engine/alert_generator/deviation_push/bot_bridge/bot_bridge_v2);F2 候选码加实体前缀后缀 + 兜底 ORDER BY;F3 去重命中改为刷新文本/等级/天数/归属;F4 余额快照批次开关(默认 skip,另备 aggregate/per_customer);F5 admin 端点补鉴权(无 token 401)+ 可选 entity_id | 59e65a6 | 博海不再重建伪逾期预警;预警 KPI 归属 433/434;不再跨账套错挂 |
| 2026-09-13 | wecom-fullstack | **F4b 展示口径与落库口径同源**:新增 `split_snapshot_plans()` / `summarize_overdue_receives()`;`forecast_cash_flow_with_plans()` 的 summary/suggestions/upcoming_7d 按 mode 过滤快照批次(skip 不计 / aggregate 计批次 / per_customer 逐户),并在 summary 暴露 `*_raw`/`snapshot_rows_excluded(_amount)`/`snapshot_batches`/`snapshot_mode`;写库侧复用同一 helper;验收电池 43→51 项 + 新增 pytest 11 项 | e159db0 | 消除「同一次响应写入 0 条却展示 216 笔 / 200.72 万」;数据不隐藏、可追溯 |
## ⑥ 关联
- **依赖表**:`cash_plans`、`kpi_alerts`、`kpi_definitions`、`kpi_values`、`system_config`
- **依赖接口**:`POST /api/cma/admin/alerts/check[?entity_id=N]`、`GET /api/cma/cash/*`
- **关联模块**:预警中心(alerts)、预警规则(alert-rules)、资金预测(cash-flow)
- **代码**:`backend/app/utils/cash_forecast_engine.py::check_cash_alerts`、`backend/app/main.py::admin_check_alerts`
- **代码**:`backend/app/utils/cash_forecast_engine.py::check_cash_alerts`、`::forecast_cash_flow_with_plans`、`::split_snapshot_plans`、`::summarize_overdue_receives`、`backend/app/main.py::admin_check_alerts`
- **验收**:`backend/scripts/verify_cashplan_alert_engine_fix.py`(51 项电池)、`backend/tests/test_cash_summary_snapshot_alignment_20260913.py`
- **遗留(P2,仅观察)**:`forecast` 逐日现金流投影仍用 `get_cash_plans()` 日期窗口取待执行计划(未按快照批次过滤)。
仅当某快照批次的 plan_date 落在 `[today, today+30]` 窗口内才会被计入投影;2026-09-13 实况快照批次 plan_date=2026-06-30(历史)⇒ 窗口内 0 行,无实际影响。若未来导入「未来基准日」快照需一并收口。
---
<!-- 注意:更新本手册时必须同时更新 ⑤修改记录;队列状态见 /root/WB_WS/_registry/cma-module-queue.json -->