From 745a5d829a807676d60bcd1666d9eaec9103df4f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B8=B8=E7=86=9F=E5=90=B4=E5=BD=A6=E7=A5=96?=
业务逻辑(重要!请仔细阅读):
*
+ * 【循环盘点(CYCLE)】:
+ * 1. 首次推送1个任务,包含10个栈板
+ * 2. 任务完成后自动推送下一批10个栈板
+ * 3. 始终保持最多1个任务在流转
+ *
+ * 【手工盘点(MANUAL)】:
+ * 1. 首次推送策略(根据总栈板数决定):
+ * - 总栈板数 ≤ 5:推送1个任务(包含所有栈板)
+ * - 总栈板数 > 5:推送2个任务(每个任务最多5个栈板)
+ * 例如:8个栈板 → 任务1(5个)+ 任务2(3个)
+ * 15个栈板 → 任务1(5个)+ 任务2(5个),剩余5个等后续推送
+ * 2. 因为手工盘点有2个通道,可以2个人同时操作
+ * 3. 每个任务完成后,自动推送下一批5个栈板
+ * 4. 始终保持最多2个任务同时流转
+ *
+ * 【推送流程】:
* 1. 校验盘点单状态必须为"已下达"(RELEASED)
- * 2. 生成wms_order_task单据,明细是各个栈板
- * 3. 每次推送10个栈板,尽量每层都有栈板(按层轮询选取)
- * 4. 推送成功后状态改为"盘点中"(CHECKING)
- * 5. 第10个栈板出库后,由其他方法调用continuePushCount推送后续栈板
+ * 2. 根据盘点类型执行不同的推送策略
+ * 3. 生成wms_order_task单据,明细是各个栈板
+ * 4. 推送给WCS,由立库系统执行出库
+ * 5. 推送成功后更新盘点单状态为"盘点中"(CHECKING)
+ *
+ * 【自动流转机制】:
+ * - 当任务的所有托盘盘点完成后,会自动调用continuePushCount推送下一批
+ * - 形成"推送→盘点→推送→盘点"的自动循环
+ * - 直到所有托盘都推送完成
*
+ *
+ * @param query 推送参数(包含site、countNo、username)
+ * @return int 本次推送的栈板总数
+ * @author rqrq
*/
@Override
@Transactional(rollbackFor = Exception.class)
@@ -781,11 +806,61 @@ public class PhysicalInventoryServiceImpl extends ServiceImpl业务逻辑(重要!请仔细阅读):
*
+ * 【调用时机】:
+ * - 由handleTaskAfterCount方法在任务完成后自动调用
+ * - 不是手动调用,而是自动触发的
+ *
+ * 【循环盘点(CYCLE)】:
+ * 1. 校验未完成任务数:最多允许1个任务
+ * 2. 有未完成任务时,直接返回0(不推送)
+ * 3. 无未完成任务时,推送下一批10个栈板
+ *
+ * 【手工盘点(MANUAL)】:
+ * 1. 校验未完成任务数:最多允许2个任务
+ * 2. 已有2个未完成任务时,直接返回0(不推送,等待其他任务完成)
+ * 3. 未完成任务数<2时,推送下一批5个栈板
+ * 4. 形成动态平衡:始终保持最多2个任务同时流转
+ *
+ * 【流转示例 - 手工盘点15个托盘】:
+ * 首次:推送任务1(5个)+ 任务2(5个)
+ * ↓
+ * 任务1完成 → continuePushCount触发
+ * ├─ 检查未完成任务数:1个(任务2)
+ * ├─ 判断:1 < 2(允许推送)✅
+ * └─ 推送任务3(5个)
+ * 现在:任务2 + 任务3 并行
+ * ↓
+ * 任务2完成 → continuePushCount触发
+ * ├─ 检查未完成任务数:1个(任务3)
+ * ├─ 判断:1 < 2(允许推送)✅
+ * ├─ 查询未推送托盘数:0个
+ * └─ 返回0(无更多托盘)
+ * ↓
+ * 任务3完成 → continuePushCount触发
+ * └─ 查询未推送托盘数:0个
+ * └─ 返回0(无更多托盘)
+ *
+ * 【并发控制机制】:
+ * - 通过查询未完成任务数来控制并发
+ * - 循环盘点:最多1个任务(单通道)
+ * - 手工盘点:最多2个任务(双通道)
+ * - 超过上限时返回0,不抛异常(因为是自动触发,不需要中断流程)
+ *
+ * 【推送流程】:
* 1. 校验盘点单状态必须是"盘点中"
- * 2. 校验是否存在未完成的任务单(防止重复下达)
- * 3. 查询未推送的栈板(task_no为空的)
- * 4. 每次推送10个栈板,尽量每层都有栈板
+ * 2. 查询当前未完成的任务数
+ * 3. 判断是否达到并发上限
+ * 4. 未达到上限则推送下一批栈板
* 5. 生成wms_order_task单据并推送给WCS
*
+ *
+ * @param query 推送参数(包含site、countNo、username)
+ * @return int 本次推送的栈板数(0表示未推送或无更多托盘)
+ * @author rqrq
*/
@Override
@Transactional(rollbackFor = Exception.class)
@@ -825,17 +947,41 @@ public class PhysicalInventoryServiceImpl extends ServiceImpl+ * - PDA盘点完成(pdaSubmitCount) + * - RFID龙门架盘点完成(handleCountRfidCallback) + * - 快速盘点完成(pdaQuickSubmitCount) + *+ * + *
业务逻辑(重要!请仔细阅读):
+ *+ * 【处理流程】: + * 1. 查询该栈板关联的任务号(count_pallet.task_no) + * 2. 如果没有任务号,说明不是通过推送出库的,跳过处理 + * (例如:手工盘点中手动添加的托盘,不走推送流程) + * 3. 更新wms_order_task_detail状态为"已完成" + * 4. 检查该任务的所有明细是否都已完成 + * 5. 如果都完成了,更新wms_order_task主表状态为"已完成" + * 6. 触发continuePushCount自动推送下一批 + * + * 【自动流转机制】: + * - 任务的所有托盘盘点完成后,自动推送下一批 + * - 循环盘点:推送10个托盘 + * - 手工盘点:推送5个托盘,但受2个任务并发限制 + * - 形成"推送→盘点→推送→盘点"的自动循环 + * + * 【并发场景 - 手工盘点】: + * 场景1:任务1和任务2同时执行 + * - 任务1的最后一个托盘盘点完成 → 触发推送任务3 + * - 任务2还在执行 + * - 结果:任务2 + 任务3 并行(2个任务)✅ + * + * 场景2:已有2个任务在执行 + * - 任务2的最后一个托盘盘点完成 → 尝试推送 + * - 任务3还在执行 + * - continuePushCount检查:已有1个未完成任务,但<2,可以推送 + * - 如果有剩余托盘,推送任务4 + * - 如果无剩余托盘,返回0 + * + * 【防重复调用】: + * - 检查主表状态,如果已是"已完成",跳过触发推送 + * - 避免重复调用导致重复推送 + * + * 【异常处理】: + * - continuePushCount失败不抛异常 + * - 避免影响当前托盘的盘点结果保存 + * - 只记录日志,不中断流程 + *+ * + * @param site 工厂编码 + * @param countNo 盘点单号 + * @param palletId 托盘号 + * @param username 用户名 + * @author rqrq + */ private void handleTaskAfterCount(String site, String countNo, String palletId, String username) { // 1. 查询该栈板关联的任务号 - rqrq String taskNo = baseMapper.getTaskNoByPallet(site, countNo, palletId); if (!StringUtils.hasText(taskNo)) { // 没有任务号,说明不是通过推送出库的,不需要处理任务单 - rqrq + // 例如:手工盘点中手动添加的托盘,不走推送流程 - rqrq log.info("该栈板没有关联任务号,跳过任务单处理,palletId: {}", palletId); return; } @@ -2409,26 +2612,45 @@ public class PhysicalInventoryServiceImpl extends ServiceImpl