Files
FTC25009/docs/superpowers/specs/2026-07-10-inbound-cargo-space-height-design.md

86 lines
4.4 KiB
Markdown
Raw 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.
# 入库货位高度分配设计
## 目标
为 01、02 仓建立普通货位和高货位数据,并让 WCS 请求入库货位时按 `height` 等级分配:
- 01、02 仓的 1 层、5 层货位设置为 `the_height = 2`。
- 01、02 仓其余层货位设置为 `the_height = 1`。
- WCS `height = 2` 只能分配 `the_height = 2` 的货位。
- WCS `height = 1` 优先分配 `the_height = 1` 的货位;普通货位没有可用候选时,才允许分配 `the_height = 2` 的货位。
## 当前链路
WCS 通过 `POST /api/external/wcs/inbound/location` 请求具体货位。控制器按作业 ID、任务号或托盘号找到入库作业,然后调用 `PdaService.lockInboundCargoSpace`,由 `PdaMapper.xml` 在作业既定巷道中并发锁定一个空货位。货位写回 `mydo_job` 后返回 WCS。
`PUT_OCCUPIED` 放货有货异常会在同一仓库、同一巷道重新选择货位。该路径读取 `mydo_job` 后通过 `BasCargoSpaceMapper.xml` 选择候选,因此首次分配时必须把 WCS 高度等级保存到 `mydo_job.height`,重分配才能继承相同限制。
## 接口与校验
`WcsInboundLocationRequest` 增加 `BigDecimal height`,与现有 `MydoJob.height` 类型保持一致。
- `height` 必传。
- 只接受数值 `1` 或 `2`,其他值返回 WCS 业务错误,不进行锁位。
- 首次成功分配时将值写入 `mydo_job.height`。
- 已分配作业再次收到相同高度时幂等返回原货位,不重复锁位。
- 已分配作业再次收到不同高度时返回冲突错误,不覆盖已保存高度,也不静默更换货位。
## 正常分配
`PdaService.lockInboundCargoSpace` 增加高度参数,并将其作为 `v_height` 传给锁位和已锁货位查询。
候选过滤统一使用容量规则 `bcs.the_height >= #{v_height}`。数据库只维护等级 1、2,因此该规则等价于:
- 请求 2:只保留货位 2。
- 请求 1:保留货位 1、2。
候选排序先按 `the_height` 是否与请求值完全相同排序,再保留现有的“空位最多排优先、排/层/列/货位编号升序”规则。这样请求 1 在任何普通候选存在时都不会占用高货位,请求 2 则只能命中高货位。
查询同一托盘已有锁位时返回 `the_height`。服务层先检查已有锁位是否满足本次请求:满足时幂等复用;不满足时返回冲突错误,不再锁定第二个货位。这样可覆盖“货位已锁定但作业回写前进程中断”的残留场景。
## 异常重分配
`selectAvailableInboundCargoSpaceInRoadway` 使用 `MydoJob.height` 应用相同的容量过滤和精确高度优先排序。`PUT_OCCUPIED` 不要求 WCS 再次上传高度,以数据库中首次持久化的作业高度为准。
历史作业中 `height` 为空或非 1、2 时,不允许重分配并返回明确错误,避免无约束选位。
## 数据库变更
增加可重复执行的 SQL 脚本,并在当前配置的 `FTC25009-WMS` 数据库中事务执行:
```sql
update dbo.bas_cargo_space
set the_height = case when the_floor in (1, 5) then 2 else 1 end
where warehouse_id in ('01', '02');
```
执行前后的事务内校验要求:
- 目标总数必须为 340 行。
- `the_height = 2` 必须为 136 行。
- `the_height = 1` 必须为 204 行。
- 01、02 仓不得残留空值或其他高度值。
若任一断言不满足则回滚。当前只读统计显示 340 行的 `the_height` 均为 `NULL`,因此首次执行实际更新 340 行。
## 测试与验证
自动化测试覆盖:
- 请求缺少高度、非 1/2 高度时拒绝。
- 首次请求把高度传入锁位服务并持久化到作业。
- 相同高度重复请求幂等,不同高度重复请求冲突。
- 已有残留锁位与请求高度不兼容时拒绝,不产生第二个锁位。
- 正常锁位 SQL 对高度 1/2 的过滤及普通货位优先排序。
- `PUT_OCCUPIED` 查询继承 `MydoJob.height` 并使用同样排序。
- 现有货位排优先策略仍保留。
完成后运行 `mvn -pl ruoyi-admin test`,再运行后端打包或至少 `mvn -pl ruoyi-admin -am package -DskipTests` 验证编译。数据库执行后重新查询 01、02 仓逐层分布作为线上结果证据。
## 范围约束
- 只修改入库具体货位分配和放货有货重分配,不改变出库逻辑。
- 只更新 01、02 仓;其他仓库货位高度不变。
- 不改变托盘类型、仓库、巷道、货位状态和并发锁定等既有条件。
- 不调整 `the_height` 数据类型;本次只使用整数等级 1、2。