Admin:多件档口入库码按件创建顺运宝明细回写 #250

Open
opened 2026-08-17 15:00:07 +08:00 by ila · 2 comments
Owner

基本信息

  • 类型:缺陷
  • 父级大工单:#14
  • 所属 MVP / 版本:#224 / 档口入库码回写 MVP
  • 阶段:多件商品按件分明细回写修正

要解决什么

#240 根据当时客户确认,把同一“业务日期 + 订单号 + 档口 + 规格”的多个单件入库码用英文逗号连接,并把完整字符串写入一个顺运宝商品明细的 innerExpCode。真实操作发现顺运宝不允许在“快递单号”中填写逗号连接的多个码,因此该远端回写假设不成立。

对用户提供的多件操作 HAR 做脱敏结构分析后确认:

  1. 原顺运宝商品明细数量为 2,第一件入库码已保存在原明细;
  2. 网页调用 POST /am/stock/detail/createDetail,以 productQty=1、productPrice=0、productSpec=null 新增“档口第2件”占位明细;
  3. 创建接口返回新 detailId,刷新详情后明细数增加,原商品数量和订单金额不变;
  4. 网页再调用 POST /am/stock/detail/updateDetailCode,���第二个码写入新明细;
  5. 最终复读确认两个码分别存在于两条明细。

当前 applyClaimedInnerCode 仍会把逗号聚合值写入原 detail_id;如果原明细已有第一个目标码,还会先删除它。当前顺运宝客户端对 updateDetailCode 使用 GET,也与 HAR 中的 POST 不一致。

复现:

  1. 导入同一业务键、顺运宝商品数量为 2、Excel 含两个不同单件入库码的数据;
  2. 完成“匹配顺运宝商品”并执行回写;
  3. Admin 尝试把 码1,码2 写入原商品明细;
  4. 顺运宝不能按两个单件码使用,操作员只能手工新增一条商品明细,再把第二个码写入新明细。

做什么 / 不做什么

  • 做:
    • 保留现有一条业务记录和逗号聚合的 inner_code,仅把它作为本地单件码列表,远端不再接收聚合字符串。
    • 回写前严格拆分并校验单件码;多件记录要求“不同单件码数量、Excel 源行数量、匹配到的顺运宝商品数量”一致,不一致时不发送远端写请求。
    • 原商品明细承载一件入库码;每个额外入库码通过 createDetail 创建一条数量 1、价格 0、无规格的占位明细,再写入返回的 detailId。
    • 原明细或同一货运单其他明细已经存在某个目标码时直接复用,禁止删除再搬移,也禁止重复创建。
    • 新增明细使用可追踪且不会和同货运单其他业务记录冲突的稳定标题,例如 档口第2件-IC<记录ID>。
    • 在现有 syb_inner_code_records 增加一个 JSON 检查点字段,记录每个单件码、目标 detailId、明细来源和执行状态;每个远端步骤前后及时落库。
    • 创建或写码结果未知时进入 needs_check,绝不自动重发;重新核对读取整张货运单,识别人工已添加或先前已成功的明细,并只更新本地核对结果。
    • 回写确认和结果提示展示单件码数量、预计新增明细数及部分完成/需核对原因。
    • 补充接口、服务、迁移、异常恢复和页面回归测试。
  • 不做:
    • 不改变现有业务键、Excel 格式、导入入口和单表业务模型,不新增批次表或明细业务表。
    • 不修改原顺运宝商品的数量、价格、标题、规格或采购字段;HAR 表明新增占位明细不需要把原数量减 1。
    • 不自动删除人工新增的顺运宝商品,不自动付款,不改变采购和 Client 接口。
    • 不对超时、5xx、响应损坏或 Admin 中断后的未知远端操作自动重试。

怎么做

  • admin/repository/mysql_db.go:增加下一版 MySQL 迁移,在 syb_inner_code_records 追加可空 JSON 检查点字段(建议名 remote_items_json),补充迁移重放和 schema 自检;不新建业务表。
  • admin/model/inner_code.go、admin/repository/inner_code.go:增加单件远端执行项模型、JSON 读写和步骤检查点更新;detail_id 继续表示原始匹配明细,remote_inner_code 仅保留可读汇总。
  • admin/syb/client.go:
    • 增加 CreateInnerCodeDetail,固定调用 POST /am/stock/detail/createDetail,请求体为 id=null、稳定标题、productSpec=null、productQty=1、productPrice=0、stockId,并校验返回正整数 detailId;
    • UpdateDetailCode 按 HAR 改为 POST,stockId/detailId/code/t 继续放查询参数,t 使用当前毫秒时间戳;
    • 两个接口都只发送一次,并沿用 ErrWriteResultUnknown 分类。
  • admin/service/inner_code_match.go:匹配时保存原始目标并校验多件码数量与顺运宝 productQty,数量不一致时明确跳过;不在匹配阶段创建远端明细。
  • admin/service/inner_code_apply.go:
    • 先读取整张货运单,把已存在的目标码唯一映射到明细;
    • 保留原明细中的任一目标码,空原明细才写入第一个缺失码;
    • 其余缺失码逐件创建稳定标题的占位明细、保存返回 ID、写码并复读;
    • 任一步未知立即停止该���务记录,保存已确认的单件结果,不自动重放;
    • RecheckInnerCode 改为核验所有目标码是否各出现一次,并可识别人工已完成的额外明细。
  • admin/handler/web/inner_code.go、admin/templates/inner_code/list.html:确认提示和批次结果增加“共 N 个码 / 新增 M 条明细 / 已完成 K 件”的可读反馈,不增加新按钮。
  • 更新 docs/admin/03-data-model.md、docs/admin/08-顺运宝接口.md,明确本地聚合与远端逐件明细的区别,并记录 #240 的远端假设已被本工单替代。

验收标准

  • 单件记录继续只使用原 detail_id,写前核验、最多一次写入和写后复读行为不退化。
  • 数量 2、原明细为空时:第一个码写入原明细,只创建一条零价占位明细并写入第二个码;原商品数量和字段不被修改。
  • 数量 2、原明细已经是第一个目标码时:不删除、不重复写原码,只创建一条占位明细并写第二个码。
  • 三件及以上时只创建 码数 - 1 条占位明细,每个目标码在同一货运单中恰好出现一次。
  • 同一货运单已有人工添加且包含目标码的明细时直接识别为已完成,不重复创建或写入。
  • 单件码数、源行数或顺运宝商品数量不一致,以及目标码重复出现在多个明细时,远端零写入并显示明确原因。
  • createDetail 使用 HAR 确认的 POST JSON 契约;updateDetailCode 使用 POST 查询参数契约,并校验请求只发送一次。
  • 创建明细或写码明确失败时保存逐件结果;结果未知时转 needs_check,后台、重启恢复和重新核对均不自动重发。
  • Admin 在创建成功后中断,重新核对能依据检查点和稳定标题找回明细,不会再次创建“第2件”。
  • MySQL 旧版本升级、空库、重复迁移及 schema 自检通过;回退旧代码时新增 JSON 字段可安全保留。
  • 页面确认文案能说明预计新增明细数量,批次结果能区分全部完成、部分完成和需核对。
  • 固定 Go 1.23.0 的定向测试、全量测试、build、vet 和 git diff --check 通过。

怎么验证

在仓库根目录执行:

$env:GOTOOLCHAIN='go1.23.0'
Set-Location admin
go test ./service ./repository ./syb ./handler/web -run InnerCode -count=1
go test ./... -count=1
go build ./...
go vet ./...
Set-Location ..
git diff --check
Remove-Item Env:GOTOOLCHAIN

使用 httptest 模拟 HAR 中的创建、列表复读和写码顺序,覆���单件、两件、三件、已有人工明细、创建超时、写码超时和进程中断。真实顺运宝验收只选择专用测试货运单,先验证一条两件记录,再允许批量回写;HAR、Cookie、账号、收件信息和原始响应不得写入测试日志、Gitea 或文档。

风险和回退

  • 风险:createDetail 会在顺运宝真实增加商品明细;虽然 HAR 中数量 1、价格 0 的占位明细没有改变订单金额,但结果未知时重复创建会产生多余明细。因此必须在远端步骤前后保存检查点、使用稳定标题,并保持未知结果禁止自动重试。
  • 风险:同一货运单可能有多个多件商品,统一使用“档口第2件”会发生碰撞,因此标题必须带本地记录标识;页面展示该标识属于预期行为。
  • 风险:把 updateDetailCode 从 GET 改为 POST 需要通过假服务契约测试并先做单条真实验收,不能直接用大批生产货运单验证。
  • 回退:停止新的多件回写并回退服务代码;新增 JSON 字段和已保存检查点留在数据库,不执行逆向迁移。已经在顺运宝创建或写入的明细不自动删除,由“重新核对”列出后人工处理;单件回写仍可按旧流程使用。
## 基本信息 - 类型:缺陷 - 父级大工单:#14 - 所属 MVP / 版本:#224 / 档口入库码回写 MVP - 阶段:多件商品按件分明细回写修正 ## 要解决什么 #240 根据当时客户确认,把同一“业务日期 + 订单号 + 档口 + 规格”的多个单件入库码用英文逗号连接,并把完整字符串写入一个顺运宝商品明细的 `innerExpCode`。真实操作发现顺运宝不允许在“快递单号”中填写逗号连接的多个码,因此该远端回写假设不成立。 对用户提供的多件操作 HAR 做脱敏结构分析后确认: 1. 原顺运宝商品明细数量为 2,第一件入库码已保存在原明细; 2. 网页调用 `POST /am/stock/detail/createDetail`,以 `productQty=1`、`productPrice=0`、`productSpec=null` 新增“档口第2件”占位明细; 3. 创建接口返回新 `detailId`,刷新详情后明细数增加,原商品数量和订单金额不变; 4. 网页再调用 `POST /am/stock/detail/updateDetailCode`,���第二个码写入新明细; 5. 最终复读确认两个码分别存在于两条明细。 当前 `applyClaimedInnerCode` 仍会把逗号聚合值写入原 `detail_id`;如果原明细已有第一个目标码,还会先删除它。当前顺运宝客户端对 `updateDetailCode` 使用 GET,也与 HAR 中的 POST 不一致。 复现: 1. 导入同一业务键、顺运宝商品数量为 2、Excel 含两个不同单件入库码的数据; 2. 完成“匹配顺运宝商品”并执行回写; 3. Admin 尝试把 `码1,码2` 写入原商品明细; 4. 顺运宝不能按两个单件码使用,操作员只能手工新增一条商品明细,再把第二个码写入新明细。 ## 做什么 / 不做什么 - 做: - 保留现有一条业务记录和逗号聚合的 `inner_code`,仅把它作为本地单件码列表,远端不再接收聚合字符串。 - 回写前严格拆分并校验单件码;多件记录要求“不同单件码数量、Excel 源行数量、匹配到的顺运宝商品数量”一致,不一致时不发送远端写请求。 - 原商品明细承载一件入库码;每个额外入库码通过 `createDetail` 创建一条数量 1、价格 0、无规格的占位明细,再写入返回的 `detailId`。 - 原明细或同一货运单其他明细已经存在某个目标码时直接复用,禁止删除再搬移,也禁止重复创建。 - 新增明细使用可追踪且不会和同货运单其他业务记录冲突的稳定标题,例如 `档口第2件-IC<记录ID>`。 - 在现有 `syb_inner_code_records` 增加一个 JSON 检查点字段,记录每个单件码、目标 `detailId`、明细来源和执行状态;每个远端步骤前后及时落库。 - 创建或写码结果未知时进入 `needs_check`,绝不自动重发;重新核对读取整张货运单,识别人工已添加或先前已成功的明细,并只更新本地核对结果。 - 回写确认和结果提示展示单件码数量、预计新增明细数及部分完成/需核对原因。 - 补充接口、服务、迁移、异常恢复和页面回归测试。 - 不做: - 不改变现有业务键、Excel 格式、导入入口和单表业务模型,不新增批次表或明细业务表。 - 不修改原顺运宝商品的数量、价格、标题、规格或采购字段;HAR 表明新增占位明细不需要把原数量减 1。 - 不自动删除人工新增的顺运宝商品,不自动付款,不改变采购和 Client 接口。 - 不对超时、5xx、响应损坏或 Admin 中断后的未知远端操作自动重试。 ## 怎么做 - `admin/repository/mysql_db.go`:增加下一版 MySQL 迁移,在 `syb_inner_code_records` 追加可空 JSON 检查点字段(建议名 `remote_items_json`),补充迁移重放和 schema 自检;不新建业务表。 - `admin/model/inner_code.go`、`admin/repository/inner_code.go`:增加单件远端执行项模型、JSON 读写和步骤检查点更新;`detail_id` 继续表示原始匹配明细,`remote_inner_code` 仅保留可读汇总。 - `admin/syb/client.go`: - 增加 `CreateInnerCodeDetail`,固定调用 `POST /am/stock/detail/createDetail`,请求体为 `id=null`、稳定标题、`productSpec=null`、`productQty=1`、`productPrice=0`、`stockId`,并校验返回正整数 `detailId`; - `UpdateDetailCode` 按 HAR 改为 POST,`stockId/detailId/code/t` 继续放查询参数,`t` 使用当前毫秒时间戳; - 两个接口都只发送一次,并沿用 `ErrWriteResultUnknown` 分类。 - `admin/service/inner_code_match.go`:匹配时保存原始目标并校验多件码数量与顺运宝 `productQty`,数量不一致时明确跳过;不在匹配阶段创建远端明细。 - `admin/service/inner_code_apply.go`: - 先读取整张货运单,把已存在的目标码唯一映射到明细; - 保留原明细中的任一目标码,空原明细才写入第一个缺失码; - 其余缺失码逐件创建稳定标题的占位明细、保存返回 ID、写码并复读; - 任一步未知立即停止该���务记录,保存已确认的单件结果,不自动重放; - `RecheckInnerCode` 改为核验所有目标码是否各出现一次,并可识别人工已完成的额外明细。 - `admin/handler/web/inner_code.go`、`admin/templates/inner_code/list.html`:确认提示和批次结果增加“共 N 个码 / 新增 M 条明细 / 已完成 K 件”的可读反馈,不增加新按钮。 - 更新 `docs/admin/03-data-model.md`、`docs/admin/08-顺运宝接口.md`,明确本地聚合与远端逐件明细的区别,并记录 #240 的远端假设已被本工单替代。 ## 验收标准 - [ ] 单件记录继续只使用原 `detail_id`,写前核验、最多一次写入和写后复读行为不退化。 - [ ] 数量 2、原明细为空时:第一个码写入原明细,只创建一条零价占位明细并写入第二个码;原商品数量和字段不被修改。 - [ ] 数量 2、原明细已经是第一个目标码时:不删除、不重复写原码,只创建一条占位明细并写第二个码。 - [ ] 三件及以上时只创建 `码数 - 1` 条占位明细,每个目标码在同一货运单中恰好出现一次。 - [ ] 同一货运单已有人工添加且包含目标码的明细时直接识别为已完成,不重复创建或写入。 - [ ] 单件码数、源行数或顺运宝商品数量不一致,以及目标码重复出现在多个明细时,远端零写入并显示明确原因。 - [ ] `createDetail` 使用 HAR 确认的 POST JSON 契约;`updateDetailCode` 使用 POST 查询参数契约,并校验请求只发送一次。 - [ ] 创建明细或写码明确失败时保存逐件结果;结果未知时转 `needs_check`,后台、重启恢复和重新核对均不自动重发。 - [ ] Admin 在创建成功后中断,重新核对能依据检查点和稳定标题找回明细,不会再次创建“第2件”。 - [ ] MySQL 旧版本升级、空库、重复迁移及 schema 自检通过;回退旧代码时新增 JSON 字段可安全保留。 - [ ] 页面确认文案能说明预计新增明细数量,批次结果能区分全部完成、部分完成和需核对。 - [ ] 固定 Go 1.23.0 的定向测试、全量测试、build、vet 和 `git diff --check` 通过。 ## 怎么验证 在仓库根目录执行: ```powershell $env:GOTOOLCHAIN='go1.23.0' Set-Location admin go test ./service ./repository ./syb ./handler/web -run InnerCode -count=1 go test ./... -count=1 go build ./... go vet ./... Set-Location .. git diff --check Remove-Item Env:GOTOOLCHAIN ``` 使用 `httptest` 模拟 HAR 中的创建、列表复读和写码顺序,覆���单件、两件、三件、已有人工明细、创建超时、写码超时和进程中断。真实顺运宝验收只选择专用测试货运单,先验证一条两件记录,再允许批量回写;HAR、Cookie、账号、收件信息和原始响应不得写入测试日志、Gitea 或文档。 ## 风险和回退 - 风险:`createDetail` 会在顺运宝真实增加商品明细;虽然 HAR 中数量 1、价格 0 的占位明细没有改变订单金额,但结果未知时重复创建会产生多余明细。因此必须在远端步骤前后保存检查点、使用稳定标题,并保持未知结果禁止自动重试。 - 风险:同一货运单可能有多个多件商品,统一使用“档口第2件”会发生碰撞,因此标题必须带本地记录标识;页面展示该标识属于预期行为。 - 风险:把 `updateDetailCode` 从 GET 改为 POST 需要通过假服务契约测试并先做单条真实验收,不能直接用大批生产货运单验证。 - 回退:停止新的多件回写并回退服务代码;新增 JSON 字段和已保存检查点留在数据库,不执行逆向迁移。已经在顺运宝创建或写入的明细不自动删除,由“重新核对”列出后人工处理;单件回写仍可按旧流程使用。
Author
Owner

???:?? HAR ?? createDetail / updateDetailCode ? POST ??,?? MySQL v27 remote_items_json ???????????????????/????????????????????????????????????????

???:?? HAR ?? createDetail / updateDetailCode ? POST ??,?? MySQL v27 remote_items_json ???????????????????/????????????????????????????????????????
Author
Owner

????,??:????

????,??:???? - ????:`b8f49fe` fix: ??????????? (#250) - ????:`103610a` docs: ???? #250 - ??:`docs/task/250-???????????.md` - ??:Go 1.23.0 ??????`go test ./... -count=1`?`go build ./...`?`go vet ./...`?`git diff --check` ????? - ???:??????????????????,???????? MySQL ?? v27?
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: chengma/cmautobuy#250