Files
huachuang/docs/lms日计划备货套管代码导读.md
2026-08-17 18:00:49 +08:00

257 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LMS 日计划、备货、套管代码导读
本文对应当前 LMS 日计划和管芯调度实现,用于快速定位业务入口、调度决策、现场任务以及完成回调。
## 一、先建立整体认识
系统分为两条调用链:
1. 人工操作链:页面调用日计划接口,只修改订单、备货、套管状态,不直接创建现场任务。
2. 定时调度链XXL-JOB 查询状态为“进行中且未完成”的日计划,按顺序或权重策略创建现场任务;任务完成回调后才累计数量。
备货和套管共用日计划,但分别维护状态、进度、策略和 Claim因此两种作业可以并行互不占用对方的领取记录。
## 二、日计划人工操作时序
```mermaid
sequenceDiagram
autonumber
actor Worker as 工人
participant Page as 日计划管理/作业页面
participant Controller as DailyPlanController
participant Service as DailyPlanServiceImpl
participant Mapper as DailyPlanMapper
participant DB as MySQL
Worker->>Page: 创建或查看日计划
Page->>Controller: create / managementPage / workPage
Controller->>Service: 创建或查询
Service->>Mapper: 读写日计划
Mapper->>DB: lms_daily_plan
DB-->>Page: 日计划及当前状态
Worker->>Page: 开始订单并确认计划量
Page->>Controller: startOrder(planQty, appendQty, version)
Controller->>Service: startOrder
Service->>Mapper: 校验未开始和版本,更新订单状态
Service->>Mapper: 写数量及订单操作日志
Worker->>Page: 开始备货或开始套管
Page->>Controller: startStocking / startSleeving
Controller->>Service: 变更对应作业状态
Service->>Mapper: 状态改为进行中并记录日志
Note over Service,DB: 此处只改变状态,不创建 Task 任务
opt 追加数量
Worker->>Page: 追加数量
Page->>Controller: appendQuantity
Controller->>Service: appendQuantity
Service->>Mapper: 增加 append_qty
Service->>Mapper: 已完成作业重新改为进行中
end
opt 取消或恢复
Worker->>Page: 取消/恢复订单、备货或套管
Page->>Controller: cancelXxx / restoreXxx
Controller->>Service: 校验状态和乐观锁版本
Service->>Mapper: 更新状态并记录原因
end
```
关键规则:
- 开始订单、开始备货、开始套管都不会直接下发任务。
- 订单取消会阻止新任务领取;取消之前已合法创建的任务仍可完成并回写实际数量。
- 追加数量作用于整个日计划,所以已完成的备货、套管都会重新进入进行中,不需要在作业页分别追加。
- 所有页面操作都携带 `version`,防止页面操作相互覆盖。
## 三、备货定时调度时序
```mermaid
sequenceDiagram
autonumber
participant XXL as XXL-JOB<br/>dailyPlanStockingJob
participant Dispatch as CoreTubeTaskDispatchServiceImpl
participant Schedule as DailyPlanScheduleServiceImpl
participant CoreDB as CoreTubeMapper
participant PointDB as StockingIvtMapper
participant Task as Task模块
XXL->>Dispatch: dispatchStockingOnce()
Dispatch->>Schedule: previewStockingCandidates()
Schedule-->>Dispatch: 按顺序/权重排列的候选
loop 每种物料规格只检查一次
Dispatch->>CoreDB: 查询对接位可用目标管芯
alt 对接位存在目标管芯
Dispatch->>Schedule: claimStockingCandidate(日计划ID)
Schedule-->>Dispatch: 单根Claim
Dispatch->>CoreDB: 原子预占一根管芯
Dispatch->>Task: 创建CORE_TUBE_STOCKING_PICK
Task-->>Dispatch: taskId
Dispatch->>CoreDB: 管芯绑定taskId
Dispatch->>Schedule: confirmTaskCreated(claimToken)
Note over Schedule: 只有单根任务创建成功才推进权重
Dispatch-->>XXL: 本轮结束,只创建一条任务
else 当前规格不能直接抓取
Note over Dispatch: 跳到下一规格,不提前消耗权重
end
end
alt 所有规格都不能直接抓取且对接位有托盘
Dispatch->>PointDB: 查询空缓存位
Dispatch->>Task: 创建CORE_TUBE_PALLET_OUT
Note over Dispatch: 本轮只移出一托盘,不创建抓取任务
else 对接位为空
Dispatch->>PointDB: 为候选规格选择缓存位托盘
Note over PointDB: 优先选择可满足剩余量的最小托盘<br/>否则选择库存最多托盘
Dispatch->>Task: 创建CORE_TUBE_PALLET_IN
Note over Dispatch: 同规格未完成托盘任务使用业务键防重
else 无可用托盘
Dispatch-->>XXL: 记录备货区无可用管芯并结束
end
```
备货数量何时增加:
- 托盘移入或移出完成:只更新托盘点位和整托盘管芯位置,`stocked_qty` 不增加。
- 桁架成功抓取一根管芯并送入管芯库:`stocked_qty + 1`
- 每轮调度每个租户最多创建一条现场任务。
## 四、套管定时调度时序
```mermaid
sequenceDiagram
autonumber
participant XXL as XXL-JOB<br/>dailyPlanSleevingJob
participant Dispatch as CoreTubeTaskDispatchServiceImpl
participant Schedule as DailyPlanScheduleServiceImpl
participant CoreDB as CoreTubeMapper
participant Task as Task模块
XXL->>Dispatch: dispatchSleevingOnce()
Dispatch->>Schedule: previewSleevingCandidates()
Schedule-->>Dispatch: 按套管策略排列的候选
loop 每种物料规格只检查一次
Dispatch->>CoreDB: 查询管芯库一根可用目标管芯
alt 管芯存在
Dispatch->>Schedule: claimSleevingCandidate(日计划ID)
Schedule-->>Dispatch: 单根Claim
Dispatch->>CoreDB: 原子预占管芯
Dispatch->>Task: 创建CORE_TUBE_SLEEVING_OUT
Task-->>Dispatch: taskId
Dispatch->>CoreDB: 管芯绑定taskId
Dispatch->>Schedule: confirmTaskCreated(claimToken)
Dispatch-->>XXL: 本轮结束,只创建一根
else 管芯库没有目标管芯
Dispatch->>Task: 查询该物料的未完成备货任务
alt 存在托盘移入或备货抓取任务
Dispatch-->>XXL: 记录“正在备货”,继续下一规格
else 不存在备货任务
Dispatch-->>XXL: 记录“备货区库存不足”,继续下一规格
end
end
end
```
套管数量只在单根管芯出库任务完成后增加。套管策略和备货策略分别存储,因此可以一边使用顺序模式、一边使用权重模式。
## 五、任务完成与取消回调时序
```mermaid
sequenceDiagram
autonumber
participant ACS as AGV/桁架/套管设备
participant Task as Task模块
participant Handler as CoreTubeStockingTask<br/>CoreTubeSleevingTask
participant Dispatch as CoreTubeTaskDispatchServiceImpl
participant CoreDB as lms_core_tube
participant Plan as DailyPlanScheduleServiceImpl
ACS->>Task: 上报任务完成或取消
Task->>Handler: 按handleCode调用处理器
alt 托盘移入/移出完成
Handler->>Dispatch: handleFinished(taskId, false)
Dispatch->>CoreDB: 原子迁移源/目标点位
Dispatch->>CoreDB: 更新整托盘管芯当前位置
Note over Plan: 不更新日计划完成数量
else 单根备货抓取完成
Handler->>Dispatch: handleFinished(taskId, false)
Dispatch->>CoreDB: 管芯进入管芯库并清除托盘格位
Dispatch->>Plan: increaseStockedQuantity(..., 1)
Plan->>Plan: 确认Claim并写进度日志
else 单根套管出库完成
Handler->>Dispatch: handleFinished(taskId, true)
Dispatch->>CoreDB: 管芯进入套管设备阶段
Dispatch->>Plan: increaseSleevedQuantity(..., 1)
Plan->>Plan: 确认Claim并写进度日志
else 单根任务取消
Handler->>Dispatch: handleCancelled(taskId, ...)
Dispatch->>CoreDB: 管芯恢复原阶段和可用状态
Dispatch->>Plan: releaseClaim(claimToken)
end
Note over Dispatch,Plan: 更新语句绑定taskId或claimToken<br/>重复完成、重复取消不会重复累计
```
## 六、推荐代码阅读顺序
### 第一步:看页面能做什么
- `DailyPlanController`:所有日计划管理和作业接口入口。
- `DailyPlanService`:人工操作能力清单。
- `DailyPlanServiceImpl`:订单、备货、套管的状态转换和追加数量逻辑。
先重点阅读这些方法:
1. `startOrder`
2. `appendQuantity`
3. `startStocking` / `startSleeving`
4. `cancelOrder` / `restoreOrder` / `finishOrder`
5. `updateSort` / `updateWeight` / `updateStrategy`
### 第二步:看定时器入口
- `DailyPlanCoreTubeJob.dailyPlanStockingJob`
- `DailyPlanCoreTubeJob.dailyPlanSleevingJob`
这两个方法本身很薄,只负责按租户触发调度。核心判断都在 `CoreTubeTaskDispatchServiceImpl`
### 第三步:看备货和套管如何选任务
- `CoreTubeTaskDispatchServiceImpl.dispatchStockingOnce`:对接位优先、托盘移出/移入及规格跳过。
- `CoreTubeTaskDispatchServiceImpl.dispatchSleevingOnce`:管芯库单根出库和缺货日志。
- `CoreTubeTaskDispatchServiceImpl.createSingleTubeTask`Claim、管芯预占、Task 创建及权重确认的事务边界。
- `CoreTubeTaskDispatchServiceImpl.createPalletTask`:一次只创建一条托盘任务的决策。
### 第四步:看顺序、权重和并发控制
- `DailyPlanScheduleServiceImpl.previewCandidates`:只排列候选,不分配库存、不推进权重。
- `DailyPlanScheduleServiceImpl.claimCandidate`:为一根现场任务创建排他 Claim。
- `DailyPlanScheduleServiceImpl.confirmTaskCreated`:任务真正创建成功后才推进权重。
- `DailyPlanScheduleServiceImpl.increaseQuantity`:任务完成后的幂等进度确认。
- `DailyPlanStrategyInitializer`:为新租户并发安全地初始化默认顺序策略。
### 第五步:看任务完成后发生什么
- `CoreTubeStockingTask`:托盘和备货抓取任务回调入口。
- `CoreTubeSleevingTask`:套管出库任务回调入口。
- `CoreTubeTaskDispatchServiceImpl.handleFinished`:完成后的库存位置和日计划数量更新。
- `CoreTubeTaskDispatchServiceImpl.handleCancelled`:取消后的管芯与 Claim 恢复。
### 第六步:最后看 SQL 原子条件
- `DailyPlanMapper.xml`:候选条件、状态转换、已备货/已套管数量原子累加。
- `DailyPlanClaimMapper.xml`Claim 活动、确认、释放和过期条件。
- `CoreTubeMapper.xml`:管芯预占、绑定任务、完成和取消。
- `StockingIvtMapper.xml`:对接位、缓存位、托盘选择和托盘点位迁移。
## 七、最重要的四个业务边界
1. 页面“开始备货/开始套管”只改变状态,真正任务由 XXL-JOB 创建。
2. 候选预览不等于库存分配;只有创建单根任务成功后才消耗权重。
3. 托盘 AGV 任务不增加日计划进度,单根管芯任务完成才增加一根。
4. 备货和套管有独立状态、策略、Claim 和进度,同一日计划上可以并行执行。