Files
huachuang/docs/superpowers/specs/2026-08-05-empty-box-transport-design.md
2026-08-05 15:34:35 +08:00

102 lines
6.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 空木箱出入库设计规格
## 目标
在 WMS 中增加空木箱入库、出库及任务回调能力。木箱规格统一读取 `wms_boxtype`,实际木箱保存在 `wmw_boxinfo`,仓位通过锁类型避免并发重复分配。
## 方案比较
1. **SQL 完成全部选位与锁定**:数据库往返少,但同规格同排、新排回退和并发重试会形成复杂 SQL后续调整策略困难。
2. **加载全部仓位后由 Java 选位**:规则直观,但仓位量增长后内存和数据库传输成本较高。
3. **SQL 筛选有限候选排Java 执行优先级,条件更新抢锁**:兼顾性能、并发安全和规则可维护性。
采用方案 3。Mapper XML 只返回少量候选排或候选木箱Service 按优先级逐个尝试条件更新;更新行数为 0 时继续下一个候选。
## 数据模型
### 木箱规格表 `wms_boxtype`
字段为:
- `id`:主键。
- `material_code`:木箱规格编码,业务唯一。
- `material_name`:规格名称。
- `lash_num`:捆扎次数。
- `box_length``box_width``box_height`:长、宽、高。
空木箱业务只通过 `material_code` 接收规格,名称、尺寸和捆扎次数均从该表读取,不信任调用方传入的规格属性。
### 木箱实例表 `wmw_boxinfo`
保留现有字段,并增加:
- `status``0` 待入库、`1` 在库、`2` 已出库。
- `out_time`:实际出库完成时间,未出库时为空。
`insert_time` 表示实际入库完成时间。创建入库任务时先生成待入库记录;任务完成后写入实际入库时间并改为在库。出库完成后保留记录,更新状态和出库时间。
### 仓位锁
在字典 `wms_lock_type` 增加:
- `8`:木箱入库锁。
- `9`:木箱出库锁。
锁定时将任务预占码写入 `task_code`,任务创建成功后替换为任务 ID。完成或取消时必须同时清空 `task_code` 并恢复未锁定状态。
## 模块边界
- `nl-module-wms-api`:提供其他模块可调用的 `EmptyBoxApi`、请求对象和响应对象。
- `nl-module-wms-server`:提供控制器、规格和木箱 Mapper、仓位候选 SQL、空木箱领域服务及 `EmptyBoxTask`
- `nl-module-task-api`:复用现有任务创建、下发和目的点未完成任务数接口,不修改任务模块内部业务。
- `nl-module-base-api`:复用编码生成接口,通过规则编码 `BOX_CODE` 生成木箱编码。
任务回调类只转发 `taskId`,完成与取消的事务逻辑封装在空木箱 Service 中。
## 入库流程
1. 接口接收 `deviceCode``materialCode`,校验木箱规格存在。
2. 查询候选排:第一优先级为已经存放同规格空木箱、没有其他规格木箱和实载载具且仍有空仓位的排;第二优先级为整排没有载具的排。
3. 每个候选排只查询一个可用仓位,使用 `lock_type = 1`、载具为空作为条件更新为木箱入库锁。并发抢锁失败时尝试下一候选。
4. 调用 `BOX_CODE` 生成木箱编码,根据规格表属性插入状态为待入库的 `wmw_boxinfo`
5. 创建并下发任务:起点为 `deviceCode`,终点为目标仓位编码,载具编码为新木箱编码,业务处理器为 `EMPTYBOXTASK`
6. 任务完成后,将木箱编码绑定至仓位,数量置为 1仓位解锁木箱状态改为在库并写入实际入库时间。
7. 任务取消后解锁仓位,并物理删除对应的待入库木箱记录。
任一步骤异常都回滚本地事务;远程任务创建或下发失败时抛出业务异常,依赖现有任务回滚接口处理已创建任务。
## 出库流程
1. 接口接收 `materialCode`,只查询状态为在库、已绑定可用仓位且仓位未锁定的同规格木箱。
2.`insert_time` 升序、`box_id` 升序取得有限候选,逐条通过条件更新增加木箱出库锁;并发抢锁失败时继续下一条。
3. 当前临时出库点为 `ZXQ_01``ZXQ_02`。负载计算为“对应点位未完成任务数 + 点位当前占用库存数”,选择负载较小的点位,相同则选择 `ZXQ_01`
4. 点位占用库存数暂由 WMS 内部扩展方法获取。代码保留清晰扩展标记,后续替换为 LMS 接口同时返回候选出库点及其占用情况,不改变空木箱业务主流程。
5. 创建并下发任务:起点为木箱所在仓位,终点为选定出库点,载具编码为木箱编码。
6. 任务完成后解锁仓位并清空载具编码和数量;木箱状态改为已出库并写入 `out_time`,历史记录保留。
7. 任务取消后只解除仓位锁,木箱记录仍为在库且继续绑定原仓位。
## 对外接口
- 入库创建:请求包含 `deviceCode``materialCode`;响应包含 `taskId``boxNo``targetStructCode`
- 出库创建:请求包含 `materialCode`;响应包含 `taskId``boxNo``destinationPoint`
服务端管理接口复用相同请求和响应语义。所有参数使用注解校验,对外 API 类型放在 WMS API 模块。
## 一致性与异常
- 未找到规格、候选排、空仓位或可出库木箱时抛出明确的 `ServiceException`
- 仓位锁使用带原状态条件的更新保证并发安全,不使用“先查后无条件更新”。
- 木箱完成或取消回调必须按任务 ID 精确匹配一个锁定仓位;匹配数量异常时拒绝静默成功。
- 重复完成或重复取消属于幂等冲突,抛出业务异常以暴露任务状态不一致。
- 所有查询和更新 SQL 写入 Mapper XML不使用 `@Select``@Update`
## 验收范围
- 同规格排存在空位时优先入同排;不存在时选择整排为空的排。
- 不同规格空木箱和带组盘记录的载具不会被安排在同一排。
- 入库创建、完成、取消均正确维护木箱状态和仓位锁。
- 出库严格按实际入库时间先进先出,并在并发条件下不会重复选择木箱。
- 出库点按任务数和占用库存数综合负载选择,并在响应中返回目的点。
- 出库完成后木箱历史记录仍可查询,仓位已清空。
- WMS 模块编译通过Mapper XML 可正常加载。