From a4ffa27ba91759f4ce852c9bafc0d9f7970bb473 Mon Sep 17 00:00:00 2001 From: chengma Date: Sat, 15 Aug 2026 08:47:51 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=BD=92=E6=A1=A3=E4=BB=BB=E5=8A=A1=20?= =?UTF-8?q?#231?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/task/231-档口入库码单表导入.md | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 docs/task/231-档口入库码单表导入.md diff --git a/docs/task/231-档口入库码单表导入.md b/docs/task/231-档口入库码单表导入.md new file mode 100644 index 0000000..e96462a --- /dev/null +++ b/docs/task/231-档口入库码单表导入.md @@ -0,0 +1,54 @@ +# 231 Admin:档口入库码单表迁移与 Excel 幂等导入 + +- 类型:需求 +- 父级大工单:#14 +- 所属 MVP / 版本:#224 +- 状态:已完成 +- 日期:2026-08-15 +- Gitea 工单: + +## 背景与目标 + +把线下档口 Excel 从一次性载体转换为 Admin 可追踪的业务记录,为后续确定性匹配和安全 +回写提供数据基础,同时保持用户确认的“一张业务表”边界。 + +## 最终方案 + +- MySQL schema v23 只增加 `syb_inner_code_records`,保存导入原字段、匹配快照、回写状态 + 和操作账号,不增加批次表、尝试表,也不保存 Excel 原文件或哈希。 +- Excel 固定读取“标签入库码映射”,在前 10 行定位表头,兼容组合或拆分的档口字段和两种 + 规格表头。单次限制 10MB、5000 行,并校验字段长度和同日入库码唯一性。 +- 业务键为日期、订单号、档口及货号、标准化规格。重复业务组压成一行并记录重复数量, + 供后续匹配整组跳过;重复导入不覆盖已经回写或需要核对的审计状态。 +- 当前生产基线固定 MySQL 8.4,因此没有扩展历史 SQLite 运行时 schema。 + +## 改了哪些 + +- `admin/repository/mysql_db.go`:追加 v23 可重放迁移和结构自检。 +- `admin/model/inner_code.go`:增加单表状态、记录和导入模型。 +- `admin/repository/inner_code.go`:增加事务内按业务键锁定的幂等写入。 +- `admin/service/inner_code_import.go`:增加上传校验、Excel 解析、规格标准化和事务编排。 +- `admin/service/inner_code_import_test.go`:覆盖规格清洗、表头、重复和冲突。 +- `docs/admin/03-data-model.md`:记录 v23 单表约束和状态。 + +## 验收结果 + +| 验收标准 | 结果 | +|---|---| +| v23 迁移可重放并在自检成功后记录版本 | 通过(代码与全量测试);真实 MySQL 见未验证项 | +| 合法 Excel 幂等写入且重复业务键不新增第二行 | 通过 | +| 已完成/需核对记录重复导入不丢失远端审计状态 | 通过(SQL 条件更新) | +| 文件类型、大小、行数、必填字段和长度错误可读 | 通过 | +| 覆盖规格标准化、重复键和同日入库码冲突 | 通过 | + +## 测试 + +- 执行的命令:`go test ./service ./repository -run InnerCode -count=1`; + `go test ./... -count=1`;`go vet ./...` +- 结果:全部通过。 +- **没验证到的部分**:本机没有另行提供以 `_test` 结尾的 MySQL 8.4 隔离测试库,未执行 + v22 真实库升级和重复迁移;没有使用含商业数据的原始 Excel,只使用代码生成的脱敏工作簿。 + +## 相关提交 + +- `5a9c0f0` feat: 增加档口入库码单表导入 (#231)