forked from lunanting/cangku
需求(yanhui 2026-10-20):在 MKH-BOM 列表左侧加一栏「仓储中心24小时发货时效」, 下列 11 个主仓(横林二仓、横林三仓、横林二仓品牌仓、崔桥工厂仓、崔桥工厂品牌仓、 崔桥工厂半成品仓、新苏北仓、睢宁仓、山东青岗集仓、山东品牌仓、河南洛宁仓), 从系统库存抓取已发货/未发货订单,按订单创建时间判定发货是否及时: · 每天 12:00 核验「当天创建时间 7:00 之前」的订单是否已完成发货 · 每天 16:00 核验「当天创建时间 16:00 之前」的订单是否已完成发货 已确认的三条设计决策: 1. 子仓归属 → 连子仓一起算(京东云仓/自营仓/运营C专用仓/唯品仓等并入主仓) 2. 崔桥工厂半成品仓 → 系统无同名仓,先留空占位(不映射到配件仓 15718196) 3. 展示结构 → 只显示超时未发 实现要点 - 仓库归属用「关键词最长匹配」(不写死 wms_co_id),新增子仓只要名字含主仓关键词 就自动归入,缓存 1h。实测 28 个子仓全部正确归入 11 个主仓,132 个代发仓零误并。 - 12:00 之前**不做核验**:resolveActiveRound 返回 null,服务层直接返回 notStarted, 既不查订单表(接口 165ms)也不回填昨天的数据。前端显示「未到核验时间」+ 「12:00 开始首轮核验(核验当日 07:00 前创建的订单)」,11 个仓结构保留、数字显示「—」。 - 订单取数:两张表店铺互斥(jst_Orders = 京东/拼多多/抖音/得物/唯品会, jst_qmcust_orderlist = 天猫/淘宝/1688),并行分开查 + Node 侧按 o_id 去重合并, 用 Promise.allSettled 保证单表失败时另一表数据仍可用(detailDegraded 标记)。 - 三态判定 pending / shippedLate / onTime:send_date 与出库表 io_date 取先到的发货痕迹, 避免上游 send_date 回写滞后导致「已发的被判成没发」。 - 状态过滤:排除 Cancelled / Merged / **Split**(拆单父单永不发货,不排除会捞出一年前 1.3 万条历史单),Question 仍计入待发。 - freshness 字段如实报告出库表最新 io_date,前端「发货数据可能滞后」告警, 不拿一份可能滞后的数据去考核仓库。 排除的两次错误优化(均在代码注释里留了实测数据与复测脚本路径) 1. 用 created 替代 order_date 做窗口过滤(快 10 倍)—— 已证伪:2581 行里完全相等的只有 4 行, 差 >1h 的 412 行,198 行跨日;典型形态 order_date=10-18 23:58 而 created=10-19 04:00:08 (上游凌晨 4 点批量补录,created 是灌库时间不是下单时间)。业务口径是「订单创建时间」, 只有 order_date 正确。 2. 「UNION ALL 一条 SQL 慢 5~8 倍」—— 被后续实测推翻(46.3s vs 并行 48.2s,基本持平)。 验证 - 新增 backend/test/warehouseShipTimeliness.test.js,10 条用例全绿,覆盖: 最长匹配不误并、子仓命名、山东/河南高频前缀不误并、占位仓、12:00 前返回 null、 12:00 轮窗口 00:00~07:00、16:00 轮窗口 00:00~16:00、状态排除表、三态分桶互斥、 跨表重复 o_id 去重、round.windowEnd 必须带出(否则前端渲染成「核验 前」)。 - check-syntax 185 文件通过;全量 node --test 415 项 / 413 过 / 2 fail, 两条失败均为已知环境因素(负缓存带 TTL 因 .env 有 CLOUD_DB_* 短路; resilientSecretStore 的 Windows 权限断言,基线恒失败)。 - 真渲染验收(组件级沙盒 + 真实接口数据):两态均 0 控制台错误; 已核验态 358 单超时未发、8 个仓有数字、点仓切换选中/再点取消均正常; 多分辨率验证 1920/1600 侧栏 208px、1440/1366 收窄 176px、列表始终竖向。