diff --git a/src/main/java/com/gaotao/modules/api/service/impl/AgvMessageServiceImpl.java b/src/main/java/com/gaotao/modules/api/service/impl/AgvMessageServiceImpl.java index 895513f9..32ef5c77 100644 --- a/src/main/java/com/gaotao/modules/api/service/impl/AgvMessageServiceImpl.java +++ b/src/main/java/com/gaotao/modules/api/service/impl/AgvMessageServiceImpl.java @@ -43,6 +43,10 @@ import java.util.Map; @Autowired private PalletMapper palletMapper; + /** + * 老AGV接收仅在当前事务内条件新增一条在线明细;重复动作成功返回,不再生成新的等待询问。- rqrq + * 旧协议未传site,以全局唯一taskId对应运输主任务的site作为显式业务工厂,不申请写入锁。- rqrq + */ @Override @Transactional public String agvTaskFeedback(AgvFeedbackData inData) { @@ -63,12 +67,17 @@ import java.util.Map; log.info("接收AGV任务反馈:{}", requestJson); // 2. 参数验证 - if (inData == null || !StringUtils.hasText(inData.getTaskId())) { - throw new RuntimeException("参数验证失败:任务ID不能为空"); + if (inData == null || !StringUtils.hasText(inData.getTaskId()) + || !StringUtils.hasText(inData.getTargetPoint())) { + throw new RuntimeException("参数验证失败:任务ID和目标点不能为空"); } + + // 回调业务键和站点去除外围空格,避免同一任务或点位因空格被误判为新动作。- rqrq + String taskNo = inData.getTaskId().trim(); + String targetPoint = inData.getTargetPoint().trim(); - // 3. 根据taskId查询运输任务 - WmsTransportTask transportTask = getTransportTaskById(inData.getTaskId()); + // 按旧协议全局唯一taskId读取运输主任务,查不到或命中多条均不能继续落明细。- rqrq + WmsTransportTask transportTask = getTransportTaskById(taskNo); if (transportTask == null) { throw new RuntimeException("未找到对应的运输任务:" + inData.getTaskId()); } @@ -78,12 +87,15 @@ import java.util.Map; if (!StringUtils.hasText(palletId)) { throw new RuntimeException("运输任务中未找到栈板信息"); } - WmsTransportTask checkTask= wcsIntegrationMapper.getTransportTaskByTaskNo(inData.getTaskId()); - if(checkTask==null){ - throw new RuntimeException("运输任务不存在"); + + // 旧AGV请求不含site,使用已校验主任务工厂并显式传入写入条件,避免固定55导致串厂。- rqrq + if (!StringUtils.hasText(transportTask.getSite())) { + throw new RuntimeException("运输任务缺少工厂编码:" + taskNo); } + String site = transportTask.getSite().trim(); + WmsTransportTask checkTask = transportTask; String statusDesc=""; - if(inData.getTargetPoint().equals(checkTask.getToLocation())){ + if(targetPoint.equals(checkTask.getToLocation())){ //业务逻辑转移到定时任务 // // 5. 更新栈板calling_flag为N // String username = "AGV_SYSTEM"; @@ -105,21 +117,35 @@ import java.util.Map; // updatePalletLocationOnly(transportTask, username); // } statusDesc="送货完成"; - }else if(inData.getTargetPoint().equals(checkTask.getFromLocation())){ + }else if(targetPoint.equals(checkTask.getFromLocation())){ statusDesc="取货完成"; }else { statusDesc="等待询问"; } WmsTransportTaskDetail detail = new WmsTransportTaskDetail(); - detail.setSite("55"); - detail.setTaskNo(inData.getTaskId()); + detail.setSite(site); + detail.setTaskNo(taskNo); detail.setItemNo(1); - detail.setSeqNo(wcsIntegrationMapper.getMaxSeqNoForTaskDetail("55",inData.getTaskId())); detail.setActionType(statusDesc); - detail.setToLocation(inData.getTargetPoint()); + detail.setToLocation(targetPoint); detail.setStatus("已录入"); detail.setAgvName(inData.getDeviceId()); - wcsIntegrationMapper.insertWmsTransportTaskDetail(detail); + + // 同site+taskNo+动作在在线表已有任何状态时返回0;SQL内分配序号,不获取写入锁。- rqrq + int insertedRows = wcsIntegrationMapper.insertAgvFeedbackTaskDetailIfAbsent(detail); + if (insertedRows == 0) { + String duplicateMessage = "在线明细已存在,跳过重复AGV回调,site=" + site + + ",taskNo=" + taskNo + ",actionType=" + statusDesc; + log.info("{} - rqrq", duplicateMessage); + if (logId != null) { + // 重复回调仍按原协议记成功日志并返回SUCCESS,不覆盖首次明细及其处理状态。- rqrq + interfaceCallLogService.updateCallResult(logId, duplicateMessage, "SUCCESS", null, null); + } + return "SUCCESS"; + } + if (insertedRows != 1) { + throw new RuntimeException("AGV回调明细写入行数异常:" + insertedRows); + } // 8. 更新接口日志为成功 if (logId != null) { @@ -141,9 +167,10 @@ import java.util.Map; } /** - * 根据taskId(实际是taskNo)查询运输任务 + * 根据旧协议全局唯一taskId(实际是taskNo)查询运输任务,结果site用于后续显式隔离。- rqrq */ private WmsTransportTask getTransportTaskById(String taskId) { + // 复用原在线主任务查询;多条匹配由Mapper拒绝,不任取某个工厂继续处理。- rqrq return wcsIntegrationMapper.getTransportTaskByTaskNo(taskId); } 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 5839e65d..021f34e1 100644 --- a/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java +++ b/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java @@ -467,6 +467,14 @@ public interface WcsIntegrationMapper { void batchUpdateCompletedTaskStatus(@Param("site") String site, @Param("taskKeys") List taskKeys); void insertWmsTransportTaskDetail(WmsTransportTaskDetail inData); + + /** + * 老AGV回调仅按site+taskNo+actionType判断在线明细是否存在,任意状态均跳过重复插入。- rqrq + * site取已校验运输主任务;序号在SQL内按同site+taskNo+itemNo递增,不读取历史表或申请写入锁。- rqrq + * 返回1表示新增、0表示已存在;异常交调用方返回失败,供AGV按原协议重试。- rqrq + */ + int insertAgvFeedbackTaskDetailIfAbsent(WmsTransportTaskDetail inData); + void insertWmsOrderTaskDetail(WmsOrderTaskDetail inData); Integer getMaxSeqNoForTaskDetail(@Param("site") String site, @Param("taskNo") String taskNo); diff --git a/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml b/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml index 890c00bb..a08f2848 100644 --- a/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml +++ b/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml @@ -944,6 +944,31 @@ ) + + + + INSERT INTO wms_transport_task_detail ( + site, task_no, item_no, seq_no, action_type, [comment], + from_location, to_location, agv_code, [status], start_time, + error_code, error_msg, agv_name + ) + SELECT + #{site}, #{taskNo}, #{itemNo}, + (SELECT ISNULL(MAX(d.seq_no), 0) + 1 + FROM wms_transport_task_detail d + WHERE d.site = #{site} AND d.task_no = #{taskNo} AND d.item_no = #{itemNo}), + #{actionType}, #{comment}, #{fromLocation}, #{toLocation}, #{agvCode}, + #{status}, #{startTime}, #{errorCode}, #{errorMsg}, #{agvName} + WHERE NOT EXISTS ( + SELECT 1 + FROM wms_transport_task_detail existing_detail + WHERE existing_detail.site = #{site} + AND existing_detail.task_no = #{taskNo} + AND existing_detail.action_type = #{actionType} + ) + + insert into wms_order_task_detail( site,task_no,item_no,seq_no,action_type,[comment],from_location,to_location,agv_code,[status],start_time,