10 KiB
10 KiB
出库集波规则匹配 API 文档
对应实现:
WaveRuleMatchController#findBestMatchedRule→WaveRuleMatchService#findBestMatchedRuleByWorkStationAndOutboundType
概述
工作站集波的核心入口。用户在 WES 工作站界面选择出库类型后,前端调用本接口触发自动集波流程:
- 根据工作站 + 出库类型找出当前可用的分播墙格口
- 按规则优先级查找订单池中符合条件的出库单
- 完成 Shopee 波次绑定、ESS 校验、内部波次创建与运行
- 返回「格口 + 命中规则 + 波次」的分配结果
请求
URL
POST wms/automation/waveRuleMatch/findBestMatchedRule
请求体 (JSON)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
warehouseCode |
String | 是 | 仓库编码 |
workStation |
String | 是 | 工作站编码(或工作站数字 ID) |
shipmentType |
String | 是 | 出库类型,如 XSCK(销售出库)、MTO、RTS、RT |
示例:
{
"warehouseCode": "WH01",
"workStation": "WS001",
"shipmentType": "XSCK"
}
出库类型说明
| 出库类型 | 含义 | 处理方式 |
|---|---|---|
XSCK |
销售出库 | 标准集波(按 ticketType 分流:1=销售出库任务 一波一单,其他批量) |
MTO |
MTO 出库 | 标准集波(按 ticketType 分流:5=MTO任务 一波一单,其他批量) |
RTS |
RTS 出库 | 标准批量集波 |
RT |
RT 出库 | 一波一单,不使用 Shopee 波次号,走库内流程 |
响应
成功响应
{
"success": true,
"data": [
{
"shipmentId": 12345,
"waveId": 67890,
"shopeeWaveCode": "SW20260520001",
"waveRule": "RULE_XSCK_SSSQ",
"sortingWallId": 1001,
"sortingWallCode": "WALL_A01",
"cellId": 2001,
"cellCode": "A01-01"
}
]
}
| 响应字段 | 类型 | 说明 |
|---|---|---|
shipmentId |
Long | 已集波出库单 ID |
waveId |
Long | 内部波次 ID |
shopeeWaveCode |
String | Shopee 波次号(RT 类型返回空字符串 "") |
waveRule |
String | 命中的波次规则编码 |
sortingWallId |
Long | 分播墙 ID |
sortingWallCode |
String | 分播墙编码 |
cellId |
Long | 格口 ID |
cellCode |
String | 格口编码 |
特殊:RT 和推拣货任务返回简化结构
{shipmentId, waveId, shopeeWaveCode, waveRule, shipmentType}。
错误响应
{
"success": false,
"messageCode": "MSG_WRM_0001",
"message": "参数不完整:warehouseCode、workStation、shipmentType 不能为空"
}
错误码
| 消息码 | 说明 | 触发条件 |
|---|---|---|
MSG_WRM_0001 |
参数不完整 | warehouseCode/workStation/shipmentType 任意为空 |
MSG_WRM_0002 |
工作站不可用 | 工作站不存在、仓库不匹配或未启用 |
MSG_WRM_0003 |
参数不完整 | workstationId/shipmentType 为空(内部入口) |
MSG_WRM_0004 |
工作站[{0}]不存在 | 工作站 ID 无效 |
MSG_WRM_0005 |
工作站[{0}]未启用 | 工作站状态非 ENABLE |
MSG_WRM_0006 |
工作站[{0}]仓库编码为空 | 工作站未关联仓库 |
MSG_WRM_0007 |
未找到可用波次规则 | 仓库下无启用规则 |
MSG_WRM_0008 |
无可用格口 | 工作站下所有格口已被占用 |
MSG_WRM_0009 |
规则匹配到但无格口可用 | 当前规则下无空闲格口承接 |
MSG_WRM_0010 |
当前规则下无可匹配出库单 | 订单池无符合条件的出库单 |
MSG_WRM_0011 |
规则或工作站为空 | 内部校验 |
MSG_WRM_0012 |
工作站正在集波中 | Redis 锁获取失败,同一工作站同一出库类型正在集波 |
处理流程
POST /findBestMatchedRule
│
├─ 1. 参数校验 (warehouseCode / workStation / shipmentType)
│
├─ 2. 工作站校验 (存在 / 启用 / 仓库匹配)
│
├─ 3. Redis 锁 (仓库+工作站+出库类型, 防重复集波)
│
├─ 4. 查询启用波次规则 (按 wavePriority desc)
│
├─ [分支 A] 一波一单
│ └─ assignSingleShipmentWaves
│ 按单拣选、销售任务、MTO 任务、RT 一单一波;RT 不使用 Shopee 波次号
│
├─ [分支 B] 已绑定 Shopee 波次格口补缺口
│ └─ fillShortageCells
│ 仅处理空闲、已绑定 shopeeWaveCode、currentWaveRule 匹配当前规则的格口
│
└─ [分支 C] 空格口首次分配 (逐规则按优先级循环)
│
├─ 5. 查可用格口 (三层级):
│ ├─ sameCurRuleCells — currentWaveRule 同当前规则
│ ├─ ruleCells — waveRule 配置匹配当前规则
│ └─ emptyCells — 完全空闲格口
│
├─ 6. 按规则查询出库单:
│ ├─ 一波一单候选项 (pickType=1 / ticketType 任务 / RT)
│ └─ 批量集波候选项 (排除一波一单)
│
├─ 7. 创建内部波次 (WaveService#createInternalWave)
│
├─ 8. 格口循环处理:
│ ├─ 已有波次号 → 补单缺口判断
│ └─ 无波次号 → 抢占 Shopee 波次号 (acquireUnusedShopeeWave)
│
├─ 9. assignToCell:
│ ├─ pickCellShipmentIds — 按格口缺口截断候选单
│ ├─ ensureCellReadyForWave — 先抢占格口 (USED)
│ ├─ bindShipmentShopeeWave — ESS 绑定校验
│ │ ├─ 成功 → 写入 shipment_header.shopeeWave,并更新 shopee_wave pickType/groupKey
│ │ └─ 失败 → 写入 kickOutWave, 同波次后续过滤
│ └─ addShipmentsToInternalWave → WaveService#run
│
└─ 10. 成功返回 ResponseMessageFactory.success(),不返回格口分配明细
核心规则
规则优先级
- 上墙优先级 —
wave_rule.wavePriority(数字越大越优先) - 抓单优先级(同一规则内):
priority数字越大越优先- 同优先级按
cutOffTime越早越优先 - 同截单时间按
purchaseTime越早越优先 - 同购买时间按
orderTime越早越优先 - 同时间按
id升序兜底
格口分配优先级
| 优先级 | 格口类型 | 条件 |
|---|---|---|
| 1(最高) | sameCurRuleCells |
currentWaveRule 与当前规则相同 |
| 2 | ruleCells |
currentWaveRule 为空且 waveRule 匹配当前规则 |
| 3(兜底) | emptyCells |
currentWaveRule 和 waveRule 均为空 |
一波一单处理
以下单据类型按一波一单处理(每次集波只取 1 单,创建独立内部波次):
| 类型 | 标识 | 说明 |
|---|---|---|
| 按单拣选 | pickType=1 |
按单拣选专用 |
| 销售出库任务 | shipmentType=XSCK + ticketType=1 |
一波一单 |
| MTO 任务 | ticketType=5 |
一波一单 |
| RT | ticketType=6 |
不使用 Shopee 波次号 |
字段匹配
通过数据字典 WAVE_RULE_FIELD_MATCHING 配置出库单字段与规则字段的匹配关系:
| 操作符 | 含义 | 示例 |
|---|---|---|
IN |
多值包含 | userDef1 IN (channelId 多选值) |
= / EQ / EQUAL / EQUALS |
等值匹配 | userDef7 = shopId |
LE / <= / LESS_OR_EQUAL |
小于等于 | priority <= urgentFlag |
字段白名单(防 SQL 拼接注入):
- 出库单字段(30+):
shipmentType、ticketType、pickType、sourcePlatform、sourceErp、route、carrierCode、shipToCountry、userDef1-8等 - 规则字段(16):
channelId、fulfillmentChainId、orderSize、skuSizeType、categoryLevel1Id、shopGroup、shopId、urgentFlag、outerPackaging、deliveryRegion、fragile、liquid、highValue、battery、danger等
并发控制
Redis 分布式锁,锁 Key:wave_rule_match:{warehouseCode}:{workstationId}:{shipmentType}
同一工作站 + 同一出库类型同时只有一个请求能进入集波流程。
异常过滤
出库单必须同时满足以下条件才能进入抓单池:
leadingSts = 100(订单池状态)trailingSts = 100(订单池状态)processType = 'NORMAL'(正常处理流程)waveId is null or waveId = 0(未加入任何波次)lockCode is null or lockCode = ''(未被锁定)cancelTime is null or cancelTime = ''(未取消)holdTime is null or holdTime = ''(未挂起)
补单机制(当前代码口径)
当前代码未保留后台计划任务 pollReplenishment/pollReplenishmentOnce。补缺口能力收口在首次集波入口中的 fillShortageCells,用于处理当前工作站已绑定 Shopee 波次且规则一致的空闲格口。
- 触发方式:调用首次集波入口时顺带执行
- 扫描范围:当前工作站 + 已绑定 Shopee 波次 +
currentWaveRule匹配的空闲格口 - 单品单件:低于
WAVE/low_threshold时触发,一次性按maxShipments抓单 - 非单品单件:缺口 =
maxShipments - 当前波次已绑单量 - Flow Pick 满槽:达到
maxShipments时触发换箱换波 - 后台轮询:如需恢复,需按最终调度策略重新接入计划任务入口
相关表
| 表名 | 说明 | 关键字段 |
|---|---|---|
wave_rule |
波次规则 | code, waveType, wavePriority, maxShipments, status, channelId, shopId 等 |
shopee_wave |
Shopee 波次号段 | code, waveType, warehouseCode, pickType, groupKey, flow_pick, status (100=未使用, 200=使用中, 900=使用完成) |
shipment_header |
出库单头 | shopeeWave, kickOutWave, ticketType, pickType, groupKey, orderStructure, waveId |
wcs_sorting_wall_cell |
分播墙格口 | waveRule, currentWaveRule, shopeeWaveCode, useStatus |
wcs_work_station_pick_task_header |
拣货任务头 | shopeeWave, waveRule, shipmentId |
wave |
内部波次 | waveRule |
测试与验证
推荐验证顺序:
- 编译:按需执行
:wms-wave:compileGroovy,本轮文档同步未执行 - 静态检查:确认无新增测试类和旧测试类引用残留
- 手工验证:使用实际 wave_rule 和出库单数据调用本接口,验证系统处理日志、格口占用和订单波次绑定
- ESS 联调:验证
bindShipmentShopeeWave中 ESS 绑定接口成功/失败结果 - 补单验证:确认
fillShortageCells能补满已绑定 Shopee 波次格口且kickOutWave过滤生效