diff --git a/docs/task/240-多件档口入库码合并回写.md b/docs/task/240-多件档口入库码合并回写.md new file mode 100644 index 0000000..b2579a8 --- /dev/null +++ b/docs/task/240-多件档口入库码合并回写.md @@ -0,0 +1,78 @@ +# 240 Admin:同一顺运宝商品多件入库码合并回写 + +- 类型:缺陷 +- 父级大工单:#14 +- 所属 MVP / 版本:#224 / 档口入库码回写 MVP +- 状态:已完成,待用户验收 +- 日期:2026-08-15 +- Gitea 工单: + +## 背景与目标 + +同一个顺运宝商品明细数量大于 1 时,Excel 会按件生成多个不同的档口入库码。原导入器把 +相同日期、订单、档口和规格视为一个业务键,却要求组内入库码完全相同,因此 2026-08-15 +样本第 50、51 行被当成冲突;即使导入成功,匹配器也会因源行数量大于 1 而跳过。 + +本任务把同一顺运宝商品明细的多个单件码稳定连接为一个目标值,只向该明细唯一的 +`innerExpCode` 位置写入一次,同时保留现有确定性匹配、写前核验、写后复读和未知结果 +禁止自动重试等安全边界。 + +## 最终方案 + +- 继续使用 `(business_date, order_number, stall, spec_key)` 作为业务键,不新增表、字段或迁移。 +- 同一业务键按 Excel 源行顺序收集不同入库码,使用英文逗号且不加空格连接;相同码重复行 + 不重复拼接,`source_duplicate_count` 保留合并前源行数。 +- 单个码不得包含英文逗号或控制字符;聚合值不得超过现有数据库和顺运宝客户端共同采用的 + 128 字符上限,超限时在写库前拒绝整批导入,不截断。 +- 导入事务锁定同业务日期的现有记录,拆分已有聚合值并逐个核对单件码归属,防止一个组成码 + 被另一业务键复用。 +- 删除匹配阶段“源行数量大于 1 就跳过”的旧门禁;聚合记录仍必须唯一命中一个未采购的 + 顺运宝商品明细,歧义目标继续跳过。 +- 回写流程无需分支:现有逻辑直接使用完整聚合值完成写前比较、单次写入和写后复读。 +- 导入完成提示改为“同业务键合并 N 行”,不再把正常多件商品称为文件重复。 + +实际实现与建单方案一致。稳定顺序最终采用 Excel 源行顺序;当前文件的件序与源行顺序一致, +且无需为了只在导入阶段排序而增加数据库字段。 + +## 改了哪些 + +- `admin/service/inner_code_import.go`:聚合单件码、分隔符及长度校验、同日已有组成码归属校验。 +- `admin/repository/inner_code.go`:事务内锁定并读取同日现有聚合码。 +- `admin/service/inner_code_match.go`:允许源数量大于 1 的聚合记录继续确定性匹配。 +- `admin/handler/web/inner_code.go`:导入反馈改为同业务键合并行数。 +- `admin/model/inner_code.go`:明确一条记录对应一个顺运宝商品明细及其聚合目标值。 +- `admin/service/inner_code_import_test.go`:覆盖真实问题结构、稳定去重、超长、分隔符和组成码防串单。 +- `admin/service/inner_code_match_test.go`:覆盖聚合记录放行及其他安全阻断保持不变。 +- `admin/service/inner_code_apply_test.go`、`admin/syb/client_test.go`:覆盖完整聚合字符串只写一次、复读一致及 HTTP 参数传输。 +- `docs/admin/03-data-model.md`:记录多件聚合、长度和组成码唯一性规则。 + +## 验收结果 + +| 验收标准 | 结果 | +|---|---| +| 第 50、51 行聚合为 `DK260815A160101,DK260815A160102` | 通过 | +| 多个不同码按源行稳定连接,相同码不重复拼接 | 通过 | +| 聚合值超过 128 字符时在写库前整批失败 | 通过 | +| 聚合记录不再因源数量大于 1 被匹配器跳过 | 通过 | +| 完整聚合值只发送一次,并执行写后复读比较 | 通过(自动化假客户端) | +| 同日组成码不能归属另一业务键 | 通过(服务测试);真实 MySQL 见未验证项 | +| 单件导入、软删除恢复及未知结果禁止重试保持兼容 | 通过(全量回归) | +| 固定 Go 1.23.0 build、test、vet 通过 | 通过 | + +## 测试 + +- 执行的命令: + - `go test ./service ./repository ./syb -run InnerCode -count=1` + - `$env:GOTOOLCHAIN='go1.23.0'; go build ./...; go test ./... -count=1; go vet ./...` + - `git diff --check` +- 结果:定向测试和固定 Go 1.23.0 全量构建、测试、vet 全部通过。另用未提交的临时测试 + 只解析 `raw_data/Shopee线下档口入库码映射_20260815_V3.3-R5.xlsx`:63 个源数据行形成 + 62 条业务记录、合并 1 行,第 50、51 行目标值和数量均符合预期;验证后已删除临时测试, + 商业数据未进入 Git。 +- **没验证到的部分**:未在真实 MySQL 8.4 `_test` 库执行导入事务与并发导入;未向真实顺运宝 + 写入逗号连接值,尚未验证远端字段实际长度、页面展示和复读是否原样保留逗号;未进行浏览器 + 导入操作、生产部署或生产数据修改。 + +## 相关提交 + +- `8e50060` fix: 合并多件档口入库码回写 (#240)