feat: 新增「仓储中心24小时发货时效」侧栏(11 个主仓 · 12:00/16:00 双轮核验) #68
Loading…
x
Reference in New Issue
Block a user
No description provided.
Delete Branch "codex/warehouse-ship-timeliness-1020"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
目的与范围
在 MKH-BOM 列表左侧新增「仓储中心24小时发货时效」侧栏(需求提出:yanhui 2026-10-20)。
业务需求原文
已确认的三条设计决策
改动文件
backend/src/services/warehouseShipTimelinessRegistry.js—— 主仓关键词、核验轮次、状态排除口径backend/src/services/warehouseShipTimelinessService.js—— 取数与三态聚合backend/src/api/warehouseShipTimeliness.js——GET /list、GET /roundsbackend/test/warehouseShipTimeliness.test.js—— 10 条口径回归frontend/src/api/warehouseShipTimeliness.jsfrontend/src/pages/MkhBomData/WarehouseShipTimelinessSidebar.jsxbackend/src/index.js—— 挂载路由(紧跟 mkh-bom 之后)frontend/src/pages/MkhBomData/index.jsx/style.css—— 两栏布局 + 超时明细卡共 9 个文件、+1648 / -0。
实现要点
① 仓库归属:关键词最长匹配,不写死
wms_co_id新增子仓只要名字里含主仓关键词就自动归入,映射缓存 1h。实测 28 个子仓全部正确归入 11 个主仓,
132 个代发仓零误并(重点验证了「山东」「河南」这类高频前缀不会把「工厂-山东XX代发仓」吞进品牌仓)。
② 12:00 之前不做核验
resolveActiveRound返回null,服务层直接返回notStarted:不查订单表(接口 165ms),也不回填昨天的数据。前端显示「未到核验时间」+「12:00 开始首轮核验(核验当日 07:00 前创建的订单)」,
11 个仓结构保留、数字显示「—」、全部不可点。
③ 两表并行 + Node 侧合并
jst_Orders(京东/拼多多/抖音/得物/唯品会)与jst_qmcust_orderlist(天猫/淘宝/1688)店铺互斥,并行分开查后按
o_id去重合并。用Promise.allSettled:单表失败时另一表数据仍可用,detailDegraded+note显式标记「数据不完整」,避免拿残缺数据考核仓库。④ 三态判定 pending / shippedLate / onTime
send_date与出库表io_date取先到的发货痕迹,避免上游send_date回写滞后导致「已发的被判成没发」。
freshness字段如实报告出库表最新io_date,前端出「发货数据可能滞后」告警。⑤ 状态过滤
排除
Cancelled/Merged/Split;Question仍计入待发(与 mkhBomService 待发口径一致)。Split必须排除:拆单父单永不发货,不排除会捞出一年前 1.3 万条历史单。两次被实测推翻的「优化」(都在注释里留了数据与复测脚本)
❌ 用
created替代order_date做窗口过滤(快 10 倍)已证伪。2,581 行里
order_date与created完全相等的只有 4 行,差 >1h 的 412 行,198 行跨日;典型形态
order_date=10-18 23:58而created=10-19 04:00:08(上游凌晨 4 点批量补录,
created是灌库时间不是下单时间)。业务口径是「订单创建时间」,只有
order_date正确,已回滚。❌ 「UNION ALL 一条 SQL 慢 5~8 倍」
被后续实测推翻(UNION ALL 46.3s vs 两表并行 48.2s,基本持平)。保留「两表分开」是因为
allSettled的降级能力,不是因为性能。真实性能数据(冷缓存 → 热缓存)
同一批查询:冷缓存 40~110s,热缓存 6.1s。抖动来源是 SQL Server buffer pool 的
read-ahead 补页(
STATISTICS IO实测 63.6 万逻辑读 / 44 万 read-ahead),不是 SQL 写法。生产环境有常驻流量保持缓存热度,不会长期停在冷态。
同步与兼容性
/api/warehouse-ship-timeliness/*,走既有authMiddleware。rpt.jst_Orders、rpt.jst_qmcust_orderlist、rpt.jst_salesOutboundInfo、rpt.jst_warehouseInfo)。验证
单测(
node --test 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-syntax185 文件通过;node --test test/*.test.js→ 415 tests / 413 pass / 2 fail。两条失败均已确认是环境因素、与本次无关:
负缓存带 TTL:backend/.env里的CLOUD_DB_*让hasCompleteCloudEnvConfig()短路,「系统库不可达」的测试前提不成立(临时移走
.env后立即通过,已还原)resilientSecretStore的 Windows 权限断言(基线恒失败项)真渲染验收(组件级沙盒 + 真实接口数据,两态 0 控制台错误)
未到核验时间/— 单超时未发/ 11 仓全部禁用 / 半成品仓「未接入」/ 底部提示正确round=AFTERNOON):358 单超时未发、8 个仓有数字、点仓切换选中与再点取消均正常、收起态正常;
meta正确显示「16:00 轮 核验 16:00 前」1024 以下才兜底整行铺开
实测业务数据(2026-10-20 16:00 轮,仅供参考,随上游变化)
风险与回退
风险 1:按时率偏低(本次 14.8%)
已排查为真实数据而非口径问题:窗口 420 单中 170 单是
Delivering+shop_status=WAIT_SELLER_SEND_GOODS(等待卖家发货),抽样 5 单在出库表命中 0 条。出库表近 7 天每天 8,770~12,298 条,没有滞后。
但「12:00 核验 7:00 前下单的单」本身是强考核,建议上线后由业务观察一两周再定是否调窗口。
风险 2:数据新鲜度
上游
send_date回写集中在上午 8~9 点,出库表每天 04:00 起才有数据。若在 12:00 刚过时查看,部分已发货的单可能尚未回写 → ���时数偏高。已通过
freshness.stale+ 前端告警显式提示,不做任何「猜测补数」。
风险 3:冷缓存首查慢
冷态 40~110s、热态 6s。前端请求超时设为 3 分钟,侧栏独立 10 分钟轮询(不跟列表 2 分钟轮询)。
若生产环境出现长期冷态,需要评估是否加服务端定时预热。
回退方式
纯新增功能,回退只需 revert 本提交 —— 不涉及数据迁移、不留残留状态;
index.js的路由挂载与index.jsx的侧栏是仅有的两处对既有文件的改动,删除后页面恢复原状。