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 (