docs: finalize actual-arrival design as full-day scans, zero processing

This commit is contained in:
Misaka_Company
2026-08-04 17:57:21 +08:00
parent c708bff924
commit 8e656516ea

View File

@@ -2,7 +2,7 @@
> 日期2026-08-04 > 日期2026-08-04
> 分支:`refactor/undelivered-by-expected` > 分支:`refactor/undelivered-by-expected`
> 状态:待审核 > 状态:已实施2026-08-04 验证通过)
> 目标:把差缺对比中的「实到货物数据」提取口径修正为「目标归属日当天实际扫描」,与业务口径对齐 > 目标:把差缺对比中的「实到货物数据」提取口径修正为「目标归属日当天实际扫描」,与业务口径对齐
--- ---
@@ -13,8 +13,9 @@
1. **应到货物数据**:取**归属日 = D** 的应到批次(批次归属日 = 出库大头日,已实现为 `expected_record.batch_out_date`)。 1. **应到货物数据**:取**归属日 = D** 的应到批次(批次归属日 = 出库大头日,已实现为 `expected_record.batch_out_date`)。
- 站点"提前下载"(韵达固定提前 1 天、个别站点偶发提前 1~2 天)不影响取数——提前提交的批次按其**出库日**自动归属到 D 日。 - 站点"提前下载"(韵达固定提前 1 天、个别站点偶发提前 1~2 天)不影响取数——提前提交的批次按其**出库日**自动归属到 D 日。
2. **实到货物数据**:取 **D 日当天实际扫描**的记录(`actual_record.scan_time::date = D` 2. **实到货物数据**:取 **D 日当天实际扫描**的记录(`actual_record.scan_time::date = D`**全量、零加工**
- "当天实际扫描"指扫描行为发生在 D 日,与运单属于哪个批次无关。 - "当天实际扫描"指扫描行为发生在 D 日,与运单属于哪个批次无关。
- 重复单号在入库时即被吸收(`actual_record` 唯一键 `(site, piece_no)` + upsert对比层不再做任何加工。
3. 对取到的双方数据按运单号进行差缺对比。 3. 对取到的双方数据按运单号进行差缺对比。
**关键原则**:说"同一天"指的是**归属日期**,不是数据产生/下载的日期。 **关键原则**:说"同一天"指的是**归属日期**,不是数据产生/下载的日期。
@@ -39,30 +40,32 @@
## 三、修正方案 ## 三、修正方案
### 3.1 实到提取统一加扫描日过滤 ### 3.1 实到提取统一为「目标日当天扫描全量」
| 函数 | 用途 | 改动 | | 函数 | 用途 | 改动 |
|------|------|------| |------|------|------|
| `compare_site_outdate` | 汇总报表(应到驱动,主入口) | 实到 SQL 增加 `AND scan_time::date = %s`D | | `compare_site_outdate` | 汇总报表(应到驱动,主入口) | 实到 SQL 改为 `WHERE site=%s AND scan_time::date=%s`,取当天扫描**全量**(不再按批次运单过滤 |
| `compare_site_date` | 实到驱动对照模式 | 同上加过滤Step 4Step 1 锚点本已按当天扫描) | | `compare_site_date` | 实到驱动对照模式 | 同上Step 1 锚点本已按当天扫描Step 4 同步为全量口径 |
| `compare_site_batch` | 单批次审计(无日期语境) | **保持全量**docstring 注明"全批次全量实到,不受日期过滤" | | `compare_site_batch` | 单批次审计(无日期语境) | **保持全量**docstring 注明"全批次全量实到,不受日期过滤" |
修正后统计口径: 修正后统计口径:
``` ```
应到 = 归属日 D 的批次全量应到(交接件数,不变) 应到 = 归属日 D 的批次全量应到(交接件数,不变)
实到 = 批次运单 ∩ 扫描日 = D 的扫描件数(非 SF 子单号去重 / SF 行计数,不变 实到 = D 日当天实际扫描的全量记录(零加工
未到 = max(0, 应到 实到) 未到 = max(0, 应到 实到)(件级汇总);差缺明细按运单匹配(足额/溢到跳过)
``` ```
**去重说明**:单号去重已在入库时完成——`schema.sql``actual_record``UNIQUE(site, piece_no)``store.py` 以 ON CONFLICT DO UPDATE 写入(韵达另有 drop_duplicates。对比层拿到的实到本就是去重后的数据不再做任何额外加工。
### 3.2 边界语义确认 ### 3.2 边界语义确认
| 场景 | 修正后行为 | | 场景 | 修正后行为 |
|------|-----------| |------|-----------|
| 批次 D 的件扫描于 D+1迟到件 | 计入 D 日实到 → D 日计"未到";该件属 D+1 日实到(其运单若在 D+1 批次内则正常核销) | | 批次 D 的件扫描于 D+1迟到件 | 计入 D+1 日实到(其扫描日在 D+1D 日差缺按运单匹配判定,未到件照常呈现 |
| 批次 D 的件提前扫描于 D1 | 计入 D 日实到 | | 批次 D 的件提前扫描于 D1 | 计入 D1 日实到(扫描日为准),不入 D 日实到 |
| 当天扫描但运单不在 D 日应到批次(孤儿) | 入 D 日比对(属其他归属日批次,与现状一致) | | 当天扫描但运单不在 D 日应到批次(孤儿) | 仍计入 D 日实到件数(实到=当天全量);差缺明细按运单匹配,无对应应到运单则不出现 |
| 一件多扫(同日) | 非 SF 按子单号去重SF 行计数(不变) | | 一件多扫(同日) | 入库唯一键 `(site, piece_no)` 已吸收重复,对比层零加工 |
### 3.3 不做的事(范围外) ### 3.3 不做的事(范围外)
@@ -76,24 +79,34 @@
| 文件 | 改动 | | 文件 | 改动 |
|------|------| |------|------|
| `inbound_verify/db_compare.py` | `compare_site_outdate``compare_site_date` 两处实到 SQL `AND scan_time::date = %s``compare_site_batch` docstring 注明口径 | | `inbound_verify/db_compare.py` | `compare_site_outdate``compare_site_date` 两处实到 SQL 改为 `scan_time::date = 目标日` 全量取数`compare_site_batch` docstring 注明口径差异;`_do_compare` 实到件数 = 实到记录全量 |
仅此一处文件、两处 SQL + 一处注释 仅此一处文件;无需 schema 改动(去重本已由入库唯一键保证)
--- ---
## 五、验证计划 ## 五、验证结果2026-08-04 已重跑)
1. **重跑 08-03 全站汇总**`build_full_report("2026-08-03")`,核对 按新口径重跑 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 报表实到/已到明细中。 | 顺心 | 147 | 128 | 19 |
| 中通 | 305 | 276 | 29 |
| 韵达 | 54 | 53 | 1 |
| 安能 | 351 | **355**= 下载文件 355 行,零加工) | 0 |
08-04同为全量口径顺心 134、中通 214、韵达 102、安能 176。
- 安能 08-03 实到 355 与 `安能-实到货物数据.xlsx` 完全一致,验证"实到=当天扫描全量、零加工"成立。
- 差缺明细各运单"已到单号"扫描日全部 = 08-03。
- 报表已输出:`InboundVerify/output/应到未到数据.xlsx`
--- ---
## 六、决策记录(待确认) ## 六、决策记录
- ✅ 实到 = 归属日当天实际扫描(`scan_time::date = D`跨日扫描不计入 - ✅ 实到 = 归属日当天实际扫描的全量`scan_time::date = D`对比时零加工
- ✅ 单号去重由入库唯一键保证(`UNIQUE(site, piece_no)` + upsert对比层不重复去重。
-`compare_site_batch` 保持全批次全量(审计工具语义,不按日过滤)。 -`compare_site_batch` 保持全批次全量(审计工具语义,不按日过滤)。
- ⏳ 其余边界(迟到件计"未到"的呈现、获取层日期回读校验)按上表执行,如有异议请指出 - ✅ 差缺明细按运单匹配,足额/溢到跳过,未到件 = max(0, 应到 实到)