自动化立体仓库 - WMS系统
zwl
2 天以前 cac27c083bacfcb1fe602d722729676f87ee7023
src/main/java/com/zy/api/service/impl/WcsApiServiceImpl.java
@@ -17,6 +17,7 @@
import com.zy.api.service.WcsApiService;
import com.zy.asrs.entity.*;
import com.zy.asrs.service.*;
import com.zy.asrs.task.support.OutboundBatchSeqReleaseGuard;
import com.zy.asrs.utils.Utils;
import com.zy.common.constant.MesConstant;
import com.zy.common.model.LocTypeDto;
@@ -35,6 +36,7 @@
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -48,6 +50,8 @@
    private static final long OUT_LOCK_REPORT_PENDING_WRK_STS = 13L;
    private static final long OUT_LOCK_REPORT_SUCCESS_WRK_STS = 21L;
    private static final long OUT_LOCK_REPORT_FAIL_WRK_STS = 22L;
    private static final long OUTBOUND_CRN_COMPLETE_WRK_STS = 25L;
    private static final long OUTBOUND_STATION_COMPLETE_WRK_STS = 26L;
    private static final String OUT_LOCK_REPORT_PENDING_FLAG = "P";
    /** 同一 WCS 路径、同一单号下一组下发的任务条数上限 */
@@ -107,6 +111,8 @@
    private RowLastnoService rowLastnoService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private OutboundBatchSeqReleaseGuard outboundBatchSeqReleaseGuard;
    /**
@@ -126,6 +132,10 @@
        String validateMsg = validatePubTask(params, wrkMast);
        if (!Cools.isEmpty(validateMsg)) {
            return R.error(validateMsg);
        }
        String batchBlockMsg = validateOutboundBatchSeqReady(params, wrkMast);
        if (!Cools.isEmpty(batchBlockMsg)) {
            return R.error(batchBlockMsg);
        }
        String url = resolveTaskPath(params);
        String requestJson = JSON.toJSONString(params);
@@ -203,6 +213,7 @@
        List<String> failMsgs = new ArrayList<>();
        List<WorkTaskParams> lastSentChunk = null;
        String skipGroupKey = null;
        Set<String> blockedOutboundUserKeys = new HashSet<>();
        for (List<WorkTaskParams> chunk : chunks) {
            if (chunk == null || chunk.isEmpty()) {
@@ -211,8 +222,22 @@
            WorkTaskParams head = chunk.get(0);
            WrkMast headMast = wrkMastMap.get(head.getTaskNo());
            String key = buildBatchGroupKey(head, headMast);
            String outboundUserKey = buildOutboundUserKey(head, headMast);
            if (skipGroupKey != null && skipGroupKey.equals(key)) {
                continue;
            }
            if (outboundUserKey != null && blockedOutboundUserKeys.contains(outboundUserKey)) {
                continue;
            }
            String batchBlockMsg = validateOutboundBatchSeqReady(chunk, wrkMastMap);
            if (!Cools.isEmpty(batchBlockMsg)) {
                skipMsgs.add(batchBlockMsg);
                skipGroupKey = key;
                if (outboundUserKey != null) {
                    blockedOutboundUserKeys.add(outboundUserKey);
                }
                continue;
            }
@@ -464,6 +489,26 @@
        return outboundPltSlotReleasedInWms(userNo, batchGroup, minPlt - 1);
    }
    private String validateOutboundBatchSeqReady(List<WorkTaskParams> chunk, Map<String, WrkMast> wrkMastMap) {
        if (chunk == null || chunk.isEmpty()) {
            return null;
        }
        WorkTaskParams head = chunk.get(0);
        return validateOutboundBatchSeqReady(head, wrkMastMap.get(head.getTaskNo()));
    }
    private String validateOutboundBatchSeqReady(WorkTaskParams params, WrkMast wrkMast) {
        if (params == null || !"out".equalsIgnoreCase(params.getType())) {
            return null;
        }
        if (wrkMast == null || !Objects.equals(wrkMast.getIoType(), 101)) {
            return null;
        }
        return outboundBatchSeqReleaseGuard.validateReady(
                sortUserNoForPub(params, wrkMast),
                sortBatchGroupForPub(params, wrkMast));
    }
    private boolean outboundPltSlotReleasedInWms(String userNo, String batchSeq, int pltType) {
        EntityWrapper<WrkMast> mastWrapper = new EntityWrapper<>();
        mastWrapper.eq("user_no", userNo);
@@ -521,7 +566,7 @@
        return Comparator
                .comparing((WorkTaskParams p) -> Optional.ofNullable(p.getType()).orElse(""), String.CASE_INSENSITIVE_ORDER)
                .thenComparing(p -> sortUserNoForPub(p, wrkMastMap.get(p.getTaskNo())), Comparator.nullsLast(String::compareTo))
                .thenComparing(p -> sortBatchGroupForPub(p, wrkMastMap.get(p.getTaskNo())), Comparator.nullsLast(String::compareTo))
                .thenComparing(p -> sortBatchGroupForPub(p, wrkMastMap.get(p.getTaskNo())), WcsApiServiceImpl::compareBatchSeqNatural)
                .thenComparing(p -> sortPltForPub(p, wrkMastMap.get(p.getTaskNo())), Comparator.nullsLast(Integer::compareTo));
    }
@@ -545,6 +590,64 @@
            return wrkMast.getBatchSeq();
        }
        return null;
    }
    private static String buildOutboundUserKey(WorkTaskParams params, WrkMast wrkMast) {
        if (params == null || !"out".equalsIgnoreCase(params.getType())) {
            return null;
        }
        String userNo = sortUserNoForPub(params, wrkMast);
        if (Cools.isEmpty(userNo)) {
            return null;
        }
        return resolveSafeKey(userNo);
    }
    private static int compareBatchSeqNatural(String left, String right) {
        String safeLeft = normalizeBatchSeq(left);
        String safeRight = normalizeBatchSeq(right);
        int leftIndex = 0;
        int rightIndex = 0;
        while (leftIndex < safeLeft.length() && rightIndex < safeRight.length()) {
            char leftChar = safeLeft.charAt(leftIndex);
            char rightChar = safeRight.charAt(rightIndex);
            if (Character.isDigit(leftChar) && Character.isDigit(rightChar)) {
                int leftStart = leftIndex;
                int rightStart = rightIndex;
                while (leftIndex < safeLeft.length() && Character.isDigit(safeLeft.charAt(leftIndex))) {
                    leftIndex++;
                }
                while (rightIndex < safeRight.length() && Character.isDigit(safeRight.charAt(rightIndex))) {
                    rightIndex++;
                }
                String leftNumber = safeLeft.substring(leftStart, leftIndex);
                String rightNumber = safeRight.substring(rightStart, rightIndex);
                int compare = new BigInteger(leftNumber).compareTo(new BigInteger(rightNumber));
                if (compare != 0) {
                    return compare;
                }
                compare = Integer.compare(leftNumber.length(), rightNumber.length());
                if (compare != 0) {
                    return compare;
                }
                continue;
            }
            int compare = Character.compare(leftChar, rightChar);
            if (compare != 0) {
                return compare;
            }
            leftIndex++;
            rightIndex++;
        }
        return Integer.compare(safeLeft.length(), safeRight.length());
    }
    private static String normalizeBatchSeq(String value) {
        return Cools.isEmpty(value) ? "" : value;
    }
    private static String resolveSafeKey(String value) {
        return Cools.isEmpty(value) ? "_EMPTY_" : value;
    }
    private static String buildOutboundBatchCacheKey(String userNo, String batchSeq) {
@@ -590,9 +693,27 @@
                    throw new CoolException("任务状态修改失败!!");
                }
            }
        } else if (params.getNotifyType().equals("task")) {
        } else if (isOutboundCrnTaskComplete(params)) {
            // WCS出库任务完成:堆垛机出库任务执行完成,工作状态 -> 25。
            if (isOutboundTask(mast) && canMarkOutboundCrnComplete(mast)) {
                mast.setWrkSts(OUTBOUND_CRN_COMPLETE_WRK_STS);
                mast.setModiTime(new Date());
                if (!wrkMastService.updateById(mast)) {
                    throw new CoolException("任务状态修改失败!!");
                }
            }
        } else if (isOutboundStationTaskRunComplete(params)) {
            // WCS输送站点出库任务运行完成:托盘已到目的地,工作状态 -> 26。
            if (isOutboundTask(mast) && canMarkOutboundStationComplete(mast)) {
                mast.setWrkSts(OUTBOUND_STATION_COMPLETE_WRK_STS);
                mast.setModiTime(new Date());
                if (!wrkMastService.updateById(mast)) {
                    throw new CoolException("任务状态修改失败!!");
                }
            }
        } else if ("task".equalsIgnoreCase(params.getNotifyType())) {
            //任务
            if (params.getMsgType().equals("task_complete")) {
            if ("task_complete".equalsIgnoreCase(params.getMsgType())) {
                if (mast.getIoType() == 1 || mast.getIoType() == 2 ||mast.getIoType() == 10) {
                    mast.setWrkSts(4L);
@@ -606,25 +727,9 @@
                    throw new CoolException("任务状态修改失败!!");
                }
                //wcs任务取消接口
            } else if (params.getMsgType().equals("task_cancel")) {
            } else if ("task_cancel".equalsIgnoreCase(params.getMsgType())) {
                workService.cancelWrkMast(String.valueOf(mast.getWrkNo()), 9955L);
            } else if (params.getMsgType().equals("task_arrive")) {
                //到达目的地
                //如果出库任务是跨区则需要生成新的入库任务入库
                if(!Cools.isEmpty(mast.getLocNo())){
                    mast.setOnlineYn("N");//等待生成跨区入库任务
                }
                mast.setWrkSts(14L);
                if(Cools.isEmpty(mast.getStaNo())){
                    mast.setOveMk("Y");
                }
                mast.setModiTime(new Date());
                if (!wrkMastService.updateById(mast)) {
                    throw new CoolException("任务状态修改失败!!");
                }
            }
        } else if (params.getNotifyType().equals("weight")) {
        }
        return R.ok();
    }
@@ -635,8 +740,29 @@
                && "crn_out_task_run".equalsIgnoreCase(params.getMsgType());
    }
    private boolean isOutboundCrnTaskComplete(ReceviceTaskParams params) {
        return params != null
                && "Crn".equalsIgnoreCase(params.getNotifyType())
                && "crn_out_task_complete".equalsIgnoreCase(params.getMsgType());
    }
    private boolean isOutboundStationTaskRunComplete(ReceviceTaskParams params) {
        return params != null
                && "Devp".equalsIgnoreCase(params.getNotifyType())
                && "station_out_task_run_complete".equalsIgnoreCase(params.getMsgType());
    }
    private boolean isOutboundTask(WrkMast mast) {
        return mast != null && mast.getIoType() != null && (mast.getIoType() == 101 || mast.getIoType() == 110);
    }
    private boolean canMarkOutboundCrnComplete(WrkMast mast) {
        if (mast == null || mast.getWrkSts() == null) {
            return false;
        }
        return mast.getWrkSts() < 14
                || mast.getWrkSts().equals(OUT_LOCK_REPORT_SUCCESS_WRK_STS)
                || mast.getWrkSts().equals(OUT_LOCK_REPORT_FAIL_WRK_STS);
    }
    private boolean canMarkOutboundTaskComplete(WrkMast mast) {
@@ -645,7 +771,19 @@
        }
        return mast.getWrkSts() < 14
                || mast.getWrkSts().equals(OUT_LOCK_REPORT_SUCCESS_WRK_STS)
                || mast.getWrkSts().equals(OUT_LOCK_REPORT_FAIL_WRK_STS);
                || mast.getWrkSts().equals(OUT_LOCK_REPORT_FAIL_WRK_STS)
                || mast.getWrkSts().equals(OUTBOUND_CRN_COMPLETE_WRK_STS)
                || mast.getWrkSts().equals(OUTBOUND_STATION_COMPLETE_WRK_STS);
    }
    private boolean canMarkOutboundStationComplete(WrkMast mast) {
        if (mast == null || mast.getWrkSts() == null) {
            return false;
        }
        return mast.getWrkSts() < 14
                || mast.getWrkSts().equals(OUT_LOCK_REPORT_SUCCESS_WRK_STS)
                || mast.getWrkSts().equals(OUT_LOCK_REPORT_FAIL_WRK_STS)
                || mast.getWrkSts().equals(OUTBOUND_CRN_COMPLETE_WRK_STS);
    }
    @Override
@@ -778,6 +916,9 @@
            if ("Y".equalsIgnoreCase(wrkMast.getPauseMk())) {
                return "task paused";
            }
            if (Objects.equals(wrkMast.getIoType(), 101) && Cools.isEmpty(wrkMast.getBatchSeq())) {
                return "出库进仓编号(batchSeq)为空,跳过下发";
            }
            if (requiresOutboundErpConfirm(wrkMast) && !"Y".equalsIgnoreCase(wrkMast.getPdcType())) {
                return "task not confirmed by erp";
            }