From db06776ff732a7f9ab5fc289da01877d5f04c132 Mon Sep 17 00:00:00 2001 From: Misaka_Company Date: Tue, 4 Aug 2026 17:04:03 +0800 Subject: [PATCH] docs: design for actual-arrival extraction by scan date --- .../2026-08-04-实到按扫描日提取修正-design.md | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 docs/2026-08-04-实到按扫描日提取修正-design.md diff --git a/docs/2026-08-04-实到按扫描日提取修正-design.md b/docs/2026-08-04-实到按扫描日提取修正-design.md new file mode 100644 index 0000000..8065d5b --- /dev/null +++ b/docs/2026-08-04-实到按扫描日提取修正-design.md @@ -0,0 +1,99 @@ +# 实到按「归属日当天扫描」提取修正 · 设计方案 + +> 日期:2026-08-04 +> 分支:`refactor/undelivered-by-expected` +> 状态:待审核 +> 目标:把差缺对比中的「实到货物数据」提取口径修正为「目标归属日当天实际扫描」,与业务口径对齐 + +--- + +## 一、业务口径(与业务部门对齐后的最终陈述) + +差缺对比在**归属日期(业务日期)D** 这一维度上进行: + +1. **应到货物数据**:取**归属日 = D** 的应到批次(批次归属日 = 出库大头日,已实现为 `expected_record.batch_out_date`)。 + - 站点"提前下载"(韵达固定提前 1 天、个别站点偶发提前 1~2 天)不影响取数——提前提交的批次按其**出库日**自动归属到 D 日。 +2. **实到货物数据**:取 **D 日当天实际扫描**的记录(`actual_record.scan_time::date = D`)。 + - "当天实际扫描"指扫描行为发生在 D 日,与运单属于哪个批次无关。 +3. 对取到的双方数据按运单号进行差缺对比。 + +**关键原则**:说"同一天"指的是**归属日期**,不是数据产生/下载的日期。 + +--- + +## 二、现状问题 + +| 环节 | 现状 | 问题 | +|------|------|------| +| 应到提取 | `WHERE batch_out_date = D`(应到驱动入口) | ✅ 已对齐 | +| 实到提取 | `WHERE waybill_no = ANY(批次运单)`,**无扫描日过滤** | ❌ 跨日扫描混入 | + +**实证案例(安能 08-03)**: +- 08-03 实到下载文件 = 355 行,全部扫描于 08-03(获取层正确); +- 今天 15:03 另有一次 08-04 实到下载(176 行),其中 **6 件扫描于 08-04、运单属于 08-03 批次**; +- 对比 SQL 按运单号取实到 → 08-03 实到 = 350(当天)+ 6(次日)= **356**,与"当天实际扫描"定义不符。 + +根因:`db_compare.py` 三处取实到的 SQL 只按运单号匹配,未按扫描日过滤。 + +--- + +## 三、修正方案 + +### 3.1 实到提取统一加扫描日过滤 + +| 函数 | 用途 | 改动 | +|------|------|------| +| `compare_site_outdate` | 汇总报表(应到驱动,主入口) | 实到 SQL 增加 `AND scan_time::date = %s`(D) | +| `compare_site_date` | 实到驱动对照模式 | 同上加过滤(Step 4;Step 1 锚点本已按当天扫描) | +| `compare_site_batch` | 单批次审计(无日期语境) | **保持全量**,docstring 注明"全批次全量实到,不受日期过滤" | + +修正后统计口径: + +``` +应到 = 归属日 D 的批次全量应到(交接件数,不变) +实到 = 批次运单 ∩ 扫描日 = D 的扫描件数(非 SF 子单号去重 / SF 行计数,不变) +未到 = max(0, 应到 − 实到) +``` + +### 3.2 边界语义确认 + +| 场景 | 修正后行为 | +|------|-----------| +| 批次 D 的件扫描于 D+1(迟到件) | 不计入 D 日实到 → D 日计"未到";该件属 D+1 日实到(其运单若在 D+1 批次内则正常核销) | +| 批次 D 的件提前扫描于 D−1 | 不计入 D 日实到 | +| 当天扫描但运单不在 D 日应到批次(孤儿) | 不入 D 日比对(属其他归属日批次,与现状一致) | +| 一件多扫(同日) | 非 SF 按子单号去重,SF 行计数(不变) | + +### 3.3 不做的事(范围外) + +- 下载层各站查询日期口径已验证正确(08-03 四站文件 100% 当天扫描),**不改下载层**。 +- 获取层"日期回读校验"(韵达/中通/顺心选完日期后未校验输入框值)另立改进项,不阻塞本次。 +- 百世为站级日聚合(已扫/应扫,固定当天),不涉及。 + +--- + +## 四、涉及改动清单 + +| 文件 | 改动 | +|------|------| +| `inbound_verify/db_compare.py` | `compare_site_outdate`、`compare_site_date` 两处实到 SQL 加 `AND scan_time::date = %s`;`compare_site_batch` docstring 注明口径 | + +仅此一处文件、两处 SQL + 一处注释。 + +--- + +## 五、验证计划 + +1. **重跑 08-03 全站汇总**(`build_full_report("2026-08-03")`),核对: + - 安能实到 356 → **350**(= 355 当天 − 5 孤儿,或 350 匹配批次),未到件数相应变化; + - 顺心 / 中通 / 韵达先实查 DB 中是否有跨日扫描匹配各自 08-03 批次,预期无变化(各自文件全为 08-03 扫描)。 +2. **明细抽查**:差缺明细表内各运单的"已到单号"扫描日全部 = 08-03。 +3. **口径复核**:安能 6 件 08-04 扫描确认不再出现在 08-03 报表实到/已到明细中。 + +--- + +## 六、决策记录(待确认) + +- ✅ 实到 = 归属日当天实际扫描(`scan_time::date = D`),跨日扫描不计入。 +- ✅ `compare_site_batch` 保持全批次全量(审计工具语义,不按日过滤)。 +- ⏳ 其余边界(迟到件计"未到"的呈现、获取层日期回读校验)按上表执行,如有异议请指出。