Files
ttx-project-doc/集波/SHOPEE_010_出库集波V1.2_WaveRuleMatchService_流程文档.md
T

10 KiB
Raw Blame History

WaveRuleMatchService 当前流程文档

对应代码:wms-wave/src/main/groovy/com/ittx/wms/wave/service/shopee/WaveRuleMatchService.groovy

本文只描述当前代码已经存在的流程,不保留已删除方法或历史占位方案。

1. 服务职责

WaveRuleMatchService 负责 Shopee 自动集波的工作站调度、规则匹配、Shopee 波次号准备、格口占用、picking task 同步、内部 wave 创建与运行,以及失败回滚和处理日志。

当前 ticketType 分流:

ticketType 类型 分流方法
1 SALES_TASK assignTaskTicket
2 SALES_ORDER assignOrder
3 RTS assignOrder
4 MTO_ORDER assignOrder
5 MTO_TASK assignTaskTicket
6 RT assignRt

MTO_TASK 保持任务单流程;SALES_ORDERMTO_ORDERRTS 共用订单流程。

2. 调度入口

2.1 assignShopeeWaveToAcceptedWorkStations

计划任务入口:

assignShopeeWaveToAcceptedWorkStations(session, warehouseCode, workStationCode)
├─ 查询当前仓库可接单且启用的拣选工作站
├─ 指定 workStationCode 时只处理该工作站
├─ 按可用空格口数量降序、工作站 ID 升序排序
├─ 逐个调用 matchByStation(session, workstation)
└─ 单个工作站失败不阻断后续工作站

只要方法已经接收 WcsWorkStationshipmentType 都直接读取 workstation.shipmentType,不再单独传参。

2.2 matchByStation

matchByStation(session, workstation)
├─ 校验 workstation.status=ENABLE
├─ 校验 warehouseCode
├─ 校验 acceptStatus=OPEN
├─ 获取 warehouseCode 维度 Redis 锁
├─ ORDER_PICK
│  └─ assignSingles
└─ BATCH_PICK
   ├─ 查询操作员技能与工作站 waveRule 交集
   ├─ findEnabledRules
   ├─ fillShortage,优先补当前工作站已占用格口
   └─ 无补单结果时按规则 ticketType 分流
      ├─ 1/5 → assignTaskTicket
      ├─ 2/3/4 → assignOrder
      └─ 6 → assignRt

仓库级锁覆盖同一工作站匹配轮次,最终在 finally 中解锁并记录结束日志。

3. 快速拣选

assignSingles 处理 pickType=1 候选,每单独占一个格口和一个内部 wave。

assignSingles(warehouseCode, workstation)
├─ findSingleEmptyCells(workstation.id)
├─ findSingleShipments(warehouseCode, emptyCellCount, workstation)
└─ 逐单处理
   ├─ findShipmentExt
   ├─ 确定 Shopee 波次号
   │  ├─ shopeeWaveCode 已有值 → 直接使用
   │  ├─ RT → 使用 shipmentCode
   │  └─ 其他 → acquireWave
   ├─ RT → backfillRtShopeeWaveCode
   ├─ 非 RT 且使用已有波次号 → createInternalShopeeWave
   ├─ occupySingleCell
   ├─ createWave
   ├─ syncShopeePickingTaskAndFilterAcceptedShipments(..., ticketType)
   │  └─ 仅 RT 跳过外部接口
   ├─ updateLocalShopeeWaveBinding
   └─ addToWave

快速拣选不写 waveRule,调用 updateLocalShopeeWaveBinding 时传空规则编码。

4. 任务单分流

SALES_TASKMTO_TASK 共用 assignTaskTicket

assignTaskTicket(warehouseCode, workstation, rule, ticketType)
├─ findSingleEmptyCells(workstation.id, rule)
├─ findTaskTicketShipments(..., ticketType, rule)
└─ 逐单处理
   ├─ 从 shipment_header_ext1 读取 shopeeWaveCode
   ├─ createInternalShopeeWave
   │  └─ code + ticketType 不存在时创建 shopee_wave
   ├─ occupySingleCell
   ├─ createWave
   ├─ syncShopeePickingTaskAndFilterAcceptedShipments(..., ticketType)
   ├─ updateLocalShopeeWaveBinding
   └─ addToWave

任务单同步完成后直接执行本地绑定,不再经过独立绑定转发方法,也不重复执行 Shopee 波次锁和可用性检查。

5. 订单分流

SALES_ORDERMTO_ORDERRTS 共用 assignOrder

assignOrder(warehouseCode, workstation, rule, ticketType)
├─ findUnusedCells(workstation.id, rule)
└─ 对首个可用格口
   ├─ findAvailableShipments(..., ticketType)
   ├─ hasEmptyCellMinShipments
   ├─ acquireWave(warehouseCode, ticketType)
   └─ assignAcquiredWaveToCell
      └─ assignToCell

首次分配每轮只启动一个新格口;后续容量缺口由 fillShortage 优先处理。

6. RT 分流

assignRt 是 RT 专用的一单一格口流程:

assignRt(warehouseCode, workstation, rule)
├─ findSingleEmptyCells(workstation.id, rule)
├─ findRtTicketShipments
└─ 逐单处理
   ├─ 使用 shipmentCode 作为本地 Shopee 波次号
   ├─ backfillRtShopeeWaveCode
   ├─ occupySingleCell
   ├─ createWave
   ├─ updateLocalShopeeWaveBinding
   └─ addToWave

RT 不申请接口号段,也不调用 Shopee picking task 外部接口。

7. 缺口补单

fillShortage 只按关联 shopee_wave.status=200(USING) 判断格口是否需要进入补单检查。

fillShortage(warehouseCode, workstation)
├─ findShortage(workstation.id)
├─ 逐格口读取 currentWaveRule 与 ticketType
├─ calcNeedQty
├─ 记录需要补单的格口处理日志
├─ resolveBoundShipmentGroup
├─ findAvailableShipmentBatch(..., shopeeWaveCode, groupKey)
└─ assignToCell

补单不重新申请 Shopee 波次号,并保持同一 Shopee 波次的 groupKey 一致。

8. 单格口完整分配

assignToCell 在格口锁内完成普通订单首次分配或补单:

assignToCell(...)
├─ 校验 ticketType、shipmentIds、shopeeWaveCode
├─ 获取 cellLockKey(cell.id)
├─ pickCellShipments,按剩余容量截断候选
├─ occupyCell
├─ createWave
├─ Shopee 同步
│  ├─ 新格口 → syncShopeePickingTaskAndFilterAcceptedShipments
│  └─ 已有同波次格口 → syncShopeeAppendOrderAndFilterAcceptedShipments
├─ bindBatchShipmentWave
│  ├─ waveBindLockKey
│  ├─ isWaveAvailable
│  └─ updateLocalShopeeWaveBinding
├─ addToWave
├─ 非 Flow Pick 达到 maxShipments → shopee_wave.status=400(FULL)
└─ finally 释放格口锁

assignAcquiredWaveToCell 只承接已经取得的 Shopee 波次号,并调用 assignToCell

9. Shopee picking task 同步

9.1 首次同步

syncShopeePickingTaskAndFilterAcceptedShipments 显式接收 ticketType

  • RT:不调用外部接口,直接返回当前单据。
  • 其他类型:始终调用 sendShopeePickingTaskRequest
  • 同步成功后写 pickingTaskSyncWaveCode,并更新 shopee_wave.startPickUploadSts
  • 根据 Shopee 返回失败列表解析踢单,失败单写入 kickOutWave

接口映射:

ticketType 接口
SALES_TASK Sales start picking task
SALES_ORDER Sales create picking task
RTS / MTO_ORDER RTS/MTO create picking task
MTO_TASK MTO start picking task

9.2 补单同步

已有同波次格口通过 syncShopeeAppendOrderAndFilterAcceptedShipments 调用 append order

  • SALES_ORDER → Sales append order
  • RTS / MTO_ORDER → RTS/MTO append order

10. Shopee 波次记录

10.1 acquireWave

acquireWave(warehouseCode, ticketType)waveAcquireLockKey(ticketType) 锁内查询:

where ticketType = :ticketType
  and sourceType = INTERFACE
  and waveDate >= 当前时间减 10 小时
  and status = UNUSED
order by rand()
limit 1

该方法只返回候选号段,不在此处更新状态。

10.2 createInternalShopeeWave

对单据已有的 shopeeWaveCode,先按 code + ticketType 查询;不存在时创建:

  • sourceType=INTERNAL
  • bizType=NONE
  • status=USING

已存在记录不修改。

10.3 backfillRtShopeeWaveCode

RT 使用已有 shopeeWaveCodeshipmentCode

  • pickingTaskSyncWaveCode 为空时回写本地标识。
  • 创建或更新 RT 类型的 shopee_wave
  • 状态设置为 USING

11. 本地绑定与内部 wave

11.1 updateLocalShopeeWaveBinding

sortingWallCellLockKey(cell.id) 锁内:

  1. 从出库单解析唯一 ticketType
  2. 更新 wcs_sorting_wall_cell 的 Shopee 波次、当前规则和 ticketType。
  3. 更新内部 wave 的规则、分播墙、格口、Shopee 波次和 ticketType。
  4. 更新 shopee_wave.status:一波一单类型置为 FULL,普通订单保持 USING

该方法不回写 shipment_header_ext1 的绑定关系;单据与本地 wave 的关系由内部 wave 承载。

11.2 createWave / addToWave

  • createWave:解析 masterCode,调用 waveSvc.createInternalWave,并回写内部 wave 的规则、格口和 ticketType。
  • addToWave:调用 shipmentHeaderService.addMultipleToWave 后执行 waveSvc.run

12. 失败处理

失败点 当前处理
格口占用失败 返回错误,不覆盖其他波次
内部 wave 创建失败 新占格口调用 releaseSingleCell
Shopee 同步失败 释放新占格口并调用 cancelWave
Shopee 返回踢单 markKickOut 写入 shipment_header_ext1.kickOutWave
本地绑定失败 释放新占格口并调用 cancelWave
加入或运行内部 wave 失败 释放新占格口并调用 cancelWave

cancelFailedShopeeWaves 供计划任务取消状态为 FAILED 且已绑定格口的内部 wave。

13. 查询与规则匹配

当前候选查询入口:

  • findSingleShipments:快速拣选候选。
  • findTaskTicketShipmentsSALES_TASK / MTO_TASK 候选。
  • findRtTicketShipmentsRT 候选。
  • findAvailableShipments / findAvailableShipmentBatch:普通订单首次分配和补单。

规则过滤包括:

  • appendSingleFilter
  • appendKickOutFilter
  • appendGroupKeyFilter
  • appendOrderStructureFilter
  • appendRuleMatch
  • buildOrderByClause

普通订单首先确定候选 groupKey,再抓取同组订单;补单通过 resolveBoundShipmentGroup 延续已有波次的组特征。

14. 当前方法关系

assignShopeeWaveToAcceptedWorkStations
└─ matchByStation
   ├─ assignSingles
   └─ BATCH_PICK
      ├─ fillShortage
      │  └─ assignToCell
      ├─ assignTaskTicket
      ├─ assignOrder
      │  └─ assignAcquiredWaveToCell
      │     └─ assignToCell
      └─ assignRt

assignSingles / assignTaskTicket / assignRt
├─ occupySingleCell
├─ createWave
├─ updateLocalShopeeWaveBinding
└─ addToWave

assignToCell
├─ occupyCell
├─ createWave
├─ syncShopeePickingTaskAndFilterAcceptedShipments
│  或 syncShopeeAppendOrderAndFilterAcceptedShipments
├─ bindBatchShipmentWave
├─ addToWave
└─ cancelWave / releaseSingleCell