fix(wle): 0 单不再冒充「全部正常」——窗口空时查数据源是否停更 #94

Merged
yanhui merged 1 commits from yanhui-wle-emptydata-1102 into main 2026-11-02 13:32:50 +08:00
Collaborator

目的与范围

修「物流转运异常」页面/钉钉把「数据源没同步」显示成「已发货 0 单,全部正常」的假绿。

现象(业务 2026-11-02 反馈):09:00 那批推的是
已发货 0 单 / 0 个包裹,异常 0 个包裹(0%),业务问「就算没有异常,也不该 0 单」。

实际原因(已查库确认,不是口径问题):

事实 数据
物流镜像表 jst_order_express_details 最后一次灌库 2026-11-01 07:55:04(截至 11-02 10:16 已 26.5 小时未同步)
11-01 当天 12 仓发货行数 0(全表该发货日也只有 1 行,属 POP 仓)
10-31 当天 12 仓发货行数 5,813(正常)
订单表 jst_Orders 11-01 send_date 单量 4,601 单 —— 货确实发了

缺陷:freshness 原本只用「本批窗口内行的 query_time」算新鲜度。
窗口一行都没有时 snapshotAt 是空串 → stale=false、hint=''、coversDeadline=null,
于是「上游没同步」与「当天真没发货」在页面和钉钉里完全无法区分,钉钉还会写「全部正常」。

范围:warehouseLogisticsExceptionService / 对应钉钉 job / WLE 页面(含导出与统计口径不动)。

改动

  1. service:窗口 0 行时补查一次表级 MAX(query_time),新增
    freshness.emptyWindow / sourceLastUpdate / sourceAgeMinutes / sourceStale;
    hint 分三种情况(真停更 / 表新但该日无记录 / 取不到表级时间)给不同文案。
  2. 钉钉正文:totalPackages === 0 不再无脑「全部正常」;
    • 真停更:⚠️ 物流数据未同步:镜像表最后更新 …(已 N 小时未同步),… 0 单不代表当天没发货
    • 表新但该日 0 条:… 在物流镜像表里 0 条发货记录(数据源本身正常)… 请到聚水潭核对
    • 抬头仍带「异常」关键词(钉钉自定义关键词安全设置)
  3. 前端:emptyWindow 走 error 红条;发货卡片副标改「数据未同步,见上方红条」。
  4. 顺带修:钉钉消息链接带 ?date=YYYY-MM-DD,但页面从不读该参数,点进去永远显示「今天这批」
    → 现按 URL 初始化核验日(历史消息才点得对批次)。

同步与兼容性

  • 未改 packageCount / shippedOrders / 异常判据 / 剔除口径,只新增字段与提示。
  • 新字段为增量,老前端忽略不影响;notStarted 分支的 freshness 也补齐了同名字段保持形状一致。

验证

  • npm --prefix backend run check:505 tests / 503 pass,新增 5 个用例全过:
    停更 hint、表新但 0 条、有行时不付全表 MAX(性能回归)、推送文案两态。
    既有失败 2 个与本任务无关(cloudDatabaseConfigCache 负缓存 TTL、resilientSecretStore 的 Windows 0600 断言)。
  • 生产库实跑(本地 4002 直连 JSReportReplica):
    • date=2026-11-02 → emptyWindow=true、sourceLastUpdate=2026-11-01 07:55:04、sourceAgeMinutes≈1590、hint 正确
    • date=2026-11-01 → 4,390 单 / 9 异常、emptyWindow=false,原「未覆盖核验时刻」提示不变
  • 钉钉 dryRun 正文实测:
    【仓储物流转运异常】11-02 09:00 核验 · 11-01 发货
    已发货 0 单 / 0 个包裹,异常 0 个包裹(0%)
    ⚠️ 物流数据未同步:镜像表最后更新 2026-11-01 07:55:04(已 26.5 小时未同步),2026-11-01 的发货记录一条都没进库 —— 上面 0 单不代表当天没发货,请先到聚水潭核对。
    
  • Playwright 真渲染(5173):?date=2026-11-02 → 红条 + 副标「数据未同步,见上方红条」,pageerror 0;
    ?date=2026-11-01 → 4,390 单 / 9 异常正常出表,URL 参数生效。
  • 前端 eslint 干净、vite build 通过。

风险与回退

  • 空窗口多一条全表 MAX(query_time)(实测 13.5s,402 万行视图),随主结果进 5 分钟缓存,
    且只在窗口 0 行时触发(有数据的正常批次零成本,已写用例锁住)。
  • 回退:revert 本提交即可,无表结构、无数据迁移。

后续(不在本 PR)

  • 该镜像表 11-01 07:55 后停止灌库,需 IT 侧修 ETL;修好前 11-01 那批仍会是 0 单(现在至少会明说是没同步)。
## 目的与范围 修「物流转运异常」页面/钉钉把「数据源没同步」显示成「已发货 0 单,全部正常」的假绿。 **现象**(业务 2026-11-02 反馈):09:00 那批推的是 `已发货 0 单 / 0 个包裹,异常 0 个包裹(0%)`,业务问「就算没有异常,也不该 0 单」。 **实际原因**(已查库确认,不是口径问题): | 事实 | 数据 | |---|---| | 物流镜像表 `jst_order_express_details` 最后一次灌库 | **2026-11-01 07:55:04**(截至 11-02 10:16 已 26.5 小时未同步) | | 11-01 当天 12 仓发货行数 | **0**(全表该发货日也只有 1 行,属 POP 仓) | | 10-31 当天 12 仓发货行数 | 5,813(正常) | | 订单表 `jst_Orders` 11-01 `send_date` 单量 | **4,601 单** —— 货确实发了 | **缺陷**:`freshness` 原本只用「本批窗口内行的 `query_time`」算新鲜度。 窗口一行都没有时 `snapshotAt` 是空串 → `stale=false`、`hint=''`、`coversDeadline=null`, 于是「上游没同步」与「当天真没发货」在页面和钉钉里完全无法区分,钉钉还会写「全部正常」。 范围:`warehouseLogisticsExceptionService` / 对应钉钉 job / WLE 页面(含导出与统计口径**不动**)。 ## 改动 1. **service**:窗口 0 行时补查一次表级 `MAX(query_time)`,新增 `freshness.emptyWindow / sourceLastUpdate / sourceAgeMinutes / sourceStale`; hint 分三种情况(真停更 / 表新但该日无记录 / 取不到表级时间)给不同文案。 2. **钉钉正文**:`totalPackages === 0` 不再无脑「全部正常」; - 真停更:`⚠️ 物流数据未同步:镜像表最后更新 …(已 N 小时未同步),… 0 单不代表当天没发货` - 表新但该日 0 条:`… 在物流镜像表里 0 条发货记录(数据源本身正常)… 请到聚水潭核对` - 抬头仍带「异常」关键词(钉钉自定义关键词安全设置) 3. **前端**:`emptyWindow` 走 error 红条;发货卡片副标改「数据未同步,见上方红条」。 4. **顺带修**:钉钉消息链接带 `?date=YYYY-MM-DD`,但页面从不读该参数,点进去永远显示「今天这批」 → 现按 URL 初始化核验日(历史消息才点得对批次)。 ## 同步与兼容性 - 未改 `packageCount` / `shippedOrders` / 异常判据 / 剔除口径,只新增字段与提示。 - 新字段为增量,老前端忽略不影响;`notStarted` 分支的 freshness 也补齐了同名字段保持形状一致。 ## 验证 - `npm --prefix backend run check`:**505 tests / 503 pass**,新增 5 个用例全过: 停更 hint、表新但 0 条、**有行时不付全表 MAX**(性能回归)、推送文案两态。 既有失败 2 个与本任务无关(`cloudDatabaseConfigCache` 负缓存 TTL、`resilientSecretStore` 的 Windows `0600` 断言)。 - 生产库实跑(本地 4002 直连 `JSReportReplica`): - `date=2026-11-02` → `emptyWindow=true`、`sourceLastUpdate=2026-11-01 07:55:04`、`sourceAgeMinutes≈1590`、hint 正确 - `date=2026-11-01` → 4,390 单 / 9 异常、`emptyWindow=false`,原「未覆盖核验时刻」提示不变 - 钉钉 `dryRun` 正文实测: ``` 【仓储物流转运异常】11-02 09:00 核验 · 11-01 发货 已发货 0 单 / 0 个包裹,异常 0 个包裹(0%) ⚠️ 物流数据未同步:镜像表最后更新 2026-11-01 07:55:04(已 26.5 小时未同步),2026-11-01 的发货记录一条都没进库 —— 上面 0 单不代表当天没发货,请先到聚水潭核对。 ``` - Playwright 真渲染(5173):`?date=2026-11-02` → 红条 + 副标「数据未同步,见上方红条」,`pageerror` 0; `?date=2026-11-01` → 4,390 单 / 9 异常正常出表,URL 参数生效。 - 前端 `eslint` 干净、`vite build` 通过。 ## 风险与回退 - 空窗口多一条全表 `MAX(query_time)`(实测 13.5s,402 万行视图),随主结果进 5 分钟缓存, 且**只在窗口 0 行时触发**(有数据的正常批次零成本,已写用例锁住)。 - 回退:revert 本提交即可,无表结构、无数据迁移。 ## 后续(不在本 PR) - 该镜像表 11-01 07:55 后停止灌库,需 IT 侧修 ETL;修好前 11-01 那批仍会是 0 单(现在至少会明说是没同步)。
yanhui added 1 commit 2026-11-02 10:32:05 +08:00
11-02 09:00 那批推到钉钉群的是「已发货 0 单 / 0 个包裹,异常 0 个包裹(0%)」,
业务问「怎么可能 0 单」。查库确认:物流镜像表 jst_order_express_details
最后灌库停在 2026-11-01 07:55,11-01 当天 12 个发货仓一条发货记录都没有
(订单表 jst_Orders 同日有 4601 单发货,说明货是真发了,只是物流没进库)。

根因不是口径,是「0 单没有告警」这个设计缺陷:freshness 只用本批窗口内行的
query_time 算,窗口一行都没有时 snapshotAt 为空串 → stale=false、hint='',
于是「上游没同步」和「当天真没发货」在页面和钉钉里长得完全一样,还写「全部正常」。

改动
- service:窗口 0 行时补查一次表级 MAX(query_time)(全表 13.5s,只在空窗口付这笔钱,
  随主结果进 5 分钟缓存),新增 freshness.emptyWindow / sourceLastUpdate /
  sourceAgeMinutes / sourceStale,并按「真停更 / 表新但当天无记录 / 取不到时间」
  三种情况给不同 hint。
- 钉钉正文:0 条时不再无脑写「本批无转运异常,全部正常」;真停更写
  「⚠️ 物流数据未同步:镜像表最后更新 …(已 N 小时未同步)… 0 单不代表当天没发货」,
  表新但当天无记录则说明「库里 0 条发货记录(数据源正常),请到聚水潭核对」。
- 前端:emptyWindow 走红条(原来只判 coversDeadline/stale,空窗口不告警),
  发货卡片副标改为「数据未同步,见上方红条」。
- 前端顺带修:钉钉消息链接带 ?date=YYYY-MM-DD,但页面从不读这个参数,
  点进去永远显示「今天这批」;现按 URL 初始化核验日。

验证
- npm --prefix backend run check:505 tests / 503 pass;新增 5 个用例
  (停更 hint、表新但 0 条、有行时不付全表 MAX、推送文案两态)全过。
  既有失败 2 个与本任务无关:cloudDatabaseConfigCache 负缓存 TTL、
  resilientSecretStore 的 Windows 0600 权限断言。
- 生产库实跑(本地 4002,直连 JSReportReplica):
  date=2026-11-02 → emptyWindow=true、sourceLastUpdate=2026-11-01 07:55:04、
  sourceAgeMinutes≈1590、hint 正确;date=2026-11-01 → 4390 单 / 9 异常、
  emptyWindow=false,原有「未覆盖核验时刻」提示不变。
- 钉钉 dryRun 正文实测:前 3 行即带「⚠️ 物流数据未同步 … 0 单不代表当天没发货」。
- Playwright 真渲染(5173):
  ?date=2026-11-02 → 红条 + 「数据未同步,见上方红条」,0 pageerror;
  ?date=2026-11-01 → 4,390 单 / 9 异常正常出表,且 URL 参数已生效。
- 前端 eslint 干净,vite build 通过。

风险与回退
- 只增字段与提示,不改任何统计口径;packageCount/shippedOrders 计算逻辑未动。
- 空窗口多一条全表 MAX 查询(13.5s),已用 5 分钟缓存兜住,且只在异常路径触发。
- 回退:单文件 revert 本提交即可,无数据结构变更。
yanhui merged commit 54ad6aad89 into main 2026-11-02 13:32:50 +08:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: lunanting/cangku#94
No description provided.