feat:出库单一键设置功能及移库单CRUD

This commit is contained in:
zhouz
2026-07-28 16:21:22 +08:00
parent 9e43129c37
commit 04ffd865a3
56 changed files with 2638 additions and 23 deletions

View File

@@ -0,0 +1,86 @@
# WMS 移库管理功能实现计划
> **面向 AI 代理的工作者:** 在当前会话内按任务顺序执行,使用 TDD 验证核心找位和锁定行为。
**目标:** 实现移库单 CRUD、库存与目标仓位选择、仓位锁定以及按来源载具自动找位建单的内部 API。
**架构:** WMS Server 新增独立 `moveinv` 业务包,主 Service 维护单据事务,`MoveTargetStructSelector` 专门负责目标仓位选择。数据库查询集中在 Mapper XML跨模块自动建单契约放在 WMS API。前端沿用出库页面的 Vben 表格、抽屉和弹窗模式。
**技术栈:** Java 17、Spring Boot、MyBatis/MyBatis-Plus、OpenFeign、Vue 3、TypeScript、Ant Design Vue。
---
### 任务 1数据模型和 Mapper
**文件:**
- 创建:`nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/dal/dataobject/moveinv/MoveInvDO.java`
- 创建:`nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/dal/dataobject/moveinvdtl/MoveInvDtlDO.java`
- 创建:`nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/dal/mysql/moveinv/MoveInvMapper.java`
- 创建:`nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/dal/mysql/moveinvdtl/MoveInvDtlMapper.java`
- 创建:`nl-module-wms/nl-module-wms-server/src/main/resources/mapper/moveinv/MoveInvMapper.xml`
- 创建:`nl-module-wms/nl-module-wms-server/src/main/resources/mapper/moveinvdtl/MoveInvDtlMapper.xml`
- 修改:`nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/dal/mysql/structAttr/StrucAttrMapper.java`
- 修改:`nl-module-wms/nl-module-wms-server/src/main/resources/mapper/structAttr/StrucAttrMapper.xml`
- [ ] 映射两张移库表全部字段。
- [ ] 增加分页、详情、按载具查询来源库存、同层空闲目标仓位查询。
- [ ] 增加移出锁、移入锁和按移库单释放锁的条件更新。
### 任务 2目标仓位选择器
**文件:**
- 创建:`nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/service/moveinv/MoveTargetStructSelector.java`
- 创建:`nl-module-wms/nl-module-wms-server/src/test/java/cn/code/nl/module/wms/service/moveinv/MoveTargetStructSelectorTest.java`
- [ ] 先写测试,覆盖同层、距离排序和批次目标去重。
- [ ] 运行测试确认因选择器不存在而失败。
- [ ] 实现最小选择算法并运行测试通过。
### 任务 3后端业务和管理端接口
**文件:**
- 创建:`nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/controller/admin/moveinv/vo/*.java`
- 创建:`nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/controller/admin/moveinv/MoveInvController.java`
- 创建:`nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/service/moveinv/MoveInvService.java`
- 创建:`nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/service/moveinv/MoveInvServiceImpl.java`
- 修改:`nl-module-wms/nl-module-wms-api/src/main/java/cn/code/nl/module/wms/enums/ErrorCodeConstants.java`
- [ ] 实现分页、详情、可用库存、可用目标仓位。
- [ ] 实现新增、修改、删除事务。
- [ ] 创建时给来源仓位加 `4` 移出锁、目标仓位加 `5` 移入锁。
- [ ] 修改/删除时只释放当前移库单持有的锁。
### 任务 4自动找位建单 API
**文件:**
- 创建:`nl-module-wms/nl-module-wms-api/src/main/java/cn/code/nl/module/wms/api/moveinv/MoveInvApi.java`
- 创建:`nl-module-wms/nl-module-wms-api/src/main/java/cn/code/nl/module/wms/api/moveinv/dto/MoveInvAutoCreateReqDTO.java`
- 创建:`nl-module-wms/nl-module-wms-api/src/main/java/cn/code/nl/module/wms/api/moveinv/dto/MoveInvAutoCreateRespDTO.java`
- 创建:`nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/api/moveinv/MoveInvApiImpl.java`
- [ ] API 只接收来源载具编码列表。
- [ ] Service 逐载具选择同库区同层目标仓位,确保目标不重复。
- [ ] 任意载具不可用或无目标时整单回滚。
### 任务 5前端管理页面
**文件:**
- 创建:`nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/wms/moveinv/index.ts`
- 创建:`nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/moveinv/data.ts`
- 创建:`nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/moveinv/index.vue`
- 创建:`nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/moveinv/modules/form.vue`
- 创建:`nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/moveinv/modules/inventory-select.vue`
- 创建:`nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/moveinv/modules/struct-select.vue`
- 创建:`nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/moveinv/modules/detail.vue`
- [ ] 实现列表和生成状态操作限制。
- [ ] 新增/修改抽屉默认全屏并回填明细。
- [ ] 每个载具分别选择不同目标仓位。
- [ ] 实现详情展示。
### 任务 6验证
- [ ] 运行后端核心测试。
- [ ] 运行 WMS reactor 编译。
- [ ] 运行前端类型检查。
- [ ] 检查工作区差异,不覆盖既有用户修改。

View File

@@ -0,0 +1,164 @@
# WMS 移库管理功能设计
## 1. 目标
基于现有 `wms_moveinv``wms_moveinvdtl` 表实现完整的移库管理功能,包括移库单列表、新增、修改、删除、详情、可用库存选择、目标仓位选择,以及供“一键设置”直接调用的自动建单接口。
## 2. 功能范围
### 2.1 移库单列表
- 分页查询移库单主表,默认按主键倒序。
- 展示单据编码、单据类型、业务日期、仓库、总数量、明细数、单据状态、生成方式、创建人、创建时间和备注。
- 单据编码可进入详情页。
- 生成状态的单据允许修改、删除;其他状态不允许修改、删除。
### 2.2 新增和修改
- 页面交互与现有出库单新增、修改保持一致。
- 新增时先选择仓库及库区,再选择该库区内可用库存。
- 库存按载具选择,每个载具生成一条 `wms_moveinvdtl`
- 每条明细必须单独选择一个目标仓位。
- 同一张移库单内,不允许多条明细选择同一个目标仓位。
- 修改页面回填主表和全部明细。
- 修改保存时更新主表,释放旧明细关联的仓位锁,删除旧明细,插入新明细,并按新明细重新加锁。
- 主表的 `total_qty``detail_count` 根据保存的明细汇总生成。
### 2.3 可用库存
库存来源为组盘数据和载具所在仓位,必须同时满足:
- 组盘数据未删除,并处于入库可用状态。
- 载具编码不为空。
- 载具所在仓位已启用且未删除。
- 来源仓位未被其他业务锁定。
- 来源仓位属于当前选择的仓库和库区。
选择结果回填载具编码、来源仓位、来源库区、物料编码、批次、数量、计量单位及来源单号。
### 2.4 手工目标仓位选择
目标仓位必须满足:
- 与来源仓位属于同一个仓库。
- 与来源仓位属于同一个库区。
- 与来源仓位具有相同的 `layer_num`
- 仓位已启用且未删除。
- `lock_type = 0`,即仓位未锁定。
- `storagevehicle_code` 为空,即仓位上没有载具。
- 不能是来源仓位。
- 不能是当前移库单其他明细已经选择的目标仓位。
## 3. 自动目标仓位选择器
新增独立的 `MoveTargetStructSelector`,集中封装自动找位规则。业务 Service 不直接编写找位排序逻辑,方便后续替换算法。
选择器输入:
- 来源仓位。
- 当前批次已经选择的目标仓位标识集合。
选择器输出:
- 一个满足条件的目标仓位。
默认规则:
1. 筛选同仓库、同库区、同层的空闲仓位。
2. 排除来源仓位及当前批次已经选择的目标仓位。
3. 优先选择与来源仓位 `col_num` 距离较近的仓位。
4. 距离相同时按 `row_num``col_num``block_num``struct_id` 升序选择。
5. 找不到目标仓位时抛出业务异常。
仓位候选查询 SQL 统一放在 `StrucAttrMapper.xml` 中,选择器只负责候选校验和顺序选择。
## 4. 一键设置自动建单接口
在 WMS API 模块开放自动创建移库单接口,供出库“一键设置”等跨模块业务调用。
请求参数:
- 来源载具编码列表。
处理流程:
1. 校验载具编码不可重复。
2. 批量查询每个载具对应的来源仓位和可用库存。
3. 对每个载具调用 `MoveTargetStructSelector`,自动选择同库区、同层目标仓位。
4. 本次已选择的目标仓位加入排除集合,确保一车一目标且目标不重复。
5. 生成一张移库单及对应明细。
6. 任意载具不存在、库存不可用或找不到目标仓位时,整个事务回滚。
7. 返回创建成功的移库单标识和单据编码。
接口生成方式使用接口创建对应的字典值,初始单据状态为“生成”。
## 5. 仓位锁定
锁定类型来自字典 `wms_lock_type`
- `4`:移出锁。
- `5`:移入锁。
创建成功后:
- 来源仓位设置 `lock_type = 4`
- 目标仓位设置 `lock_type = 5`
- 两类锁均写入 `inv_type``inv_id``inv_code`,关联当前移库单。
修改时:
1. 校验单据处于生成状态。
2. 仅释放 `inv_id` 等于当前移库单标识的旧来源、目标仓位锁。
3. 更新主表并重建明细。
4. 对新来源仓位加移出锁,对新目标仓位加移入锁。
删除时:
- 仅允许删除生成状态单据。
- 释放当前单据持有的来源和目标仓位锁。
- 删除主表和明细。
建单、修改、删除、加锁和解锁必须处于同一数据库事务。
## 6. 数据一致性与并发
- 保存前再次在数据库中校验来源仓位和目标仓位状态,不能只依赖页面查询结果。
- 仓位加锁更新必须带上当前未锁定条件,受影响行数不为 1 时视为仓位已被占用并回滚。
- 同一载具不能在一张单据中重复出现。
- 同一目标仓位不能在一张单据中重复出现。
- 主表、明细和仓位锁任一步失败,整笔事务回滚。
## 7. 前端结构
- 新增移库管理 API 文件。
- 新增移库列表页面。
- 新增全屏移库新增/修改页面。
- 新增库存选择弹窗。
- 新增目标仓位选择弹窗。
- 新增移库详情页面。
- 表格列沿用系统全局分隔线、勾选框颜色和操作按钮图标规范。
## 8. 错误处理
需要提供明确的中文业务异常:
- 移库单不存在。
- 当前状态不允许修改或删除。
- 来源载具不存在或库存不可用。
- 来源仓位已锁定。
- 目标仓位已占用或已锁定。
- 目标仓位与来源仓位不在同一库区或同一层。
- 目标仓位在当前单据中重复。
- 未找到同库区、同层的可用目标仓位。
## 9. 验证范围
- 后端编译通过。
- 前端类型检查通过。
- 新增、修改时主表和明细正确保存。
- 修改时旧锁释放、新锁正确创建。
- 删除时来源和目标仓位锁正确释放。
- 自动找位只选择同库区、同层、未锁定、无载具的仓位。
- 批量自动建单目标仓位不重复。
- 任意一条自动找位失败时不产生主表、明细或残留锁。
- 起点锁定类型为 `4`,目的点锁定类型为 `5`