自动化立体仓库 - WMS系统
skyouc
10 小时以前 6efbf154b3ed88d376763b9d9807256c7bd5eaeb
src/main/java/com/zy/common/service/CommonService.java
@@ -242,12 +242,19 @@
     * @return locNo 检索到的库位号
     */
    public StartupDto getDoubleLocNoRun(Integer whsType, Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, Integer moveCrnNo, LocTypeDto locTypeDto, int times) {
        // 初始化参数
        int crnNo = 6;      //堆垛机号
        int nearRow = 12;    //浅库位排 (与11对应)
        int curRow = 11;     //深库位排
        int rowCount = 2;   //轮询轮次 (12/11 对 和 13/14 对)
        LocMast locMast = null;     // 目标库位
        // 1. 初始化参数
        int crnNo = 6;      // 堆垛机号
        int deepRow, shallowRow;
        int rowCount = 2;   // 轮询两组货架 (11/12 对 和 14/13 对)
        // 根据轮询次数切换排,严格保证深位优先
        if (times % 2 == 0) {
            deepRow = 11;
            shallowRow = 12;
        } else {
            deepRow = 14;
            shallowRow = 13;
        }
        StartupDto startupDto = new StartupDto();
        RowLastno rowLastno = rowLastnoService.selectById(whsType);
@@ -258,261 +265,86 @@
        if (Cools.isEmpty(rowLastnoType)) {
            throw new CoolException("数据异常,请联系管理员===》库位规则类型未知");
        }
        int sRow = rowLastno.getsRow();
        int eRow = rowLastno.geteRow();
        int crnNumber = rowLastno.getCrnQty();
        // 根据轮询次数切换排 (优先深库位排 11, 14)
        if (times % 2 == 0) {
            nearRow = 12;
            curRow = 11;
        } else {
            nearRow = 13;
            curRow = 14;
        }
        LocMast locMast = null;
        // 2. 开始检索 (优先级:深位堆叠 > 深位空位 > 浅位空位)
        // ===============>>>> 开始执行
        curRow = rowLastno.getCurrentRow();
        // A. 优先尝试:深位为空,且其对应的浅位已经存放了相同物料 (实现 signRule1 的核心逻辑)
        if (Utils.BooleanWhsTypeStaIoType(rowLastno) && !Cools.isEmpty(findLocNoAttributeVo.getMatnr())) {
            List<LocMast> shallowMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                    .eq("row1", shallowRow)
                    .eq("loc_sts", "F")
                    .eq("crn_no", crnNo));
        if (!Cools.isEmpty(moveCrnNo) && moveCrnNo != 0) {
            crnNumber = moveCrnNo;
            if (times == 0) {
                curRow = moveCrnNo * 4 - 1;
            } else {
                curRow = moveCrnNo * 4 - 2;
            }
        }
            for (LocMast sLoc : shallowMasts) {
                LocDetl detl = locDetlService.selectOne(new EntityWrapper<LocDetl>().eq("loc_no", sLoc.getLocNo()));
                if (detl != null && detl.getMatnr().equals(findLocNoAttributeVo.getMatnr())
                        && detl.getBatch().equals(findLocNoAttributeVo.getBatch())) {
//        //此程序用于优化堆垛机异常时的运行时间
//        for (int i = times; i < crnNumber * 2; i++) {
//            int[] locNecessaryParameters = Utils.LocNecessaryParameters(rowLastno, curRow, crnNumber);
//            curRow = locNecessaryParameters[1];
//            crnNo = locNecessaryParameters[2];
//            if (basCrnpService.checkSiteError(crnNo, true)) {
//                rowCount = locNecessaryParameters[0];
//                nearRow = locNecessaryParameters[3];
//                List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
//                        .eq("row1", nearRow).eq("loc_sts", "O").eq("whs_type", rowLastnoType.getType().longValue()));
//                int crnCountO = wrkMastService.selectCount(new EntityWrapper<WrkMast>().eq("crn_no", crnNo).le("io_type", 100));
//                if (locMasts.size() - crnCountO <= 2) {
//                    log.error(crnNo + "号堆垛机没有空库位!!! 尺寸规格: {}, 轮询次数:{}", JSON.toJSONString(locTypeDto), times);
//                    nearRow = 0;
//                    times++;
//                    continue;
//                }
//                break;
//            } else {
//                times++;
//            }
//        }
        if (nearRow == 0) {
            throw new CoolException("无可用堆垛机");
        }
                    String dLocNo = Utils.getDeepLoc(slaveProperties, sLoc.getLocNo());
                    LocMast dLoc = locMastService.selectOne(new EntityWrapper<LocMast>()
                            .eq("loc_no", dLocNo)
                            .eq("loc_sts", "O"));
        boolean signRule1 = false;
        boolean signRule2 = false;
        if (Utils.BooleanWhsTypeStaIoType(rowLastno)) {
            // 靠近摆放规则 --- 同天同规格物料 //分离版
            if (!Cools.isEmpty(findLocNoAttributeVo.getMatnr()) && staDescId == 1) {
                signRule1 = true;
            }
            // 靠近摆放规则 --- 同天同规格物料 //互通版
            if (!Cools.isEmpty(findLocNoAttributeVo.getMatnr()) && staDescId == 1) {
                signRule2 = true;
            }
            if (!Cools.isEmpty(findLocNoAttributeVo.getMatnr()) && (staDescId == 11 || staDescId == 111)) {
                signRule1 = true;
            }
        }
        if (signRule1) {
            if (nearRow != curRow) {
                List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                        .eq("row1", nearRow).eq("loc_sts", "O").eq("crn_no", crnNo));
                for (LocMast locMast1 : locMasts) {
                    //获取巷道
//                    List<String> groupOutsideLocCrn = Utils.getGroupOutLocCrn(curRow,nearRow,locMast1.getLocNo(), curRow>nearRow);
//                    LocMast locMastGro = locMastService.selectById(wrkMast.getLocNo());
                    //获取目标库位所在巷道最浅非空库位
                    LocMast locMastF = locMastService.selectLocByLocStsPakInF(curRow, nearRow, locMast1, rowLastnoType.getType().longValue());
                    if (!Cools.isEmpty(locMastF) && locMastF.getLocSts().equals("F")) {
                        LocDetl locDetl = locDetlService.selectOne(new EntityWrapper<LocDetl>().eq("loc_no", locMastF.getLocNo()));
                        if (!Cools.isEmpty(locDetl) && findLocNoAttributeVo.getMatnr().equals(locDetl.getMatnr())
                                && findLocNoAttributeVo.getBatch().equals(locDetl.getBatch())
                                && findLocNoAttributeVo.getBrand().equals(locDetl.getBrand())) {
                            //获取目标库位所在巷道最深空库位
                            locMast = locMastService.selectLocByLocStsPakInO(curRow, nearRow, locMast1, rowLastnoType.getType().longValue());
                            break;
                        }
                    }
                }
            }
        } else if (signRule2) {
            List<String> locNos = locDetlService.getSameDetlToday(findLocNoAttributeVo.getMatnr(), sRow, eRow);
            for (String locNo : locNos) {
                if (Utils.isShallowLoc(slaveProperties, locNo)) {
                    continue;
                }
                String shallowLocNo = Utils.getShallowLoc(slaveProperties, locNo);
                // 检测目标库位是否为空库位
                LocMast shallowLoc = locMastService.selectById(shallowLocNo);
                if (shallowLoc != null && shallowLoc.getLocSts().equals("O")) {
                    if (VersionUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) {
                        if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) {
                            locMast = shallowLoc;
                            crnNo = locMast.getCrnNo();
                            break;
                        }
                    if (dLoc != null && VersionUtils.locMoveCheckLocTypeComplete(dLoc, locTypeDto)) {
                        locMast = dLoc;
                        break;
                    }
                }
            }
        }
//        // 靠近摆放规则 --- 空托  //分离版
//        if (staDescId == 10 && Utils.BooleanWhsTypeStaIoType(whsType)) {
//            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>().eq("row1", nearRow).eq("loc_sts", "O"));
//            for (LocMast locMast1:locMasts){
//                if (VersionUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) {
//                    continue;
//                }
//                String shallowLoc = Utils.getDeepLoc(slaveProperties,locMast1.getLocNo());
//                LocMast locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no",shallowLoc));
//                if (!Cools.isEmpty(locMast2) && locMast2.getLocSts().equals("D")){
//                    locMast = locMast1;
//                    break;
//                }
//            }
//        }
//        // 靠近摆放规则 --- 空托 //互通版
//        if (staDescId == 10 && Utils.BooleanWhsTypeStaIoType(rowLastno)) {
//            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
//                    .eq("loc_sts", "D").ge("row1", sRow).le("row1", eRow).eq("whs_type", rowLastnoType.getType().longValue()));
//            if (!locMasts.isEmpty()) {
//                for (LocMast loc : locMasts) {
//                    if (Utils.isShallowLoc(slaveProperties, loc.getLocNo())) {
//                        continue;
//                    }
//                    String shallowLocNo = Utils.getShallowLoc(slaveProperties, loc.getLocNo());
//                    // 检测目标库位是否为空库位
//                    LocMast shallowLoc = locMastService.selectById(shallowLocNo);
//                    if (shallowLoc != null && shallowLoc.getLocSts().equals("O")) {
//                        if (VersionUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) {
//                            if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) {
//                                locMast = shallowLoc;
//                                crnNo = locMast.getCrnNo();
//                                break;
//                            }
//                        }
//                    }
//                }
//            }
//        }
        Wrapper<StaDesc> wrapper = null;
        StaDesc staDesc = null;
        BasDevp staNo = null;
//        if (Utils.BooleanWhsTypeSta(rowLastno, staDescId)) {
//            // 获取目标站
//            wrapper = new EntityWrapper<StaDesc>()
//                    .eq("type_no", staDescId)
//                    .eq("stn_no", sourceStaNo)
//                    .eq("crn_no", crnNo);
//            staDesc = staDescService.selectOne(wrapper);
//            if (Cools.isEmpty(staDesc)) {
//                log.error("type_no={},stn_no={},crn_no={}", staDescId, sourceStaNo, crnNo);
////                throw new CoolException("入库路径不存在");
//                crnNo = 0;
//            } else {
//                staNo = basDevpService.selectById(staDesc.getCrnStn());
//                if (!staNo.getAutoing().equals("Y")) {
//                    log.error("目标站" + staDesc.getCrnStn() + "不可用");
////                throw new CoolException("目标站"+staDesc.getCrnStn()+"不可用");
//                    crnNo = 0;
//                }
//                startupDto.setStaNo(staNo.getDevNo());
//            }
//            // 更新库位排号
//            if (Cools.isEmpty(locMast)) {
//                rowLastno.setCurrentRow(curRow);
//                rowLastnoService.updateById(rowLastno);
//            }
//        }
        // 开始查找库位 ==============================>>
        // 1.按规则查找库位
        if (Cools.isEmpty(locMast) && crnNo != 0) {
            // 首先尝试查找对应的深库位排 (11 或 14)
            List<LocMast> deepLocMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                    .eq("row1", curRow)
                    .eq("loc_sts", "O").eq("crn_no", crnNo)
        // B. 次优先:深位为空,且浅位也为空 (入深位)
        if (locMast == null) {
            List<LocMast> deepMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                    .eq("row1", deepRow)
                    .eq("loc_sts", "O")
                    .eq("crn_no", crnNo)
                    .orderBy("lev1", true).orderBy("bay1", true));
            for (LocMast deepLoc : deepLocMasts) {
                if (!VersionUtils.locMoveCheckLocTypeComplete(deepLoc, locTypeDto)) {
                    continue;
                }
                // 获取对应的浅库位,确保浅库位不挡住入库
                String shallowLocNo = Utils.getShallowLoc(slaveProperties, deepLoc.getLocNo());
                LocMast shallowLoc = locMastService.selectOne(new EntityWrapper<LocMast>()
                        .eq("loc_no", shallowLocNo).eq("crn_no", crnNo));
            for (LocMast dLoc : deepMasts) {
                String sLocNo = Utils.getShallowLoc(slaveProperties, dLoc.getLocNo());
                LocMast sLoc = locMastService.selectOne(new EntityWrapper<LocMast>()
                        .eq("loc_no", sLocNo)
                        .eq("loc_sts", "O"));
                // 只有浅库位为空,或者浅库位已经有货(且不是挡住入库的状态,这里简单判断为空即可放入深库位)
                // 实际上,双深入库时,如果深库位为空且浅库位为空,应优先入深库位
                if (!Cools.isEmpty(shallowLoc) && (shallowLoc.getLocSts().equals("O") || shallowLoc.getLocSts().equals("F"))) {
                    locMast = deepLoc;
                    break;
                }
            }
            // 如果没找到深库位,再尝试找浅库位排 (12 或 13)
            if (Cools.isEmpty(locMast)) {
                List<LocMast> shallowLocMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                        .eq("row1", nearRow)
                        .eq("loc_sts", "O").eq("crn_no", crnNo)
                        .orderBy("lev1", true).orderBy("bay1", true));
                for (LocMast shallowLoc : shallowLocMasts) {
                    if (!VersionUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) {
                        continue;
                    }
                    // 浅库位入库的前提是深库位已经满了,或者有特殊要求。这里直接允许入浅库位。
                    locMast = shallowLoc;
                if (sLoc != null && VersionUtils.locMoveCheckLocTypeComplete(dLoc, locTypeDto)) {
                    locMast = dLoc;
                    break;
                }
            }
        }
        if (!Cools.isEmpty(locMast) && !basCrnpService.checkSiteError(crnNo, true)) {
            locMast = null;
        // C. 最后:如果深位实在没法放(深位已满或浅位挡路且物料不同),再考虑浅位为空
        if (locMast == null) {
            List<LocMast> shallowMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                    .eq("row1", shallowRow)
                    .eq("loc_sts", "O")
                    .eq("crn_no", crnNo)
                    .orderBy("lev1", true).orderBy("bay1", true));
            for (LocMast sLoc : shallowMasts) {
                if (VersionUtils.locMoveCheckLocTypeComplete(sLoc, locTypeDto)) {
                    locMast = sLoc;
                    break;
                }
            }
        }
        // 递归查询
        if (Cools.isEmpty(locMast) || !locMast.getLocSts().equals("O")) {
            // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归
        // 3. 递归与异常处理
        if (Cools.isEmpty(locMast)) {
            // 当前这组货架找完了,递归尝试下一组
            if (times < rowCount * 2) {
                times = times + 1;
                return getDoubleLocNoRun(whsType, 1, sourceStaNo, findLocNoAttributeVo, moveCrnNo, locTypeDto, times);
                return getDoubleLocNoRun(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, moveCrnNo, locTypeDto, times + 1);
            }
//            // 2.库位当前所属尺寸无空库位时,调整尺寸参数,向上兼容检索库位
//            if (locTypeDto.getLocType1() < 2) {
//                int i = locTypeDto.getLocType1() + 1;
//                locTypeDto.setLocType1((short)i);
//                return getLocNo(1, staDescId, sourceStaNo, matnr,batch,grade, locTypeDto, 0);
//            }
            log.error("系统没有空库位!!! 尺寸规格: {}, 轮询次数:{}", JSON.toJSONString(locTypeDto), times);
            throw new CoolException("没有空库位");
        }
        String locNo = locMast.getLocNo();
        // 生成工作号
        // 4. 返回结果
        String locNo = locMast.getLocNo();
        int workNo = getWorkNo(0);
        // 返回dto
        startupDto.setWorkNo(workNo);
        startupDto.setCrnNo(crnNo);
        startupDto.setSourceStaNo(sourceStaNo);