diff --git a/src/main/java/com/gaotao/modules/api/service/impl/WmsMessageServiceImpl.java b/src/main/java/com/gaotao/modules/api/service/impl/WmsMessageServiceImpl.java index 0d88a2c..d2b7bfd 100644 --- a/src/main/java/com/gaotao/modules/api/service/impl/WmsMessageServiceImpl.java +++ b/src/main/java/com/gaotao/modules/api/service/impl/WmsMessageServiceImpl.java @@ -316,8 +316,41 @@ public class WmsMessageServiceImpl implements WmsMessageService { // 2. 参数验证 - rqrq validateWcsWareHouseParams(inData); + if("取货通知".equals(inData.getTransTypeDesc())) { + // 3. 幂等性验证:检查是否已处理过该消息 - rqrq + WcsCallbackTask existTask = wcsIntegrationMapper.getWcsCallbackTaskByBusinessKey( + inData.getSite(), + inData.getPalletId(), + inData.getTransTypeDesc(), + inData.getTaskNo(), + inData.getItemNo(), + inData.getToBarcode() + ); + + if (existTask != null) { + // 已存在相同的回调任务,直接返回成功,不执行任何业务逻辑 - rqrq + String idempotentMsg = String.format("消息已处理(幂等性验证),跳过重复操作 - taskId=%d, 栈板=%s, 类型=%s, taskNo=%s, itemNo=%d, toStation=%s, 原记录创建时间=%s", + existTask.getId(), + inData.getPalletId(), + inData.getTransTypeDesc(), + inData.getTaskNo(), + inData.getItemNo(), + inData.getToBarcode(), + existTask.getCreatedTime()); + + log.info(idempotentMsg + " - rqrq"); + + // 更新成功日志 - rqrq + long executionTime = System.currentTimeMillis() - startTime; + interfaceCallLogService.updateCallResult(logId, idempotentMsg, "SUCCESS", null, executionTime); + + return idempotentMsg; + } + } + log.info("幂等性验证通过,开始处理新消息 - rqrq:栈板={}, 类型={}, taskNo={}, itemNo={}, toStation={}", + inData.getPalletId(), inData.getTransTypeDesc(), inData.getTaskNo(), inData.getItemNo(), inData.getToBarcode()); - // 3. 根据业务类型分别处理 - rqrq + // 4. 根据业务类型分别处理 - rqrq String result; switch (inData.getTransTypeDesc()) { case "入库": @@ -339,7 +372,7 @@ public class WmsMessageServiceImpl implements WmsMessageService { throw new RuntimeException("不支持的事务类型:" + inData.getTransTypeDesc()); } - // 4. 更新成功日志 - rqrq + // 5. 更新成功日志 - rqrq long executionTime = System.currentTimeMillis() - startTime; interfaceCallLogService.updateCallResult(logId, result, "SUCCESS", null, executionTime); diff --git a/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java b/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java index 02f6b5e..93b8f55 100644 --- a/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java +++ b/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java @@ -174,6 +174,16 @@ public interface WcsIntegrationMapper { */ WmsTransportTask getActivePalletTransportTask(@Param("site") String site, @Param("palletId") String palletId); + /** + * @Description 查询栈板在wms_transport_task表中是否有未完成的任务 - rqrq + * @param site 站点 + * @param palletId 栈板编码 + * @return 未完成的运输任务列表(状态不是"已完成"或"已取消") + * @author rqrq + * @date 2025/11/26 + */ + WmsTransportTask getUnfinishedTransportTaskByPallet(@Param("site") String site, @Param("palletId") String palletId); + /** * 统计栈板明细数量 - AI制作 */ @@ -485,6 +495,25 @@ public interface WcsIntegrationMapper { */ void insertWcsCallbackTask(WcsCallbackTask callbackTask); + /** + * @Description 根据业务唯一键查询WCS回调任务是否已存在(幂等性验证)- rqrq + * @param site 站点 + * @param palletId 栈板ID + * @param transTypeDesc 操作类型 + * @param taskNo 任务号 + * @param itemNo 明细号 + * @param toStation 目标站点 + * @return WCS回调任务(如果已存在) + * @author rqrq + * @date 2025/11/26 + */ + WcsCallbackTask getWcsCallbackTaskByBusinessKey(@Param("site") String site, + @Param("palletId") String palletId, + @Param("transTypeDesc") String transTypeDesc, + @Param("taskNo") String taskNo, + @Param("itemNo") Integer itemNo, + @Param("toStation") String toStation); + /** * 查询指定状态的WCS回调任务列表 - AI制作 */ diff --git a/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/PalletCancelServiceImpl.java b/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/PalletCancelServiceImpl.java index fa97299..bf677dc 100644 --- a/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/PalletCancelServiceImpl.java +++ b/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/PalletCancelServiceImpl.java @@ -44,32 +44,43 @@ public class PalletCancelServiceImpl implements PalletCancelService { String site = data.getSite(); String palletId = data.getPalletId(); - System.out.println("开始取消WCS组盘 - rqrq,palletId=" + palletId); + log.info("开始取消WCS组盘 - rqrq,palletId={}", palletId); - // 检查栈板是否有AGV调度任务 - rqrq + // ⚠️ 前置校验:检查栈板是否已呼叫AGV送入立库(wms_transport_task表)- rqrq + WmsTransportTask unfinishedTask = wcsIntegrationMapper.getUnfinishedTransportTaskByPallet(site, palletId); + if (unfinishedTask != null) { + String taskNo = unfinishedTask.getTaskNo(); + String status = unfinishedTask.getStatus(); + log.warn("托盘已呼叫AGV送入立库,无法取消 - rqrq:palletId={}, taskNo={}, status={}", palletId, taskNo, status); + throw new RuntimeException("该托盘已经呼叫AGV送入立库,无法取消托盘,请先取消AGV任务(任务号:" + taskNo + ",状态:" + status + ")"); + } + + log.info("wms_transport_task表检查通过,无未完成任务 - rqrq"); + + // 检查栈板是否有AGV调度任务(这个是旧逻辑,保留兼容性)- rqrq WmsTransportTask transportTask = wcsIntegrationMapper.getActivePalletTransportTask(site, palletId); if (transportTask != null) { String taskStatus = transportTask.getStatus(); String taskNo = transportTask.getTaskNo(); - System.out.println("栈板存在运输任务 - rqrq,taskNo=" + taskNo + ",status=" + taskStatus); + log.info("栈板存在运输任务 - rqrq,taskNo={}, status={}", taskNo, taskStatus); if ("已下达".equals(taskStatus)) { // 任务已下达到AGV,不允许取消组盘 - rqrq - System.out.println("任务已下达到AGV,无法取消组盘 - rqrq"); + log.warn("任务已下达到AGV,无法取消组盘 - rqrq,taskNo={}", taskNo); throw new RuntimeException("已有AGV来提取,无法取消组盘"); } else if ("已预约".equals(taskStatus) || "已创建".equals(taskStatus)) { // 任务未下达到AGV,先取消AGV任务 - rqrq - System.out.println("任务状态为" + taskStatus + ",先取消AGV任务 - rqrq"); + log.info("任务状态为{},先取消AGV任务 - rqrq,taskNo={}", taskStatus, taskNo); try { agvTaskService.cancelAgvTask(site, taskNo); - System.out.println("AGV任务取消成功 - rqrq"); + log.info("AGV任务取消成功 - rqrq,taskNo={}", taskNo); } catch (Exception e) { - System.out.println("AGV任务取消失败 - rqrq:" + e.getMessage()); + log.error("AGV任务取消失败 - rqrq,taskNo={},error={}", taskNo, e.getMessage()); throw new RuntimeException("取消AGV任务失败:" + e.getMessage()); } } } else { - System.out.println("栈板不存在运输任务,继续取消组盘 - rqrq"); + log.info("栈板不存在运输任务,继续取消组盘 - rqrq"); } // 获取当前用户 - rqrq @@ -77,11 +88,11 @@ public class PalletCancelServiceImpl implements PalletCancelService { // 1. 更新pallet_detail的wcs_flag=1 - rqrq wcsIntegrationMapper.updateAllPalletDetailWcsFlagToOne(site, palletId); - System.out.println("已更新栈板明细wcs_flag为1 - rqrq"); + log.info("已更新栈板明细wcs_flag为1 - rqrq,palletId={}", palletId); // 2. 更新pallet的calling_flag=N - rqrq wcsIntegrationMapper.updatePalletCallingFlag(site, palletId, "N", username); - System.out.println("已更新栈板calling_flag为N - rqrq"); + log.info("已更新栈板calling_flag为N - rqrq,palletId={}", palletId); // 3. 调用WCS API通知取消组盘 - rqrq SpecialPalletTask pushData = new SpecialPalletTask(); @@ -90,7 +101,7 @@ public class PalletCancelServiceImpl implements PalletCancelService { pushData.setOperationType(1); wcsApiService.SpecialPalletTask(pushData); - System.out.println("取消WCS组盘完成 - rqrq"); + log.info("取消WCS组盘完成 - rqrq,palletId={}", palletId); } } diff --git a/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/WcsIntegrationServiceImpl.java b/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/WcsIntegrationServiceImpl.java index e9f444d..8f396ec 100644 --- a/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/WcsIntegrationServiceImpl.java +++ b/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/WcsIntegrationServiceImpl.java @@ -2246,6 +2246,17 @@ public class WcsIntegrationServiceImpl implements WcsIntegrationService { System.out.println("开始取消WCS组盘 - rqrq,palletId=" + palletId); + // ⚠️ 前置校验:检查栈板是否已呼叫AGV送入立库(wms_transport_task表)- rqrq + WmsTransportTask unfinishedTask = wcsIntegrationMapper.getUnfinishedTransportTaskByPallet(site, palletId); + if (unfinishedTask != null) { + String taskNo = unfinishedTask.getTaskNo(); + String status = unfinishedTask.getStatus(); + System.err.println("托盘已呼叫AGV送入立库,无法取消 - rqrq:palletId=" + palletId + ", taskNo=" + taskNo + ", status=" + status); + throw new RuntimeException("该托盘已经呼叫AGV送入立库,无法取消托盘,请先取消AGV任务(任务号:" + taskNo + ",状态:" + status + ")"); + } + + System.out.println("wms_transport_task表检查通过,无未完成任务 - rqrq"); + // 获取当前用户 - rqrq String username = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUsername(); diff --git a/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml b/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml index 83f83a7..53c243f 100644 --- a/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml +++ b/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml @@ -383,6 +383,27 @@ ORDER BY created_time DESC + + + + + + INSERT INTO wcs_callback_task (