package com.zy.asrs.service.impl; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import com.core.common.Cools; import com.core.common.DateUtils; import com.core.exception.CoolException; import com.zy.asrs.entity.*; import com.zy.asrs.mapper.TaskMapper; import com.zy.asrs.service.*; import com.zy.asrs.task.handler.AgvHandler; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.concurrent.TimeUnit; @Slf4j @Service("taskService") public class TaskServiceImpl extends ServiceImpl implements TaskService { @Autowired private TaskLogService taskLogService; @Autowired private LocCacheService locCacheService; @Autowired private WaitPakinService waitPakinService; @Autowired private TaskDetlService taskDetlService; @Autowired private TaskService taskService; @Autowired private TaskDetlLogService taskDetlLogService; @Autowired private OrderPakoutService orderPakoutService; @Autowired private OrderDetlPakoutService orderDetlPakoutService; @Autowired private AgvHandler agvHandler; @Override @Transactional(rollbackFor = Exception.class) public void completeWrkMast(String workNo, Long userId) { Task wrkMast = this.selectOne(new EntityWrapper() .eq("wrk_no", workNo) .andNew("(is_deleted = 0)")); if (Cools.isEmpty(wrkMast)) { throw new CoolException(workNo + "工作档不存在"); } if (wrkMast.getWrkSts() == 4 || wrkMast.getWrkSts() == 14) { throw new CoolException("当前工作档已完成"); } // 入库 + 库位转移 if (wrkMast.getIoType() < 50){ wrkMast.setWrkSts(4L); // 出库 } else { wrkMast.setWrkSts(14L); } Date now = new Date(); wrkMast.setCrnStrTime(DateUtils.calculate(now, 1L, TimeUnit.SECONDS, true)); wrkMast.setCrnEndTime(now); wrkMast.setModiTime(now); wrkMast.setModiUser(userId); // 完成操作人员记录 wrkMast.setManuType("手动完成"); if (!this.updateById(wrkMast)) { throw new CoolException("修改工作档失败"); } } @Override @Transactional public void pickWrkMast(String workNo, Long userId) { Task wrkMast = this.selectOne(new EntityWrapper() .eq("wrk_no", workNo) .andNew("(is_deleted = 0)")); if (Cools.isEmpty(wrkMast)) { throw new CoolException(workNo + "工作档不存在"); } // 入出库类型判断 if (wrkMast.getIoType() != 103 && wrkMast.getIoType() != 104 && wrkMast.getIoType() != 107) { throw new CoolException("当前入出库类型无法进行操作"); } // 工作状态判断 if (wrkMast.getWrkSts() < 11 || wrkMast.getWrkSts() == 15) { throw new CoolException("当前工作状态无法进行操作"); } // 保存工作明细档历史档 // if (!wrkDetlLogService.save(wrkMast.getWrkNo())) { // throw new CoolException("保存工作明细档历史档失败"); // } // 保存工作主档历史档 if (!taskLogService.save(wrkMast.getWrkNo())) { throw new CoolException("保存工作主档历史档失败"); } // 获取目标站 // Wrapper wrapper = new EntityWrapper() // .eq("type_no", wrkMast.getIoType() - 50) // .eq("stn_no", wrkMast.getStaNo()) // 作业站点 = 拣料出库的目标站 // .eq("crn_no", wrkMast.getCrnNo()); // 堆垛机号 // StaDesc staDesc = staDescService.selectOne(wrapper); // if (Cools.isEmpty(staDesc)) { // throw new CoolException("入库路径不存在"); // } Date now = new Date(); // 堆垛机站点(目标站) // Integer staNo = staDesc.getCrnStn(); // 更新工作档数据状态 wrkMast.setIoType(wrkMast.getIoType() - 50); // 入出库类型: 103->53,104->54,107->57 wrkMast.setWrkSts(2L); // 工作状态: 2.设备上走 wrkMast.setSourceStaNo(wrkMast.getStaNo()); // 源站 // wrkMast.setStaNo(staNo + ""); // 目标站 wrkMast.setLocNo(wrkMast.getSourceLocNo()); // 目标库位 = 出库时的源库位 wrkMast.setSourceLocNo(""); // 源库位清空 wrkMast.setModiTime(now); wrkMast.setModiUser(userId); if (!this.updateById(wrkMast)) { throw new CoolException("更新工作档数据状态失败"); } // 修改库位状态 Q.拣料/盘点/并板再入库 LocCache locMast = locCacheService.selectOne(new EntityWrapper().eq("loc_no", wrkMast.getLocNo())); locMast.setLocSts("Q"); locMast.setModiTime(now); locMast.setModiUser(userId); if (!locCacheService.updateById(locMast)) { throw new CoolException("修改库位状态失败"); } } @Override public List selectToBeCompleteData() { return this.baseMapper.selectToBeCompleteData(); } @Override @Transactional public void cancelWrkMast(String workNo, Long userId) { Date now = new Date(); Task wrkMast = this.selectOne(new EntityWrapper() .eq("wrk_no", workNo) .andNew("(is_deleted = 0)")); if (Cools.isEmpty(wrkMast)) { throw new CoolException(workNo + "工作档不存在"); } // 如果是AGV任务,根据任务状态决定是否需要调用AGV接口取消任务 // 仅状态7(新建AGV任务)不访问AGV直接取消;其他状态必须先调用AGV取消接口,AGV返回成功才能取消 if ("agv".equals(wrkMast.getTaskType())) { Long wrkSts = wrkMast.getWrkSts(); if (wrkSts != null && wrkSts == 7L) { // 状态7:新建AGV任务,未发送给AGV,无需调用AGV接口,直接取消 String displayTaskId = (wrkMast.getWrkNo() != null) ? String.valueOf(wrkMast.getWrkNo()) : String.valueOf(wrkMast.getId()); log.info("取消AGV任务:任务ID:{},状态:7(新建AGV任务),无需调用AGV接口,直接取消", displayTaskId); } else { // 非状态7(含8、9、10等):必须先调用AGV取消接口,AGV返回成功才能取消 if (wrkMast.getId() == null) { throw new CoolException("取消AGV任务失败:任务ID为空"); } String agvWrkNo = wrkMast.getAgvWrkNo(); Integer wrkNo = wrkMast.getWrkNo(); Long taskId = wrkMast.getId(); if ((agvWrkNo == null || agvWrkNo.isEmpty()) && wrkNo == null && taskId == null) { throw new CoolException("取消AGV任务失败:无法获取有效的任务标识(agvWrkNo、wrkNo和id都为空)"); } String errorMsg = agvHandler.cancelAgvTask(wrkMast); if (errorMsg != null) { log.warn("取消AGV任务失败,AGV未返回成功 - 任务ID:{},错误:{}", (wrkMast.getWrkNo() != null) ? String.valueOf(wrkMast.getWrkNo()) : String.valueOf(wrkMast.getId()), errorMsg); throw new CoolException("取消AGV任务失败:" + errorMsg); } } } String locNo = ""; // 待修改目标库位 String locSts = ""; // 待修改目标库位状态 // 入库取消(修改目标库位) if (wrkMast.getIoType() < 100) { locNo = wrkMast.getLocNo(); locSts = "O"; // 库位转移 if (wrkMast.getIoType() == 11) { // 库位转移:源库位 LocCache locMast = locCacheService.selectOne(new EntityWrapper().eq("loc_no", wrkMast.getSourceLocNo())); if (Cools.isEmpty(locMast)) { throw new CoolException("取消库位转移失败,源库位不存在:" + wrkMast.getSourceLocNo()); } locMast.setLocSts(wrkMast.getFullPlt().equalsIgnoreCase("N") ? "D" : "F"); locMast.setModiTime(now); locMast.setModiUser(userId); locCacheService.updateById(locMast); } // 出库取消(修改源库位) } else { locNo = wrkMast.getSourceLocNo(); // 出库 ===>> F.在库 if (wrkMast.getIoType() > 100 && wrkMast.getIoType() != 110) { locSts = "F"; // 空板出库 ===>> D.空桶/空栈板 } else if (wrkMast.getIoType() == 110) { locSts = "D"; // 库位转移 ===>> D.空桶/空栈板 } else if (wrkMast.getIoType() == 11) { locSts = wrkMast.getFullPlt().equalsIgnoreCase("N") ? "D" : "F"; // 库位转移:目标库位 LocCache locMast = locCacheService.selectOne(new EntityWrapper().eq("loc_no", wrkMast.getLocNo())); if (Cools.isEmpty(locMast)) { throw new CoolException("取消库位转移失败,目标库位不存在:" + wrkMast.getSourceLocNo()); } locMast.setLocSts("O"); locMast.setModiTime(now); locMast.setModiUser(userId); locCacheService.updateById(locMast); } } //取消入库工作档时,查询组托表,如果有将状态改为待处理 if (wrkMast.getIoType() == 1) { List waitPakins = waitPakinService.selectList(new EntityWrapper().eq("zpallet", wrkMast.getBarcode())); for (WaitPakin waitPakin : waitPakins) { if (!Cools.isEmpty(waitPakin)) { waitPakin.setIoStatus("N"); waitPakin.setLocNo(""); waitPakinService.update(waitPakin, new EntityWrapper() // .eq("order_no", waitPakin.getOrderNo()) .eq("zpallet", waitPakin.getZpallet()) .eq("matnr", waitPakin.getMatnr()) .eq("batch", waitPakin.getBatch())); } } } // 取消操作人员记录 wrkMast.setManuType("手动取消"); wrkMast.setModiUser(userId); wrkMast.setModiTime(now); if (!taskService.updateById(wrkMast)) { throw new CoolException("取消工作档失败"); } // 保存工作主档历史档 if (!taskLogService.save(wrkMast.getWrkNo())) { throw new CoolException("保存工作历史档失败, workNo = " + wrkMast.getWrkNo()); } // 逻辑删除工作主档 wrkMast.setIsDeleted(1); boolean wrkMastRes = taskService.updateById(wrkMast); if (wrkMast.getIoType() != 10 && wrkMast.getIoType() != 110) { // 删除工作档明细 boolean wrkDetlRes = taskDetlService.delete(new EntityWrapper().eq("wrk_no", workNo)); } // 修改库位状态(如果库位不为空) boolean locMastRes = true; if (!Cools.isEmpty(locNo)&&wrkMast.getIoType() > 100) { LocCache locMast = locCacheService.selectOne(new EntityWrapper().eq("loc_no", locNo)); if (Cools.isEmpty(locMast)) { throw new CoolException("取消工作档失败,库位不存在:" + locNo); } if (!Cools.isEmpty(locSts)) { locMast.setLocSts(locSts); locMast.setModiTime(now); locMast.setModiUser(userId); locMastRes = locCacheService.updateById(locMast); } } if (!wrkMastRes || !locMastRes) { throw new CoolException("保存数据失败"); } } @Override @Transactional(rollbackFor = Exception.class) public void deleteWrkMast(String workNo, Long userId) { Date now = new Date(); Task wrkMast = this.selectOne(new EntityWrapper() .eq("wrk_no", workNo) .andNew("(is_deleted = 0)")); if (Cools.isEmpty(wrkMast)) { throw new CoolException(workNo + "工作档不存在"); } String displayTaskId = (wrkMast.getWrkNo() != null) ? String.valueOf(wrkMast.getWrkNo()) : String.valueOf(wrkMast.getId()); // 如果是AGV任务,尝试同步申请AGV取消(但不会被AGV返回的错误校验拦截,会继续删除) if ("agv".equals(wrkMast.getTaskType())) { Long wrkSts = wrkMast.getWrkSts(); // 状态8和9:已发送给AGV任务,尝试调用AGV接口取消任务 // 状态10:AGV呼叫异常,可以取消,但不会请求AGV取消接口 // 状态7或更早:还未发送给AGV,无需调用AGV接口 if (wrkSts != null && wrkSts >= 8L && wrkSts != 10L) { try { // 验证任务信息是否完整 if (wrkMast.getId() != null) { // 验证taskId是否可用(agvWrkNo、wrkNo或id至少有一个) String agvWrkNo = wrkMast.getAgvWrkNo(); Integer wrkNo = wrkMast.getWrkNo(); Long taskId = wrkMast.getId(); if ((agvWrkNo != null && !agvWrkNo.isEmpty()) || wrkNo != null || taskId != null) { // 同步申请AGV取消,但不抛出异常(不会被错误校验拦截) String errorMsg = agvHandler.cancelAgvTask(wrkMast); if (errorMsg != null) { log.warn("删除AGV任务:尝试取消AGV任务失败,但继续执行删除操作,任务ID:{},错误:{}", displayTaskId, errorMsg); } else { log.info("删除AGV任务:成功取消AGV任务,任务ID:{}", displayTaskId); } } else { log.warn("删除AGV任务:无法获取有效的任务标识(agvWrkNo、wrkNo和id都为空),跳过AGV取消,继续执行删除操作,任务ID:{}", displayTaskId); } } else { log.warn("删除AGV任务:任务ID为空,跳过AGV取消,继续执行删除操作,任务ID:{}", displayTaskId); } } catch (Exception e) { // 捕获所有异常,记录日志但不阻止删除操作(不会被AGV返回的错误校验拦截) log.error("删除AGV任务:尝试取消AGV任务时发生异常,但继续执行删除操作,任务ID:{}", displayTaskId, e); } } else { // 状态10(AGV呼叫异常)或状态7或更早,无需调用AGV接口 if (wrkSts != null && wrkSts == 10L) { log.info("删除AGV任务:任务ID:{},状态:{}(AGV呼叫异常),无需调用AGV接口,直接删除", displayTaskId, wrkSts); } else { log.info("删除AGV任务:任务ID:{},状态:{}(待呼叫AGV或更早),无需调用AGV接口,直接删除", displayTaskId, wrkSts); } } } // 释放库位等资源(类似cancelWrkMast的逻辑) String locNo = ""; // 待修改目标库位 String locSts = ""; // 待修改目标库位状态 // 入库取消(修改目标库位) if (wrkMast.getIoType() < 100) { locNo = wrkMast.getLocNo(); locSts = "O"; // 库位转移 if (wrkMast.getIoType() == 11) { // 库位转移:源库位 LocCache locMast = locCacheService.selectOne(new EntityWrapper().eq("loc_no", wrkMast.getSourceLocNo())); if (!Cools.isEmpty(locMast)) { locMast.setLocSts(wrkMast.getFullPlt().equalsIgnoreCase("N") ? "D" : "F"); locMast.setModiTime(now); locMast.setModiUser(userId); locCacheService.updateById(locMast); } } // 出库取消(修改源库位) } else { locNo = wrkMast.getSourceLocNo(); // 出库 ===>> F.在库 if (wrkMast.getIoType() > 100 && wrkMast.getIoType() != 110) { locSts = "F"; // 空板出库 ===>> D.空桶/空栈板 } else if (wrkMast.getIoType() == 110) { locSts = "D"; // 库位转移 ===>> D.空桶/空栈板 } else if (wrkMast.getIoType() == 11) { locSts = wrkMast.getFullPlt().equalsIgnoreCase("N") ? "D" : "F"; // 库位转移:目标库位 LocCache locMast = locCacheService.selectOne(new EntityWrapper().eq("loc_no", wrkMast.getLocNo())); if (!Cools.isEmpty(locMast)) { locMast.setLocSts("O"); locMast.setModiTime(now); locMast.setModiUser(userId); locCacheService.updateById(locMast); } } } //取消入库工作档时,查询组托表,如果有将状态改为待处理 if (wrkMast.getIoType() == 1) { List waitPakins = waitPakinService.selectList(new EntityWrapper().eq("zpallet", wrkMast.getBarcode())); for (WaitPakin waitPakin : waitPakins) { if (!Cools.isEmpty(waitPakin)) { waitPakin.setIoStatus("N"); waitPakin.setLocNo(""); waitPakinService.update(waitPakin, new EntityWrapper() .eq("zpallet", waitPakin.getZpallet()) .eq("matnr", waitPakin.getMatnr()) .eq("batch", waitPakin.getBatch())); } } } // 删除操作人员记录 wrkMast.setManuType("手动删除"); wrkMast.setModiUser(userId); wrkMast.setModiTime(now); // 逻辑删除工作主档 wrkMast.setIsDeleted(1); if (!taskService.updateById(wrkMast)) { throw new CoolException("删除工作档失败"); } if (wrkMast.getIoType() != 10 && wrkMast.getIoType() != 110) { // 删除工作档明细 taskDetlService.delete(new EntityWrapper().eq("wrk_no", workNo)); } // 修改库位状态(如果库位不为空) if (!Cools.isEmpty(locNo) && wrkMast.getIoType() > 100) { LocCache locMast = locCacheService.selectOne(new EntityWrapper().eq("loc_no", locNo)); if (!Cools.isEmpty(locMast) && !Cools.isEmpty(locSts)) { locMast.setLocSts(locSts); locMast.setModiTime(now); locMast.setModiUser(userId); locCacheService.updateById(locMast); } } // 如果是入库任务,释放预约库位 if (wrkMast.getIoType() != null && wrkMast.getIoType() < 100 && !Cools.isEmpty(wrkMast.getLocNo())) { try { LocCache locCache = locCacheService.selectOne( new EntityWrapper().eq("loc_no", wrkMast.getLocNo()) ); if (locCache != null && "S".equals(locCache.getLocSts())) { // 库位状态为S(入库预约),释放为O(闲置) locCache.setLocSts("O"); locCache.setModiTime(now); locCache.setModiUser(userId); locCacheService.updateById(locCache); log.info("删除AGV任务:已释放预约库位:{}(S→O),任务ID:{}", wrkMast.getLocNo(), displayTaskId); } } catch (Exception e) { log.warn("删除AGV任务:释放预约库位失败,库位:{},任务ID:{}", wrkMast.getLocNo(), displayTaskId, e); } } log.info("删除AGV任务成功:任务ID:{},工作号:{}", displayTaskId, workNo); } @Override public List selectToBeHistoryData() { return this.baseMapper.selectToBeHistoryData(); } }