Files
InboundVerify/docs/2026-08-03-应到驱动差缺统计重构-实现总结.md
Misaka 36b204abe5 refactor(db_compare): 差缺统计改为应到驱动,以出库日为批次归属日
将未到统计从实到驱动(实到锚点反推批次)改为应到驱动(batch_out_date 归属日直接取应到批次),以吸收应到任务提前 1~2 天提交的扰动(韵达固定 +1、中通偶发 +1)。

- expected_record 新增 out_date / batch_out_date + 索引;入库解析出库时间并聚合批次归属日,支持历史回填

- 新增 compare_site_outdate 应到驱动入口,保留 compare_site_date 实到驱动作对照

- 未到任务 / POST /compare / 全站汇总切换到应到驱动

- 附现状梳理、设计、实现总结三篇文档
2026-08-03 22:52:28 +08:00

5.7 KiB
Raw Blame History

应到驱动差缺统计重构 · 实现总结(备忘录)

完成日期2026-08-03 分支:refactor/undelivered-by-expected 关联文档:docs/2026-08-02-未到差缺统计逻辑现状梳理.mddocs/2026-08-03-应到驱动差缺统计重构-design.md 状态:已完成并验证,待提交


一、背景

原差缺统计为实到驱动:以目标日实到扫描为锚点 → 反推交接批次 → 展开批次全量应到 → 逐单比对。

业务部门日常以应到数据为依据,且应到任务可能被提前提交 1~2 天(韵达固定提前 1 天),导致:

  • 完全按应到统计会出现假差缺;
  • 实到驱动会把历史批次混入当天报表1 单命中即整批展开)。

重构目标:改为应到驱动,并用「出库日」作为批次归属日,自动吸收提前提交。

二、核心口径

  • 批次归属日 = 批次内运单「出库时间」日期众数,并列取较早(字段:expected_record.batch_out_date)。
  • 统计 D 日差缺 = 取所有 batch_out_date = D 的应到批次,展开全量应到 → 查全量实到 → 逐运单比对。
  • 无论批次在 D / D-1 / D-2 哪天下载(business_date 为何),只要出库日 = D 即纳入 D 日统计。

三、数据实证7 月全量)

站点 下载日=出库大头日 出库大头日=下载日+1
顺心 83/83100% 0
中通 28/3093% 2071402071902
韵达 0 29/29100%,固定提前)
安能 31/31100% 0

关键结论:

  • 出库大头日 ≈ 实到峰值日154/158 一致97.5%)——"出库日"基本等于"这批货实际到的那天"。
  • "提前提交"的批次(中通 071402 出库 7/15、071902 出库 7/20在出库时间上如实体现真实归属日。
  • 四站应到文件的「出库时间」字段非空率 100%,且已完整保留在 PG expected_record.raw JSONB 中。

四、代码改动

4.1 数据层

  • schema.sqlexpected_record 新增 out_date DATE(运单出库日)、batch_out_date DATE(批次归属日)+ idx_expected_out_date / idx_expected_batch_out_date 索引。
  • store.py
    • _ingest_expected:解析「出库时间」写 out_date;按交接单号聚合出库日众数(并列取较早)写 batch_out_date
    • 新增 _batch_out_date_map() 辅助函数。
    • 新增 backfill_out_date() + CLI 子命令 backfill-out-date,历史数据一次性回填。

4.2 比对层

  • db_compare.py
    • 新增 compare_site_outdate(site, target_date):应到驱动入口,WHERE batch_out_date = target_date 取批次 → 展开 → 比对。
    • 保留 compare_site_date()(实到驱动)作对照,不删除。
    • _target_date_for() 改为默认取今天(不再依赖 actual_offset
    • build_full_report() 改用 compare_site_outdate
  • runtime.py_site_undelivered_handler 切到应到驱动,锚点日期默认今天。
  • cli/server.pyPOST /compare 切到应到驱动。

五、实施与验证

5.1 数据迁移

python -m inbound_verify.store init                 # 建表/补列(幂等)
python -m inbound_verify.store backfill-out-date     # 历史回填

回填结果:

  • out_date:顺心 3290 / 中通 5419 / 韵达 1640 / 安能 3459 条,共 13808 条。
  • batch_out_date:顺心 93 / 中通 35 / 韵达 32 / 安能 35 个批次。
  • 抽样核对 PG out_date vs 归档 Excel 出库日一致率 96~100%。

5.2 批次归属验证

批次 下载日 batch_out_date 预期
中通 ...071401 7/14 7/14 正常
中通 ...071402 7/14 7/15 提前提交归位
中通 ...071901 7/19 7/19 正常
中通 ...071902 7/19 7/20 提前提交归位
韵达 ...07312001 7/31 8/1 固定 +1
顺心/安能 = 下载日 无扰动

5.3 回溯对照7/02~7/31

新应到驱动 vs 旧实到驱动,差异方向符合设计:

  • 旧驱动混入历史批次(如中通 7/12 旧 236 件 vs 新 11 件;顺心 7/13 旧 59 vs 新 1
  • 新驱动只统计出库日=当天批次,数字更聚焦。
  • 个别日期新驱动未到偏大(如韵达 7/03、安能 7/29属"当天出库、次日扫描"的真实差缺口径。

5.4 接口联调(真实后端)

用例 结果
POST /compare 韵达 2026-08-02 批次 1 个(...08012001),差缺 2 件/2 单(988350756988415586),历史批次不再混入
POST /compare 中通 2026-07-15 提前提交批次 ...071402 正确归位到 7/15
__compare__/compare 全站汇总 2026-08-01 顺心 17 件 / 中通 23 件 / 韵达 0 件 / 安能 0 件,合计 40 件,报表正常生成

六、待确认 / 遗留事项

  • out_date / batch_out_date 依赖站点「出库时间」字段语义(当前按"货物实际发出时间"处理,已与业务确认)。
  • 批次内出库日并列众数取较早(已确认)。
  • "无应到"时报表直接写(如实呈现,无特殊文案,已确认)。
  • 实到驱动入口保留作对照(已确认)。
  • docs/2026-08-02-未到统计重构讨论纪要与下一步.md 中记录的 18:28 直入入库等链路疑点,本重构未处理,留待后续。

七、附:涉及文件

文件 说明
schema.sql 表结构:新增 out_date / batch_out_date
inbound_verify/store.py 入库解析 + 历史回填
inbound_verify/db_compare.py 应到驱动比对入口(保留实到驱动对照)
inbound_verify/runtime.py 未到任务切到应到驱动
inbound_verify/cli/server.py /compare API 切到应到驱动