15 KiB
密集库出库补偿、移库与指定通道作业设计
1. 目标
在不改变现有入库流程和非密集库出库规则的前提下,完成以下能力:
- 出库作业下发 WCS 失败后自动补偿,最多自动重试 5 次,耗尽后支持人工下发。
- 所有 03 密集库出库与移库作业在下发前都必须是所在通道当前最外侧作业。
- 指定托盘和指定货位出库遇到遮挡时,自动生成
in_or_out=23的移库作业。 - KPI 货位平面图支持按通道、数量和目标通道生成同层移库作业。
- 新增指定通道出库菜单,按通道组查看库存并按端头托盘数量生成出库作业。
- 入库、普通出库、指定货位/通道出库和移库使用不同的 WCS 接口配置。
2. 现状约束
- 后端为 RuoYi Maven 多模块项目,出库作业与入库作业共用
mydo_job、mydo_job_detail。 - 作业归档过程存在
INSERT ... SELECT *,直接给mydo_job增加字段会同步影响活动表、归档表和多个存储过程。 - 03 仓的一个通道由同一排、同一层、同一通道带的
group_coding标识。 bas_cargo_area_config.direction_type是入库由深到浅的货位选择方向:方向1为列号从小到大,方向2为列号从大到小。- 当前出库代码错误复用了
sendPutawayTask配置键;本设计改为按作业类型路由。 - 当前 WCS 模拟开关默认开启,真实联调时必须显式关闭。
3. 总体架构
采用“业务作业 + WCS 下发记录”的 Outbox 结构:
mydo_job继续保存业务作业,不增加补偿字段。- 新表
wcs_job_dispatch与作业一一关联,保存下发状态、重试次数、错误、时间和并发版本。 OutboundDispatchService是所有出库、指定货位、指定通道和移库作业下发 WCS 的唯一入口。DenseLaneService负责密集库通道顺序、遮挡托盘、最外侧资格和移库目标货位选择。RelocationJobService负责自动/人工移库作业生成和 WCS 完成后的库存搬移。- Quartz 每分钟调用
WcsOutboundRetryTask.retryFailedJobs()执行自动补偿。
所有入口统一调用同一套下发资格检查,前端按钮、定时重试和分配后即时下发不能绕过密集库最外侧规则。
4. WCS 下发记录
新增表 wcs_job_dispatch:
| 字段 | 类型 | 说明 |
|---|---|---|
job_id |
nvarchar(255) PK | 对应作业 ID |
dispatch_status |
nvarchar(20) | PENDING、SENDING、BLOCKED、RETRY_WAIT、SUCCESS、EXHAUSTED |
auto_retry_count |
int | 已执行的自动重试次数,范围 0 至 5 |
manual_retry_count |
int | 人工下发次数 |
last_error |
nvarchar(1000) | 最后一次失败或等待原因 |
last_attempt_time |
datetime2 | 最后一次实际调用 WCS 时间 |
next_retry_time |
datetime2 | 下次允许自动重试时间 |
success_time |
datetime2 | 下发成功时间 |
version_no |
int | 并发抢占版本 |
create_time |
datetime2 | 创建时间 |
update_time |
datetime2 | 更新时间 |
初次下发失败不计入自动重试次数,状态设为 RETRY_WAIT、auto_retry_count=0。定时任务每调用一次前递增自动重试次数,失败达到 5 次后设为 EXHAUSTED。人工下发只递增 manual_retry_count,不重置自动重试次数,也不会重新进入自动队列。
密集库作业因不是当前最外侧而未调用 WCS 时,不计失败、不增加重试次数,记录统一设为 BLOCKED 并写入等待原因。外侧作业完成后立即唤醒同通道 BLOCKED 记录;定时任务每分钟复查一次 BLOCKED 记录作为异常恢复兜底。
通过原子状态更新把记录抢占为 SENDING,防止定时任务、人工按钮和业务线程并发重复下发。超过发送超时时间仍为 SENDING 的记录允许重新进入补偿流程。WCS 以 taskNo 作为幂等键;重复报文必须返回同一任务的成功确认。
5. 下发状态流转
5.1 分配后即时下发
- 出库分配或作业生成事务提交。
- 创建
PENDING下发记录。 - 调用统一下发服务。
- 资格不满足:转为
BLOCKED,业务接口返回作业已生成、等待外侧作业完成。 - WCS 调用失败:记录
RETRY_WAIT,业务接口返回作业已生成、WCS 下发失败并进入补偿队列。 - WCS 调用成功:记录
SUCCESS,作业状态改为3,执行阶段改为1,写入开始时间。
分配成功后不因 WCS 网络失败回滚库存预占和作业生成,避免操作员重复分配。数据库分配失败仍按现有事务回滚。
5.2 自动重试
- Quartz 每分钟扫描
RETRY_WAIT且auto_retry_count < 5、next_retry_time <= 当前时间的记录,同时复查BLOCKED作业是否已经成为最外侧。 - 每批按创建时间处理,单批数量可配置,默认 100。
- 重新执行作业存在性、作业状态、密集库最外侧和 WCS 路由检查。
- 网络或业务失败采用固定 1 分钟间隔;第 5 次失败转为
EXHAUSTED。 BLOCKED复查和最外侧资格不满足都不消耗重试次数。
5.3 人工下发
- 出库作业管理对
PENDING、RETRY_WAIT、EXHAUSTED的未完成作业显示“手动下发 WCS”。 - 操作前弹出确认框,展示自动重试次数和最后错误。
- 人工下发仍执行密集库最外侧校验。
- 失败后保持原自动状态或
EXHAUSTED,更新错误和人工次数;成功后转为SUCCESS。
6. 密集库最外侧规则
仅仓库 03 且货位存在非空 group_coding 时应用密集库规则。
- 同通道范围:
warehouse_id + group_coding,group_coding已包含排和层。 - 方向
1:入库从小列到大列,当前最外侧为所有占用/预占货位中的最大列。 - 方向
2:入库从大列到小列,当前最外侧为所有占用/预占货位中的最小列。 - 方向
3:按距离两侧边界较近者优先,同距离取较小列。 - 占用范围包括状态
2(满)、3(入库分配)、4(出库/移库分配)且托盘码非空的货位。
资格检查以事务中的实时货位数据为准,不能使用页面缓存。若同一最外侧托盘已经存在状态 2/3 的活动作业,只允许该作业继续,其他作业等待。
7. 遮挡处理与自动移库
7.1 触发范围
- 出库单分配明确指定库存明细、库存主记录或托盘时。
- 指定货位出库选择 03 仓密集库货位时。
- 指定托盘前存在其他占用托盘时。
7.2 遮挡托盘判定
按第 6 节的出库顺序,位于目标托盘外侧的占用托盘均为遮挡托盘。
- 遮挡托盘已有活动出库作业时,不再生成移库作业;该出库作业自然成为前置动作。
- 遮挡托盘没有活动出库/移库作业时,按从外到内顺序生成移库作业。
- 目标出库作业可以同时生成,但只有所有外侧货位释放后才具备下发资格。
7.3 自动移库目标
目标货位必须满足:
- 同仓库、同层、不同
group_coding。 - 状态为
1、未锁定、无托盘码。 - 符合托盘类型允许仓库和货位类型规则。
- 符合原通道的存储模式、项目号或物料相容规则。
- 不得被其他活动作业预占。
候选通道优先沿用现有入库规则:优先已有相容库存的通道,再按占用数量和通道编码选择;通道内按入库方向选择最深可用货位。生成作业后将源货位置为 4,目标货位置为 3 并预留托盘码。
8. 移库作业
in_or_out=23,任务号调用util_serial_task '23'。- 主作业的
cargo_space_id为源货位,target_cargo_space_id为目标货位。 - 每个托盘生成一个移库主作业;按库存明细生成对应
mydo_job_detail,保留库存、批次、项目号和数量追溯。 - 移库作业使用独立 WCS 路由,不进入 PDA 出库确认列表。
WCS 完成移库回调后,在一个数据库事务内:
- 锁定移库作业、源货位、目标货位和托盘库存。
- 校验作业类型为 23、作业已下发、源目标仍与作业一致。
- 将该托盘所有
bas_stock.cargo_space_id更新为目标货位。 - 源货位置为
1并清空托盘码,目标货位置为2并保留托盘码。 - 作业及明细归档并从活动表删除。
- 事务提交后触发同源通道下一条等待作业的资格检查和即时下发。
重复完成回调通过活动/归档作业查询实现幂等,已完成时返回成功。
9. KPI 货位平面图指定移库
仅在 03 密集库视图显示“指定移库”命令。弹窗包含:
- 当前层,只读。
- 源通道选择,只列出当前层有满货位的通道。
- 移库托盘数量,范围 1 至源通道当前可移动托盘数。
- 目标通道选择,只列出当前层具有足够相容空位的其他通道。
- 外侧托盘预览,展示托盘码、源货位、库存明细和总数量。
提交时后端重新锁定并验证通道、层、数量、库存与目标容量,按外到内选择源托盘并生成移库作业。页面数据只用于预览,不作为作业生成依据。
10. 指定货位出库
现有非密集库逻辑保持不变。03 密集库指定货位出库调整为:
- 锁定目标货位和通道。
- 计算外侧遮挡托盘。
- 为没有活动出库作业的遮挡托盘生成移库作业。
- 生成目标托盘的指定货位出库作业及下发记录。
- 先尝试下发当前最外侧移库/出库作业;目标作业等待通道逐步清空。
11. 指定通道出库
在出库管理下新增“指定通道出库”菜单和权限:
out:denseLaneOutbound:listout:denseLaneOutbound:previewout:denseLaneOutbound:generate
列表仅查询 03 仓 group_coding 非空且至少存在一个状态 2 满货位的通道,展示:
- 通道组编码、货区、排、层和方向。
- 满托盘数量、可出库托盘数量、库存总数量。
- 聚合库存摘要和可展开库存明细。
- 当前最外侧托盘及货位。
生成弹窗要求选择整托数量和适配出库口。后端按当前外侧顺序选择前 N 个未被活动作业占用的托盘,返回预览供确认,确认后每托生成一个指定出库作业和完整作业明细。任何托盘状态变化都会使旧预览失效,提交时重新校验并返回明确冲突信息。
12. WCS 路由
配置增加独立键并允许通过环境变量覆盖:
external:
systems:
WCS:
apis:
sendPutawayTask: ${WCS_PUTAWAY_PATH:/wcs/api/receiveWmsJob}
sendRetrieveTask: ${WCS_OUTBOUND_PATH:/wcs/api/receiveWmsOutJob}
sendLocationOutboundTask: ${WCS_LOCATION_OUTBOUND_PATH:/wcs/api/receiveWmsLocationOutJob}
sendRelocationTask: ${WCS_RELOCATION_PATH:/wcs/api/receiveWmsMoveJob}
路由规则:
in_or_out < 20:sendPutawayTask。in_or_out = 20:sendLocationOutboundTask,覆盖指定货位和指定通道整托出库。in_or_out = 23:sendRelocationTask。- 其他
in_or_out >= 20:sendRetrieveTask。
所有接口继续按作业所属仓库解析独立 WCS 根地址。
13. UI 设计
沿用现有 Vue 2、Element UI 和 RuoYi 页面密度:
- 出库作业列表增加“WCS 下发状态”“自动重试”“最后错误”列;错误使用 tooltip,避免撑高表格。
- “手动下发 WCS”使用发送图标和确认对话框,仅对允许状态显示。
- KPI 平面图在密集库工具栏增加移库命令,使用紧凑表单弹窗,不改变平面图颜色体系。
- 指定通道出库采用筛选栏、通道表格和单层生成弹窗;库存明细使用表格展开行,不嵌套装饰卡片。
14. 数据库迁移
新增一份可重复执行的 SQL Server 迁移脚本,包含:
- 创建
wcs_job_dispatch、状态/重试索引和字段说明。 - 确认
bas_task_no存在 ID23,存在则保留当前序号,不存在则补充移库类型。 - 新增指定通道出库菜单、按钮权限和角色授权兼容处理。
- 新增 Quartz 任务记录,调用
wcsOutboundRetryTask.retryFailedJobs,Cron 为每分钟一次,禁止并发。 - 为密集库通道、活动作业和下发扫描补充必要索引,创建前检查同名索引。
迁移不修改或删除现有业务数据,可重复执行。
15. 错误处理
- WCS 网络失败、超时、非成功响应和报文序列化失败均写入下发记录。
- 最外侧不满足、前置作业未完成和目标货位状态变化属于等待/并发冲突,不消耗自动重试次数。
- 自动移库目标不足时,原出库分配整体失败,不生成部分移库作业。
- 人工指定移库目标容量或相容性不足时,整个请求回滚。
- 移库完成时源目标或库存不一致,事务回滚并返回明确错误,不做部分库存搬移。
- 菜单生成作业时预览已过期,返回刷新提示,不自动替换为其他托盘。
16. 测试与验收
16.1 后端单元与 Mapper 测试
- 首次失败进入补偿队列且自动次数为 0。
- 自动重试恰好最多执行 5 次,第 5 次失败后耗尽。
- 人工下发超过 5 次仍可调用,但不会恢复自动队列。
- 调度并发抢占只有一个调用者成功。
- 非最外侧作业不调用 WCS且不增加重试次数。
- 方向 1、方向 2 的最外侧和遮挡集合正确。
- 指定托盘/货位遮挡时按外到内生成类型 23 作业。
- 自动目标同层、不同通道、相容且按入库规则选深位。
- 移库完成原子更新库存、源目标货位并归档。
- 指定通道预览与生成只选择端头 N 个托盘。
20、23和普通出库分别命中正确 WCS 配置键。
16.2 前端验证
- 出库作业列表正确显示状态、次数、错误和人工按钮权限。
- KPI 指定移库只能选择同层目标通道,数量和容量校验提示明确。
- 指定通道出库列表、展开明细、预览数量和生成确认可用。
- 生产构建通过,桌面和常用窄屏下表格、弹窗无文字遮挡。
16.3 集成场景
- 构造 WCS 连续失败,验证初次调用加 5 次自动重试后耗尽。
- 人工恢复下发,验证成功状态和作业状态更新。
- 在方向 1 和方向 2 通道各构造三托遮挡,验证下发顺序为外到内。
- 指定最内托盘出库,验证先生成并完成两个移库作业,再下发目标出库。
- KPI 指定跨通道同层移库,验证库存和货位一致。
- 指定通道出库 N 托,验证只选择端头 N 托及其完整库存。
- 验证非 03 仓原有自动、手动和指定货位出库不受影响。
17. 需求覆盖
| 原需求 | 设计章节 |
|---|---|
| 失败标记、5 次重试、定时器、人工下发、最外侧校验 | 4、5、6 |
| 指定托盘遮挡自动移库,类型 23 | 7、8 |
| KPI 平面图指定同层移库 | 9 |
| 出库 WCS 地址区分 | 12 |
| 指定货位出库遮挡移库 | 10 |
| 指定通道出库菜单与端头 N 托 | 11 |