# 234 Admin:档口入库码安全回写、核验与异常恢复 - 类型:需求 - 父级大工单:#14 - 所属 MVP / 版本:#224 - 状态:已完成 - 日期:2026-08-15 - Gitea 工单: ## 背景与目标 在操作员明确勾选并二次确认后,把档口入库码安全写入顺运宝商品明细的 `innerExpCode`,并对删除旧值、网络未知结果和 Admin 中断提供保守恢复路径。 ## 最终方案 - `syb.Client` 增加清除旧值和写入新值两个封装;参数先在本地校验,每个动作只发送一次。 网络错误、5xx、响应读取失败或成功响应损坏统一标识为“写入结果未知”。 - 每条记录先用数据库条件状态从 `ready` 原子领取为 `applying`,然后重新读取远端并核对 stock/detail、规格、sku、variationSku、采购字段和规划旧值。任一变化都停止写入。 - 旧值为空时直接写;旧值非空时删除明确成功才写。写入成功响应后再次读取,只有远端值 与目标一致才标为已回写;未知或不一致进入需核对,绝不自动重试。 - “重新核对”只读取 `listByStock`。远端已是目标值时收敛为已回写,否则继续需核对。 - Admin 启动时把遗留 `applying` 改为 `needs_check`,不会在启动过程中发送远端请求。 ## 改了哪些 - `admin/syb/client.go`:增加单次删除/写入接口和未知结果错误分类。 - `admin/repository/inner_code.go`:增加领取、完成、只读核对和启动恢复。 - `admin/service/inner_code_apply.go`:增加写前门禁、删后写、写后核验和批量统计。 - `admin/handler/web/inner_code.go`、`admin/handler/web/web.go`:接通回写和重新核对 POST。 - `admin/main.go`:启动时收敛中断记录。 - `admin/syb/client_test.go`、`admin/service/inner_code_apply_test.go`、 `admin/repository/inner_code_test.go`:覆盖单次请求、安全门禁和恢复。 - `admin/repository/mysql_db_integration_test.go`:增加 v22→v23 隔离 MySQL 测试。 - `docs/admin/08-顺运宝接口.md`:记录两个写接口和禁止重试规则。 ## 验收结果 | 验收标准 | 结果 | |---|---| | 非 ready 或重复领取记录不发送写请求 | 通过(条件领取实现) | | 写前重新核对商品身份、采购字段和旧值 | 通过 | | 空旧值不删;非空旧值删除成功才写;每个动作一次 | 通过 | | 写后复读一致才完成,未知结果不自动重试 | 通过 | | 重新核对只有读取,没有写入 | 通过 | | 重启把 applying 转为 needs_check | 通过 | ## 测试 - 执行的命令:`go test ./syb ./service ./repository ./handler/web -run InnerCode -count=1`; 固定 `GOTOOLCHAIN=go1.23.0` 执行 `go build ./...`、`go test ./... -count=1`、 `go vet ./...`;`git diff --check`。 - 结果:全部通过。假服务端验证了请求路径、参数、单次发送、业务失败和未知结果分类。 - **没验证到的部分**:没有执行真实顺运宝删除/写入;没有提供 `_test` MySQL 8.4 配置, 因此新增的 v22→v23 集成测试已编译但按环境门禁跳过;未测试进程恰好在远端写入瞬间被强杀。 ## 相关提交 - `2778eed` feat: 安全回写档口入库码并支持核验恢复 (#234)