package com.zy.core.service; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.core.common.Cools; import com.core.exception.CoolException; import com.zy.asrs.domain.param.ManualRollbackTaskParam; import com.zy.asrs.entity.WrkMast; import com.zy.asrs.service.WrkMastLogService; import com.zy.asrs.service.WrkMastService; import com.zy.common.utils.RedisUtil; import com.zy.core.News; import com.zy.core.enums.CrnTaskModeType; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.WrkStsType; import com.zy.core.model.CommandResponse; import com.zy.core.model.command.CrnCommand; 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.HashMap; @Slf4j @Service public class WrkCommandRollbackService { private static final int DEFAULT_AUTO_ROLLBACK_LIMIT = 3; @Autowired private WrkMastService wrkMastService; @Autowired private WrkMastLogService wrkMastLogService; @Autowired private RedisUtil redisUtil; @Transactional(rollbackFor = Exception.class) public void handleSingleCrnSendResult(CrnCommand command, CommandResponse response, String deviceName) { if (command == null || command.getTaskNo() == null || command.getTaskNo() <= 0) { return; } if (CrnTaskModeType.RESET.id.equals(command.getTaskMode())) { return; } WrkMast wrkMast = wrkMastService.selectByWorkNo(command.getTaskNo()); if (wrkMast == null) { return; } if (!isSingleCrnRunStatus(wrkMast.getWrkSts())) { return; } if (response != null && Boolean.TRUE.equals(response.getResult())) { clearSendFailState(wrkMast); return; } String failMessage = buildFailMessage(deviceName, response); int nextFailCount = (wrkMast.getSendFailCount() == null ? 0 : wrkMast.getSendFailCount()) + 1; int rollbackLimit = getAutoRollbackLimit(); boolean manualRequired = nextFailCount >= rollbackLimit; Long updateStatus = manualRequired ? getManualStatus(wrkMast.getWrkSts()) : getRollbackStatus(wrkMast.getWrkSts()); if (updateStatus == null) { return; } saveWrkLog(wrkMast.getWrkNo()); wrkMast.setWrkSts(updateStatus); wrkMast.setSendFailCount(nextFailCount); wrkMast.setErrorTime(new Date()); wrkMast.setErrorMemo(failMessage); wrkMast.setSystemMsg(failMessage); wrkMast.setModiTime(new Date()); wrkMastService.updateById(wrkMast); if (manualRequired) { News.taskError(wrkMast.getWrkNo(), "{}下发命令失败,已达到自动回滚上限({}),请在工作档手动回滚。原因: {}", deviceName, rollbackLimit, failMessage); } else { News.taskWarn(wrkMast.getWrkNo(), "{}下发命令失败,任务已自动回滚({}/{}). 原因: {}", deviceName, nextFailCount, rollbackLimit, failMessage); } } @Transactional(rollbackFor = Exception.class) public boolean manualRollbackTask(ManualRollbackTaskParam param) { WrkMast wrkMast = findWrkMast(param == null ? null : param.getWrkNo(), param == null ? null : param.getTaskNo()); if (wrkMast == null) { throw new CoolException("任务不存在"); } Long rollbackStatus = getRollbackStatusFromManual(wrkMast.getWrkSts()); if (rollbackStatus == null) { throw new CoolException("当前任务不处于待人工回滚状态"); } saveWrkLog(wrkMast.getWrkNo()); wrkMast.setWrkSts(rollbackStatus); wrkMast.setSendFailCount(0); wrkMast.setSystemMsg("人工回滚完成,等待重新下发"); wrkMast.setModiTime(new Date()); wrkMastService.updateById(wrkMast); News.taskInfo(wrkMast.getWrkNo(), "人工回滚完成,任务状态已恢复为待执行"); return true; } private void clearSendFailState(WrkMast wrkMast) { boolean needUpdate = (wrkMast.getSendFailCount() != null && wrkMast.getSendFailCount() > 0) || wrkMast.getErrorTime() != null || !Cools.isEmpty(wrkMast.getErrorMemo()); if (!needUpdate) { return; } saveWrkLog(wrkMast.getWrkNo()); wrkMast.setSendFailCount(0); wrkMast.setErrorTime(null); wrkMast.setErrorMemo(null); wrkMast.setSystemMsg(""); wrkMast.setModiTime(new Date()); wrkMastService.updateById(wrkMast); } private WrkMast findWrkMast(Integer wrkNo, String taskNo) { if (wrkNo != null) { return wrkMastService.selectByWorkNo(wrkNo); } if (!Cools.isEmpty(taskNo)) { return wrkMastService.getOne(new QueryWrapper().eq("wms_wrk_no", taskNo)); } return null; } private void saveWrkLog(Integer wrkNo) { try { wrkMastLogService.save(wrkNo); } catch (Exception e) { log.warn("保存工作档日志失败, wrkNo={}", wrkNo, e); } } private int getAutoRollbackLimit() { Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key); if (!(systemConfigMapObj instanceof HashMap)) { return DEFAULT_AUTO_ROLLBACK_LIMIT; } try { HashMap systemConfigMap = (HashMap) systemConfigMapObj; return Math.max(1, Integer.parseInt(systemConfigMap.getOrDefault("deviceCommandAutoRollbackLimit", String.valueOf(DEFAULT_AUTO_ROLLBACK_LIMIT)))); } catch (Exception ignore) { return DEFAULT_AUTO_ROLLBACK_LIMIT; } } private String buildFailMessage(String deviceName, CommandResponse response) { if (response != null && !Cools.isEmpty(response.getMessage())) { return response.getMessage(); } return deviceName + "命令下发失败"; } private boolean isSingleCrnRunStatus(Long wrkSts) { return Long.valueOf(WrkStsType.INBOUND_RUN.sts).equals(wrkSts) || Long.valueOf(WrkStsType.OUTBOUND_RUN.sts).equals(wrkSts) || Long.valueOf(WrkStsType.LOC_MOVE_RUN.sts).equals(wrkSts); } private Long getRollbackStatus(Long wrkSts) { if (Long.valueOf(WrkStsType.INBOUND_RUN.sts).equals(wrkSts)) { return WrkStsType.INBOUND_DEVICE_RUN.sts; } if (Long.valueOf(WrkStsType.OUTBOUND_RUN.sts).equals(wrkSts)) { return WrkStsType.NEW_OUTBOUND.sts; } if (Long.valueOf(WrkStsType.LOC_MOVE_RUN.sts).equals(wrkSts)) { return WrkStsType.NEW_LOC_MOVE.sts; } return null; } private Long getManualStatus(Long wrkSts) { if (Long.valueOf(WrkStsType.INBOUND_RUN.sts).equals(wrkSts)) { return WrkStsType.INBOUND_MANUAL.sts; } if (Long.valueOf(WrkStsType.OUTBOUND_RUN.sts).equals(wrkSts)) { return WrkStsType.OUTBOUND_MANUAL.sts; } if (Long.valueOf(WrkStsType.LOC_MOVE_RUN.sts).equals(wrkSts)) { return WrkStsType.LOC_MOVE_MANUAL.sts; } return null; } private Long getRollbackStatusFromManual(Long wrkSts) { if (Long.valueOf(WrkStsType.INBOUND_MANUAL.sts).equals(wrkSts)) { return WrkStsType.INBOUND_DEVICE_RUN.sts; } if (Long.valueOf(WrkStsType.OUTBOUND_MANUAL.sts).equals(wrkSts)) { return WrkStsType.NEW_OUTBOUND.sts; } if (Long.valueOf(WrkStsType.LOC_MOVE_MANUAL.sts).equals(wrkSts)) { return WrkStsType.NEW_LOC_MOVE.sts; } return null; } }