# WaveRuleMatchService 功能完成度分析

对照来源：`C:\Users\zoe\Downloads\SHOPEE_010_出库集波V1.2.docx`

代码范围：`C:\work\gitlab\shopee\wes-loghub\wms-wave\src\main\groovy\com\ittx\wms\wave\service\hairo\WaveRuleMatchService.groovy`

更新日期：2026-06-02

本文只维护 `WaveRuleMatchService` 对照最终需求仍未完成、未闭环或需要接口确认的功能。已落地且逻辑清晰的实现只在“已明确口径”中简要记录，不再作为待办展开。

## 已明确口径

- 首次集波入口保留 `ResponseMessage`。
- 错误分支继续返回 `ResponseMessageFactory.error(...)`。
- 首次集波成功只返回 `ResponseMessageFactory.success()`，不返回分配明细数据。
- 首次集波不维护 `allocatedRows` 汇总。
- 一波一单、缺货补满、空格口分配的执行结果通过系统处理日志记录。
- 当前未保留 `pollReplenishment/pollReplenishmentOnce` 计划任务入口；补缺口能力收口在首次集波入口的 `fillShortageCells(...)`。
- 一波一单规则已按当前确认口径修正：`XSCK + ticketType=1`、`ticketType=5`、`pickType=1`、`RT(ticketType=6)` 均进入一波一单，RT 不使用 Shopee 波次号。
- `fillShortageCells(...)` 不返回 `rows`，只执行缺货补满副作用并记录系统处理日志。
- `findShortageCells(...)` 已改为直接 SQL 查询 `wcs_sorting_wall_cell`。
- `findShortageCells(...)` 限制 `useStatus = IDLE`、`shopeeWaveCode` 有值、`currentWaveRule = rule.code`。
- `findCells(Long workStationId)` 已改为直接 SQL 查询 `wcs_sorting_wall_cell`。
- 单品单件 `calcCellNeedQty(...)` 已改为只统计未拣货任务对应的出库单数量。
- 非单品单件补单按 `maxShipments - 当前 Shopee wave 单量` 计算缺口。
- `low_threshold` 只用于单品单件 wave rule 的补单触发判断。
- 同一规则内抓单排序已按 `shipment_header.priority`、`cutOffTime`、`purchaseTime`、`orderTime`、`id` 处理。
- `WAVE_RULE_FIELD_MATCHING` 已实现基础字段映射，字典口径为：`identifier` 是出库单字段，`value1` 是 `wave_rule` 字段，`value2` 是操作符。
- ESS 校验失败单据已有基础 `kickOutWave` 记录能力。
- 首次集波入口已有 Redis 工作站锁；Shopee 波次绑定使用波次号维度 Redis 锁。
- 同工作站不混做不同订单类型已在入口层落地：Redis 锁前通过 `USED` 格口的 `shopeeWaveCode` 反查 `shipment_header.shipmentType`，发现其它出库类型时记录系统处理日志并返回 `MSG_WRM_0014`。
- `WaveService#run` 是异步提交队列消息，当前服务不解析同步库存不足踢单结果。
- 库存不足踢单不记录 `kickOutWave`，由 `wms-wave` 回池链路清空 Shopee 绑定并预留上游撤单接口。

## P0 主链路缺口

### 1. 计划任务轮询补单入口待恢复

docx 要求：

- 计划任务轮询正在作业的工作站和槽口。
- 单品单件低于 `low_threshold` 时触发补单。
- 非单品单件未达到 `maxShipments` 时触发补单。
- 推拣货任务后续无需补单。

当前代码：

- 未保留 `pollReplenishment(...)`。
- 未保留 `pollReplenishmentOnce(...)`。
- 未保留 `replenishCell(...)`、`findPickingWorkstations(...)`、`findReplenishmentCells(...)`。
- 已有 `fillShortageCells(...)`，但只在首次集波入口中执行，用于当前工作站已绑定 Shopee 波次格口的缺口补满。
- 不保留新增测试类；后台轮询入口、工作站/格口扫描、逐格口补单派发仍需按最终调度策略恢复。

仍需细化点：

- 需要按系统参数控制是否启用、轮询间隔和仓库范围。
- 需要恢复后台调度入口，并复用 `fillShortageCells/assignToCell` 现有补缺口能力。
- 需要结合真实波次状态、连续空轮条件和接口响应做联调细化。

当前实现口径：

- 现有补缺口业务收口在 `fillShortageCells(...)`。
- 后续如恢复计划任务，建议继续复用工作站 Redis 锁，避免和人工首次集波入口并发抢格口。

### 2. 一波一单规则已按当前确认口径修正，剩余 ticketType 字典待补齐

docx 要求：

- 销售出库任务一波一单。
- MTO 任务一波一单。
- RT 一波一单。
- 按单拣选单据一波一单。

当前代码：

- 常量已覆盖 `TICKET_TYPE_XSCK_TASK = 1`。
- 常量已覆盖 `TICKET_TYPE_MTO_TASK = 5`。
- 常量已覆盖 `TICKET_TYPE_RT = 6`。
- `appendSingleWaveFilter(...)` 覆盖 `pickType = 1`、`ticketType in (1,5,6)`。
- `appendBatchWaveFilter(...)` 排除 `pickType in (1,2)` 和 `ticketType in (1,5,6)`。
- RT 按 `ticketType = 6` 整体一波一单，不使用 Shopee 波次号。
- 不保留新增测试类；MTO `ticketType=5`、RT `ticketType=6` 仍需结合真实数据联调验证。

未完成点：

- 需要按最新数据字典确认 `ticketType` 1-7 的完整值域。
- RT 已确认按 `ticketType = 6` 特殊处理“不使用 Shopee 波次号”，仍需真实数据验证。

当前实现口径：

- `appendSingleWaveFilter(...)` 覆盖按单拣选、XSCK 任务、MTO 任务、RT。
- `appendBatchWaveFilter(...)` 同步排除 pickType 一波一单和当前出库类型下的一波一单 ticketType。

### 3. 推拣货任务分流方法未接入首次集波主入口

docx 要求：

- 推拣货任务由上游同步 Shopee 波次号段。
- WES 不走取号逻辑。
- 根据出库类型和 wave rule 抓取该订单。
- 一单一波次一槽口。
- 后续无需补单。

当前代码：

- 当前未保留 `assignPickingTaskSingleWaves(...)`。
- 当前未保留 `findPickingTaskShipments(...)`。
- 当前未保留 `isPickingTaskReplenishmentCell(...)`。
- 普通批量抓单 `appendBatchWaveFilter(...)` 排除了 `pickType = 2`。
- 一波一单 `appendSingleWaveFilter(...)` 未包含 `pickType = 2`。

未完成点：

- 推拣货任务当前不会进入首次集波主链路。
- 需要恢复或新增主入口分流。
- 成功、失败、无数据均只记录系统处理日志，不返回明细数据。

建议实现口径：

- 在首次集波入口中增加推拣货任务分流。
- 分流顺序建议放在普通空格口批量分配之前。
- 推拣货任务继续不参与后续补单。

### 4. 同工作站不混做不同订单类型已落地，待联调验证

docx 要求：

- 用户选择出库类型后，同一个工作站不会混做不同类型。

当前代码：

- `findBestMatchedRuleByWorkStationAndOutboundType(...)` 已在 Redis 锁前调用 `hasDifferentActiveShipmentType(...)`。
- `findActiveWorkstationShipmentTypes(...)` 通过 `wcs_sorting_wall_cell` 已占用 `USED` 格口关联 `shopeeWaveCode`，反查 `shipment_header.shopeeWave` 和 `shipment_header.shipmentType`。
- 如果当前工作站已有其它出库类型，记录系统处理日志并返回 `MSG_WRM_0014`。

仍需验证点：

- 需要用真实格口、Shopee 波次和出库单数据验证 SQL 关联是否覆盖全部正在作业场景。
- 前端仍需配合做出库类型选择限制和提示。

当前实现口径：

- 优先按 `wcs_sorting_wall_cell` 已占用格口关联 `shopeeWaveCode` 反查 `shipment_header.shipmentType`。
- 返回明确错误码 `MSG_WRM_0014`，并记录系统处理日志。

## P1 上游接口和异常闭环

### 5. Shopee 波次号段申请接口未实现

docx 要求：

- `shopee_wave` 每天向上游申请波次号段。
- 本地号段用完后继续请求上游。

当前代码：

- `acquireUnusedShopeeWave(...)` 只从本地 `shopee_wave` 表取 `status = 100` 的号段。
- 本地号段为空时直接返回空。
- 方法旁已有 TODO 注释。

未完成点：

- 需要接入上游号段申请接口。
- 需要明确请求参数、返回结构、失败重试策略。
- 需要明确申请后如何落库以及状态初始值。

### 6. Shopee 波次绑定接口仍是占位

docx 要求：

- 用 Shopee wave + 抓取单号请求上游校验是否允许集在一波。
- 当前确认口径为上游绑定接口只有整批成功或整批失败。
- 失败单据写入 `shipment_header.kickOutWave`。
- 后续同 Shopee wave 补单时过滤这些单据。

当前代码：

- `bindShipmentShopeeWave(...)` 已有批量绑定和失败单据 `kickOutWave` 记录逻辑。
- `bindShipmentShopeeWave(...)` 内使用 Shopee 波次号维度 Redis 锁控制并发。
- 获取锁后会重新检查 `shopee_wave` 号段是否仍可用。
- `requestShopeeWaveBind(...)` 是真实上游绑定接口预留位置。
- 当前按整批成功/整批失败处理：失败整批写 `kickOutWave`，成功整批写 `shipment_header.shopeeWave` 并同步 `shopee_wave.pickType/groupKey/status`。

未完成点：

- 真实 ESS service、方法名、请求 DTO、响应 DTO 未确认。
- 真实接口成功/失败判断字段未确认。
- 生产环境接口缺失时是否允许放行需要确认。

建议实现口径：

- 接入正式接口后只补齐 `requestShopeeWaveBind(...)`。
- 响应解析只保留整批成功/失败字段。
- 生产环境接口缺失时建议失败并记录系统处理日志，不建议静默全部通过。

### 7. Flow Pick 封箱和换箱换波接口仍是占位

docx 要求：

- 单品单件满槽后先封箱。
- 请求 Flow Pick 换箱接口。
- 上游校验 OK 后，剩余订单切到新 Shopee 波次。
- 上游校验不 OK 时，订单回订单池，取消任务下发，通知 AGV 取消回库。

当前代码：

- `changeFlowPickWave(...)` 已有本地流程。
- `requestFlowPickSealBox(...)` 动态调用 `sealBox`。
- `requestFlowPickChangeBox(...)` 动态调用 `changeBoxWave`。
- `essFlowPickService == null` 时本地继续。
- `handleFlowPickChangeWaveFailure(...)` 只记录系统处理日志。
- `isFlowPickCellFull(...)` 仍以 `maxShipments` 作为满槽判断。

未完成点：

- Flow Pick 封箱正式接口未接入。
- Flow Pick 换箱正式接口未接入。
- 换箱失败后的订单回池、任务取消、AGV 取消回库未实现。
- 满槽判断还不是 WCS 真实物理满箱信号。

### 8. 库存不足踢单和上游撤单闭环未完全落在当前链路

docx 要求：

- 波次运行如果有库存不足的单据，直接踢单。
- 请求上游撤单接口，告知上游集波剔除的单号。
- 库存不足踢单后进入后续补单逻辑。

当前代码：

- `addShipmentsToInternalWave(...)` 调用 `WaveService#run`。
- `WaveService#run` 是异步提交队列消息，当前服务不解析同步踢单结果。
- 相关清空绑定和踢单通知逻辑已有部分转移到 `wms-wave` 模块。

未完成点：

- 需要联调确认库存不足踢单由 `ShipmentAllocationService` 完整处理。
- 库存不足踢单不记录 `kickOutWave`，只清空 Shopee 集波绑定并预留上游撤单接口。
- 需要接入真实上游撤单接口。

建议实现口径：

- `WaveRuleMatchService` 保持触发和补单职责。
- 库存不足踢单、清绑定、上游撤单优先由 `wms-wave` 的踢单流程统一处理。
- 当前服务只需要能识别踢单后的缺口并由计划任务补单。

### 9. 库存最优分配规则未在当前服务闭环

docx 要求：

- 集波后自动运行波次。
- 库存最优分配规则：到期日先进先出，其次工作站点位与库存点位半径最小，同半径低层货位优先。

当前代码：

- `WaveRuleMatchService` 只创建内部波次、加入出库单、调用 `WaveService#run`。
- 当前服务没有库存分配策略参数。

未完成点：

- 需要确认库存分配规则是否已在 `wms-wave` 模块实现。
- 如果需要当前服务传入工作站点位或策略参数，需要补充调用契约。
- 需要联调验证实际分配结果符合 docx 优先级。

## P1 订单池过滤和配置口径

### 10. cancel、挂起、异常单据过滤口径待确认

docx 要求：

- 集波抓单只抓正常单据。
- 上游取消、cancel、挂起、标记异常的单据都不抓。

当前代码：

- 基础 SQL 过滤包含 `leadingSts = 100`。
- 基础 SQL 过滤包含 `trailingSts = 100`。
- 基础 SQL 过滤包含 `processType = NORMAL`。
- 基础 SQL 过滤包含 `waveId = 0`。

未完成点：

- 需要确认 cancel、挂起、异常是否全部映射进现有状态字段。
- 如果存在独立字段或独立 processType，需要补 SQL 过滤。
- 需要补最小验证用例覆盖异常单据不入池。

### 11. `WAVE_RULE_FIELD_MATCHING` 生产配置值域仍需锁定

docx 要求：

- 数据字典 `WAVE_RULE_FIELD_MATCHING`。
- 标识为出库单字段。
- `value1` 为 `wave_rule` 表字段。
- `value2` 设置匹配条件，例如包含、等于，配置 `in`、`=`。

当前代码：

- `toRuleFieldMapping(...)` 已按 `identifier = shipment_header 字段`、`value1 = wave_rule 字段` 转换。
- 已有字段白名单。
- 已支持 `IN`、`EQ`、`LE`。
- 操作符有 normalize 逻辑。

未完成点：

- 需要在生产配置文档或初始化 SQL 中固定值域。
- 需要明确是否允许中文“包含/等于/小于等于”。
- 需要明确是否只允许 `IN`、`EQ`、`LE`，还是支持更多操作符。

建议配置口径：

- `identifier`：`shipment_header` 字段名。
- `value1`：`wave_rule` 字段名。
- `value2`：`IN`、`EQ`、`LE`。

## P2 代码结构和可维护性

### 12. 一波一单方法命名已收敛

当前代码：

- `assignSingleShipmentWaves(...)` 承担通用一波一单分流。
- 方法内部处理按单拣选、销售出库任务、MTO 任务、RT 等候选。
- RT 不使用 Shopee 波次号的特殊口径仍保留在流程说明中。

仍需关注点：

- RT 不使用 Shopee 波次号的特殊逻辑单独封装。
- 推拣货任务仍保留独立方法，因为它使用上游预写 Shopee 波次号。

## 非 WaveRuleMatchService 主责但仍需联动

- `wave_rule` 维护界面需要支持新增、修改规则。
- 分播墙明细界面需要支持 `waveRule` 多选绑定。
- 出库单界面按单拣选按钮需要只允许订单池 100 状态单据更新 `pickType = 1/null`。
- 出库单下发后自动分析 `shipmentCategory1`。
- 拣货任务头 `shopeeWave`、`waveRule` 字段需要和 `RunWave` 流程回写联调。
- `shopee_wave` 每日号段申请接口需要落库。
- WCS/AGV 取消任务和取消回库接口需要联调。

## 建议推进顺序

1. 接入推拣货任务首次集波分流。
2. 接入真实 ESS 集波校验接口。
3. 接入 Shopee 波次号段申请接口。
4. 接入 Flow Pick 封箱、换箱接口和失败回滚。
5. 与 `wms-wave` 联调库存不足踢单上游撤单和库存最优分配。
