自动化立体仓库 - WMS系统
dubin
2 天以前 6c8588d5f7f0de7e9489426c350472bf911a4933
src/main/java/com/zy/common/service/CommonService.java
@@ -1,26 +1,23 @@
package com.zy.common.service;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.Arith;
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.result.FindLocNoAttributeVo;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.asrs.utils.VersionUtils;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.Shelves;
import com.zy.common.model.StartupDto;
import com.zy.common.properties.SlaveProperties;
import io.swagger.models.auth.In;
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.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
@@ -90,405 +87,417 @@
        return workNo;
    }
    /**
     * 检索库位号
     *
     * @param whsType     类型 1:双深式货架
     * @param staDescId   路径工作类型
     * @param sourceStaNo 源站
     * @param matNos      商品编号集合
     * @param staDescId            路径ID
     * @param sourceStaNo          源站
     * @param findLocNoAttributeVo 属性
     * @param locTypeDto           类型
     * @return locNo 检索到的库位号
     */
    @Transactional
    public StartupDto getLocNo4(Integer whsType, Integer staDescId, Integer sourceStaNo, List<String> matNos, LocTypeDto locTypeDto, int times) {
        StartupDto startupDto = new StartupDto();
        if (sourceStaNo == 101 || sourceStaNo == 103) {
            whsType = 1;
        } else if (sourceStaNo == 105 || sourceStaNo == 107) {
            whsType = 2;
        } else {
            throw new CoolException("站点数据异常,请联系管理员");
    public StartupDto getLocNo(Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, LocTypeDto locTypeDto, String barcode) {
        StartupDto startupDto = null;
        StringBuilder builder = new StringBuilder();
        try {
            startupDto = searchLocNoByCrnNo(staDescId, sourceStaNo, findLocNoAttributeVo, locTypeDto);
        } catch (Exception e) {
            builder.append(e.getMessage()).append(",");
        }
        RowLastno rowLastno = rowLastnoService.selectById(whsType);
        if (Cools.isEmpty(rowLastno)) {
            throw new CoolException("1数据异常,请联系管理员");
        if(startupDto == null) {
            builder.append("找不到空库位");
            throw new CoolException(builder.toString());
        }
        // ===============>>>> 开始执行
        int curRow = rowLastno.getCurrentRow();
        int sRow = rowLastno.getsRow();
        int eRow = rowLastno.geteRow();
        int crn_qty = rowLastno.getCrnQty();
        int rowCount = eRow - sRow + 1;
        // 目标堆垛机号
        int crnNo = 0;
        // 目标库位
        LocMast locMast = null;
        // 靠近摆放规则 --- 同天同规格物料
        if (!Cools.isEmpty(matNos)) {
            List<String> locNos = locDetlService.getSameDetlToday(matNos.get(0), 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.locMoveCheckLocType(shallowLoc, locTypeDto)) {
                        if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) {
                            locMast = shallowLoc;
                            crnNo = locMast.getCrnNo();
                            break;
                        }
                    }
                }
            }
        }
        // 靠近摆放规则 --- 空托
        if (staDescId == 10) {
            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>().eq("loc_sts", "D").ge("row1", sRow).le("row1", eRow));
            if (locMasts.size() > 0) {
                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 (shallowLoc.getLocType1() < locTypeDto.getLocType1()) {
                            continue;
                        }
                        if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) {
                            locMast = shallowLoc;
                            crnNo = locMast.getCrnNo();
                            break;
                        }
                    }
                }
            }
        }
        // 如果没有相近物料,则按规则轮询货架
        if (null == locMast) {
            Shelves shelves = new Shelves(rowCount, crn_qty);
            int divides = (int) Arith.divides(1, curRow - 1, 4);
            curRow = (int) Arith.remainder(curRow, 4);
            if (curRow == 0) {
                curRow = 4;
            }
            for (int i = 0; i < shelves.group; i++) {
                curRow = shelves.start(curRow);
                if (curRow < 0) {
                    throw new CoolException("检索库位失败,请联系管理员");
                }
                Integer crnNo1 = shelves.get(curRow);
                crnNo1 = crnNo1 + divides * 1;
                if (basCrnpService.checkSiteError(crnNo1, true)) {
                    crnNo = crnNo1;
                    curRow = curRow + divides * 4;
                    break;
                }
            }
        }
        if (crnNo == 0) {
            throw new CoolException("没有可用的堆垛机");
        }
        // 获取目标站
        Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                .eq("type_no", staDescId)
                .eq("stn_no", sourceStaNo)
                .eq("crn_no", crnNo);
        StaDesc staDesc = staDescService.selectOne(wrapper);
        if (Cools.isEmpty(staDesc)) {
            log.error("type_no={},stn_no={},crn_no={}", staDescId, sourceStaNo, crnNo);
            throw new CoolException("入库路径不存在");
        }
        BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn());
        if (!staNo.getAutoing().equals("Y")) {
            throw new CoolException("目标站" + staDesc.getCrnStn() + "不可用");
        }
        // 更新库位排号
        rowLastno.setCurrentRow(curRow);
        rowLastnoService.updateById(rowLastno);
        // 开始查找库位 ==============================>>
        // 1.当检索库排为浅库位排时,优先寻找当前库排的深库位排
        if (locMast == null) {
            if (Utils.isShallowLoc(slaveProperties, curRow)) {
                Integer deepRow = Utils.getDeepRow(slaveProperties, curRow);
                locMast = locMastService.queryFreeLocMast(deepRow, locTypeDto.getLocType1());
                // todo:luxiaotao 如果用浅排找到的深库位,那么则需要判断这个深库位对应的浅库位是否有货(F、X、D)
                // 因库位移转、需预留空库位
                if (!locMastService.checkEmptyCount(locMast)) {
                    locMast = null;
                }
            }
            if (Cools.isEmpty(locMast)) {
                locMast = locMastService.queryFreeLocMast(curRow, locTypeDto.getLocType1());
                // 因库位移转、需预留空库位
                if (!locMastService.checkEmptyCount(locMast)) {
                    locMast = null;
                }
                // 目标库位 ===>> 浅库位, 则校验其深库位是否为 F D X
                if (null != locMast && Utils.isShallowLoc(slaveProperties, locMast.getLocNo())) {
                    LocMast deepLoc = locMastService.selectById(Utils.getDeepLoc(slaveProperties, locMast.getLocNo()));
                    if (!deepLoc.getLocSts().equals("F") && !deepLoc.getLocSts().equals("D") && !deepLoc.getLocSts().equals("X")) {
                        locMast = null;
                    }
                }
                // 目标库位 ===>> 深库位, 则校验其浅库位是否为 O
                if (null != locMast && Utils.isDeepLoc(slaveProperties, locMast.getLocNo())) {
                    LocMast shallowLoc = locMastService.selectById(Utils.getShallowLoc(slaveProperties, locMast.getLocNo()));
                    if (!shallowLoc.getLocSts().equals("O")) {
                        locMast = null;
                    }
                }
            }
        }
        // 2.库位当前所属尺寸无空库位时,调整尺寸参数,向上兼容检索库位
        if (Cools.isEmpty(locMast)) {
            // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归
            if (times < rowCount) {
                times = times + 1;
                return getLocNo(1, staDescId, sourceStaNo, matNos, locTypeDto, times);
            }
            // 轻货物找轻库位为空时,可以去找重库位仓
            if (locTypeDto.getLocType1() == 1) {
                locTypeDto.setLocType1((short) 2);
                return getLocNo(1, staDescId, sourceStaNo, matNos, locTypeDto, times);
            }
            log.error("系统没有空库位!!! 尺寸规格: {}, 轮询次数:{}", JSON.toJSONString(locTypeDto), times);
            throw new CoolException("没有空库位");
        }
        String locNo = locMast.getLocNo();
        // 生成工作号
        int workNo = getWorkNo(0);
        // 返回dto
        startupDto.setWorkNo(workNo);
        startupDto.setCrnNo(crnNo);
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setStaNo(staNo.getDevNo());
        startupDto.setLocNo(locNo);
        return startupDto;
    }
    /**
     * 检索库位号
     *
     * @param staDescId            路径ID
     * @param sourceStaNo          源站
     * @param findLocNoAttributeVo 属性
     * @param locTypeDto           类型
     * @return locNo 检索到的库位号
     * wms-dev
     */
    @Transactional
    public StartupDto getLocNoToWmsDev(Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, LocTypeDto locTypeDto, String barcode,int[] row) {
        StartupDto startupDto = null;
        StringBuilder builder = new StringBuilder();
        try {
            startupDto = searchLocNoByCrnNoToWmsDev(staDescId, sourceStaNo, findLocNoAttributeVo, locTypeDto,row);
        } catch (Exception e) {
            builder.append(e.getMessage()).append(",");
        }
        if(startupDto == null) {
            builder.append("找不到空库位");
            throw new CoolException(builder.toString());
        }
        return startupDto;
    }
    /**
     * 检索库位号
     *
     * @param whsType     类型 1:双深式货架
     * @param staDescId   路径工作类型
     * @param sourceStaNo 源站
     * @param matNos      商品编号集合
     * @param staDescId            路径ID
     * @param sourceStaNo          源站
     * @param findLocNoAttributeVo 属性
     * @param locTypeDto           类型
     * @return locNo 检索到的库位号
     */
    @Transactional
    public StartupDto getLocNo(Integer whsType, Integer staDescId, Integer sourceStaNo, List<String> matNos, LocTypeDto locTypeDto, int times) {
//        whsType = getWhsType(sourceStaNo, times);
    public StartupDto searchLocNoByCrnNo(Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, LocTypeDto locTypeDto) {
        LocMast locMast = null;
        if (staDescId == 10) {
            //搜索空托盘
            locMast = searchEmptyPallet(locTypeDto);
        }else {
            //满托盘
            locMast = searchMaxPallet(findLocNoAttributeVo, locTypeDto);
        }
        if(locMast == null) {
            throw new CoolException("找不到符合尺寸的空库位");
        }
        StartupDto startupDto = new StartupDto();
//        if (sourceStaNo < 200){
//            whsType = 1;
//        } else if (sourceStaNo > 199 && sourceStaNo < 300){
//            whsType = 2;
//        } else if (sourceStaNo > 299 && sourceStaNo < 400){
//            whsType = 3;
//        } else if (sourceStaNo > 399){
//            whsType = 4;
//        // 获取目标站
//        Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>().eq("type_no", staDescId).eq("stn_no", sourceStaNo).eq("crn_no", locMast.getCrnNo());
//        StaDesc staDesc = staDescService.selectOne(wrapper);
//        if (Cools.isEmpty(staDesc)) {
//            log.error("type_no={},stn_no={},crn_no={}", staDescId, sourceStaNo, crnNo);
//            throw new CoolException("入库路径不存在");
//        } else {
//            BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn());
//            if (!staNo.getAutoing().equals("Y")) {
//                log.error("目标站" + staDesc.getCrnStn() + "不可用");
//                throw new CoolException("目标站"+staDesc.getCrnStn()+"不可用");
//            }
//            startupDto.setStaNo(staNo.getDevNo());
//        }
        String locNo = locMast.getLocNo();
        // 生成工作号
        int workNo = getWorkNo(0);
        // 返回dto
        startupDto.setTaskNo(workNo);
        startupDto.setCrnNo(locMast.getCrnNo());
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setLocNo(locNo);
        startupDto.setTaskPri(13.0);
        return startupDto;
    }
        if (sourceStaNo == 101 || sourceStaNo == 103) {
            whsType = 1;
        } else if (sourceStaNo == 105 || sourceStaNo == 107) {
            whsType = 2;
        } else {
            throw new CoolException("站点数据异常,请联系管理员");
        }
        RowLastno rowLastno = rowLastnoService.selectById(whsType);
        if (Cools.isEmpty(rowLastno)) {
            throw new CoolException("1数据异常,请联系管理员");
        }
        // ===============>>>> 开始执行
        int curRow = rowLastno.getCurrentRow();
        int sRow = rowLastno.getsRow();
        int eRow = rowLastno.geteRow();
        int crn_qty = rowLastno.getCrnQty();
        int rowCount = eRow - sRow + 1;
        // 目标堆垛机号
        int crnNo = 0;
        // 目标库位
    @Transactional
    public StartupDto searchLocNoByCrnNoToWmsDev(Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, LocTypeDto locTypeDto,int[] row) {
        LocMast locMast = null;
        if (staDescId == 10) {
            //搜索空托盘
            locMast = searchEmptyPallet(locTypeDto);
        }else {
            //满托盘
            locMast = searchMaxPalletToWmsDev(findLocNoAttributeVo, locTypeDto,row);
        }
        // 靠近摆放规则 --- 同天同规格物料
        if (!Cools.isEmpty(matNos)) {
            List<String> locNos = locDetlService.getSameDetlToday(matNos.get(0), sRow, eRow);
            for (String locNo : locNos) {
                if (Utils.isShallowLoc(slaveProperties, locNo)) {
        if(locMast == null) {
            throw new CoolException("找不到符合尺寸的空库位");
        }
        StartupDto startupDto = new StartupDto();
        // 获取目标站
//        Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>().eq("type_no", staDescId).eq("stn_no", sourceStaNo).eq("crn_no", locMast.getCrnNo());
//        StaDesc staDesc = staDescService.selectOne(wrapper);
//        if (Cools.isEmpty(staDesc)) {
//            log.error("type_no={},stn_no={},crn_no={}", staDescId, sourceStaNo, crnNo);
//            throw new CoolException("入库路径不存在");
//        } else {
//            BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn());
//            if (!staNo.getAutoing().equals("Y")) {
//                log.error("目标站" + staDesc.getCrnStn() + "不可用");
//                throw new CoolException("目标站"+staDesc.getCrnStn()+"不可用");
//            }
//            startupDto.setStaNo(staNo.getDevNo());
//        }
        String locNo = locMast.getLocNo();
        // 生成工作号
        int workNo = getWorkNo(0);
        // 返回dto
        startupDto.setTaskNo(workNo);
        startupDto.setCrnNo(locMast.getCrnNo());
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setLocNo(locToLocNo(locNo));
        startupDto.setTaskPri(13.0);
        return startupDto;
    }
    public String locToLocNo(String locNo){//0100203
        int row = Integer.parseInt(locNo.substring(0, 2));
        int bay = Integer.parseInt(locNo.substring(2, 5));
        int lev = Integer.parseInt(locNo.substring(5, 7));
        return row + "-" +bay + "-" + lev;
    }
    //搜索满托盘库位
    public LocMast searchMaxPallet(FindLocNoAttributeVo findLocNoAttributeVo, LocTypeDto locTypeDto) {
        LocMast targetLocMast = null;
        List<String> locNos = locDetlService.getSameDetlList(findLocNoAttributeVo.getMatnr());
        for (String locNo : locNos) {
            //获取通道组
            List<Integer> locRowGroupDesc = Utils.getLocGroupDesc(slaveProperties, locNo);
            for (Integer row : locRowGroupDesc) {
                String deepLocNo = Utils.getLocNo(row, Utils.getBay(locNo), Utils.getLev(locNo));
                LocMast deepLoc = locMastService.selectById(deepLocNo);
                if (deepLoc == null) {
                    continue;
                }
                String shallowLocNo = Utils.getShallowLoc(slaveProperties, locNo);
                // 检测目标库位是否为空库位
                LocMast shallowLoc = locMastService.selectById(shallowLocNo);
                if (shallowLoc != null && shallowLoc.getLocSts().equals("O")) {
                    if (VersionUtils.locMoveCheckLocType(shallowLoc, locTypeDto)) {
                        if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) {
                            locMast = shallowLoc;
                            crnNo = locMast.getCrnNo();
                            break;
                        }
                    }
                if (deepLoc.getLocSts().equals("F")) {
                    continue;
                } else if (deepLoc.getLocSts().equals("O")) {
                    targetLocMast = deepLoc;
                    break;
                }else {
                    break;
                }
            }
        }
        // 靠近摆放规则 --- 空托
        if (staDescId == 10) {
            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>().eq("loc_sts", "D").ge("row1", sRow).le("row1", eRow));
            if (locMasts.size() > 0) {
                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 (shallowLoc.getLocType1() < locTypeDto.getLocType1()) {
        if(targetLocMast == null) {
            //相近物料匹配失败,搜索可用空库位组
            //获取设备楼层
            List<Integer> levList = basCrnpService.getLevList();
            Collections.shuffle(levList);
            List<Integer> locLevList = locMastService.getLevList();
            levList.addAll(locLevList);
            for (Integer lev : levList) {
                List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                        .eq("loc_sts", "O")
                        .eq("lev1", lev)
                        .orderBy("bay1", true));
                for (LocMast locMast : locMasts) {
                    String locNo = locMast.getLocNo();
                    //获取通道组
                    List<Integer> locRowGroupDesc = Utils.getLocGroupDesc(slaveProperties, locNo);
                    boolean flag = true;
                    for (Integer row : locRowGroupDesc) {
                        String deepLocNo = Utils.getLocNo(row, Utils.getBay(locNo), Utils.getLev(locNo));
                        LocMast deepLoc = locMastService.selectById(deepLocNo);
                        if (deepLoc == null) {
                            continue;
                        }
                        if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) {
                            locMast = shallowLoc;
                            crnNo = locMast.getCrnNo();
                        if (!deepLoc.getLocSts().equals("O")) {
                            flag = false;
                            break;
                        }
                    }
                    if (flag) {
                        for (Integer row : locRowGroupDesc) {
                            String deepLocNo = Utils.getLocNo(row, Utils.getBay(locNo), Utils.getLev(locNo));
                            LocMast deepLoc = locMastService.selectById(deepLocNo);
                            if (deepLoc == null) {
                                continue;
                            }
                            targetLocMast = deepLoc;
                            break;
                        }
                        break;
                    }
                }
                if (targetLocMast != null) {
                    break;
                }
            }
        }
        return targetLocMast;
    }
    //搜索满托盘库位 wms-dev
    public LocMast searchMaxPalletToWmsDev(FindLocNoAttributeVo findLocNoAttributeVo, LocTypeDto locTypeDto,int[] rows) {
        LocMast targetLocMast = null;
        List<String> locNos = locDetlService.getSameDetlListToWmsDev(findLocNoAttributeVo.getMatnr(),rows);
        for (String locNo : locNos) {
            //获取通道组
            List<Integer> locRowGroupDesc = Utils.getLocGroupDesc(slaveProperties, locNo);
            for (Integer row : locRowGroupDesc) {
                String deepLocNo = Utils.getLocNo(row, Utils.getBay(locNo), Utils.getLev(locNo));
                LocMast deepLoc = locMastService.selectById(deepLocNo);
                if (deepLoc == null) {
                    continue;
                }
                if (deepLoc.getLocSts().equals("F")) {
                    continue;
                } else if (deepLoc.getLocSts().equals("O")) {
                    targetLocMast = deepLoc;
                    break;
                }else {
                    break;
                }
            }
        }
        // 如果没有相近物料,则按规则轮询货架
        if (null == locMast) {
            Shelves shelves = new Shelves(rowCount, crn_qty);
            int divides = (int) Arith.divides(1, curRow - 1, 4);
            curRow = (int) Arith.remainder(curRow, 4);
            if (curRow == 0) {
                curRow = 4;
            }
            for (int i = 0; i < shelves.group; i++) {
                curRow = shelves.start(curRow);
                if (curRow < 0) {
                    throw new CoolException("检索库位失败,请联系管理员");
        if(targetLocMast == null) {
            //相近物料匹配失败,搜索可用空库位组
            //获取设备楼层
//            List<Integer> levList = basCrnpService.getLevList();
//            Collections.shuffle(levList);
//
//            List<Integer> locLevList = locMastService.getLevList();
//            levList.addAll(locLevList);
//            for (Integer lev : levList) {
//            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
//                    .eq("loc_sts", "O")
//                    .in("row1",rows)
//                    .orderBy("bay1", true));
           List<LocMast> locMasts = locMastService.selectLoc(rows);
            for (LocMast locMast : locMasts) {
                String locNo = locMast.getLocNo();
                //获取通道组
                List<Integer> locRowGroupDesc = Utils.getLocGroupDesc(slaveProperties, locNo);
                boolean flag = true;
                for (Integer row : locRowGroupDesc) {
                    String deepLocNo = Utils.getLocNo(row, Utils.getBay(locNo), Utils.getLev(locNo));
                    LocMast deepLoc = locMastService.selectById(deepLocNo);
                    if (deepLoc == null) {
                        continue;
                    }
                    if (!deepLoc.getLocSts().equals("O")) {
                        flag = false;
                        break;
                    }
                }
                Integer crnNo1 = shelves.get(curRow);
                crnNo1 = crnNo1 + divides * 1;
                if (basCrnpService.checkSiteError(crnNo1, true)) {
                    crnNo = crnNo1;
                    curRow = curRow + divides * 4;
                if (flag) {
                    for (Integer row : locRowGroupDesc) {
                        String deepLocNo = Utils.getLocNo(row, Utils.getBay(locNo), Utils.getLev(locNo));
                        LocMast deepLoc = locMastService.selectById(deepLocNo);
                        if (deepLoc == null) {
                            continue;
                        }
                        targetLocMast = deepLoc;
                        break;
                    }
                    break;
                }
            }
//                if (targetLocMast != null) {
//                    break;
//                }
//            }
        }
        return targetLocMast;
    }
    //搜索空托盘库位
    public LocMast searchEmptyPallet(LocTypeDto locTypeDto) {
        LocMast targetLocMast = null;
        List<LocMast> locMastsD = locMastService.selectList(new EntityWrapper<LocMast>()
                .eq("loc_sts", "D"));
        for (LocMast locMast : locMastsD) {
            String locNo = locMast.getLocNo();
            //获取通道组
            List<Integer> locRowGroupDesc = Utils.getLocGroupDesc(slaveProperties, locNo);
            for (Integer row : locRowGroupDesc) {
                String deepLocNo = Utils.getLocNo(row, Utils.getBay(locNo), Utils.getLev(locNo));
                LocMast deepLoc = locMastService.selectById(deepLocNo);
                if (deepLoc == null) {
                    continue;
                }
                if (deepLoc.getLocSts().equals("F")) {
                    continue;
                } else if (deepLoc.getLocSts().equals("O")) {
                    targetLocMast = deepLoc;
                    break;
                }else {
                    break;
                }
            }
        }
        if(targetLocMast == null) {
            //获取设备楼层
            List<Integer> levList = basCrnpService.getLevList();
            Collections.shuffle(levList);
            List<Integer> locLevList = locMastService.getLevList();
            levList.addAll(locLevList);
            for (Integer lev : levList) {
                //相近物料匹配失败,搜索可用空库位组
                List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                        .eq("loc_sts", "O")
                        .eq("lev1", lev)
                        .orderBy("bay1", true));
                for (LocMast locMast : locMasts) {
                    String locNo = locMast.getLocNo();
                    //获取通道组
                    List<Integer> locRowGroupDesc = Utils.getLocGroupDesc(slaveProperties, locNo);
                    boolean flag = true;
                    for (Integer row : locRowGroupDesc) {
                        String deepLocNo = Utils.getLocNo(row, Utils.getBay(locNo), Utils.getLev(locNo));
                        LocMast deepLoc = locMastService.selectById(deepLocNo);
                        if (deepLoc == null) {
                            continue;
                        }
                        if (!deepLoc.getLocSts().equals("O")) {
                            flag = false;
                            break;
                        }
                    }
                    if (flag) {
                        for (Integer row : locRowGroupDesc) {
                            String deepLocNo = Utils.getLocNo(row, Utils.getBay(locNo), Utils.getLev(locNo));
                            LocMast deepLoc = locMastService.selectById(deepLocNo);
                            if (deepLoc == null) {
                                continue;
                            }
                            targetLocMast = deepLoc;
                            break;
                        }
                        break;
                    }
                }
                if (targetLocMast != null) {
                    break;
                }
            }
        }
        if (crnNo == 0) {
            throw new CoolException("没有可用的堆垛机");
        }
        // 获取目标站
        Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                .eq("type_no", staDescId)
                .eq("stn_no", sourceStaNo)
                .eq("crn_no", crnNo);
        StaDesc staDesc = staDescService.selectOne(wrapper);
        if (Cools.isEmpty(staDesc)) {
            log.error("type_no={},stn_no={},crn_no={}", staDescId, sourceStaNo, crnNo);
            throw new CoolException("入库路径不存在");
        }
        BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn());
        if (!staNo.getAutoing().equals("Y")) {
            throw new CoolException("目标站" + staDesc.getCrnStn() + "不可用");
        }
        // 更新库位排号
        rowLastno.setCurrentRow(curRow);
        rowLastnoService.updateById(rowLastno);
        // 开始查找库位 ==============================>>
        // 1.当检索库排为浅库位排时,优先寻找当前库排的深库位排
        if (locMast == null) {
            if (Utils.isShallowLoc(slaveProperties, curRow)) {
                Integer deepRow = Utils.getDeepRow(slaveProperties, curRow);
                locMast = locMastService.queryFreeLocMast(deepRow, locTypeDto.getLocType1());
                // todo:luxiaotao 如果用浅排找到的深库位,那么则需要判断这个深库位对应的浅库位是否有货(F、X、D)
                // 因库位移转、需预留空库位
                if (!locMastService.checkEmptyCount(locMast)) {
                    locMast = null;
                }
            }
            if (Cools.isEmpty(locMast)) {
                locMast = locMastService.queryFreeLocMast(curRow, locTypeDto.getLocType1());
                // 因库位移转、需预留空库位
                if (!locMastService.checkEmptyCount(locMast)) {
                    locMast = null;
                }
                // 目标库位 ===>> 浅库位, 则校验其深库位是否为 F D X
                if (null != locMast && Utils.isShallowLoc(slaveProperties, locMast.getLocNo())) {
                    LocMast deepLoc = locMastService.selectById(Utils.getDeepLoc(slaveProperties, locMast.getLocNo()));
                    if (!deepLoc.getLocSts().equals("F") && !deepLoc.getLocSts().equals("D") && !deepLoc.getLocSts().equals("X")) {
                        locMast = null;
                    }
                }
                // 目标库位 ===>> 深库位, 则校验其浅库位是否为 O
                if (null != locMast && Utils.isDeepLoc(slaveProperties, locMast.getLocNo())) {
                    LocMast shallowLoc = locMastService.selectById(Utils.getShallowLoc(slaveProperties, locMast.getLocNo()));
                    if (!shallowLoc.getLocSts().equals("O")) {
                        locMast = null;
                    }
                }
            }
        }
        // 2.库位当前所属尺寸无空库位时,调整尺寸参数,向上兼容检索库位
        if (Cools.isEmpty(locMast)) {
            // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归
            if (times < rowCount) {
                times = times + 1;
                return getLocNo(1, staDescId, sourceStaNo, matNos, locTypeDto, times);
            }
            // 轻货物找轻库位为空时,可以去找重库位仓
            if (locTypeDto.getLocType1() == 1) {
                locTypeDto.setLocType1((short) 2);
                return getLocNo(1, staDescId, sourceStaNo, matNos, locTypeDto, times);
            }
            log.error("系统没有空库位!!! 尺寸规格: {}, 轮询次数:{}", JSON.toJSONString(locTypeDto), times);
            throw new CoolException("没有空库位");
        }
        String locNo = locMast.getLocNo();
        // 生成工作号
        int workNo = getWorkNo(0);
        // 返回dto
        startupDto.setWorkNo(workNo);
        startupDto.setCrnNo(crnNo);
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setStaNo(staNo.getDevNo());
        startupDto.setLocNo(locNo);
        return startupDto;
        return targetLocMast;
    }
    public static String zerofill(String msg, Integer count) {
        if (msg.length() == count) {
@@ -502,158 +511,6 @@
            }
            return msgBuilder.toString();
        }
    }
    /**
     * 根据入库站获取库位排号分配
     */
    private Integer getWhsType(Integer sourceStaNo, int times) {
        if (times >= 16) {
            return 4;
        }
        switch (sourceStaNo) {
            case 173:
            case 176:
            case 180:
            case 185:
                return 1;
            case 189:
            case 194:
            case 198:
            case 202:
                return 2;
            case 206:
//            case 211:
//            case 215:
//            case 219:
//            case 223:
            case 227:
                return 3;
            case 305:
            case 303:
            case 301:
                return 4;
            default:
                throw new CoolException("根据入库站获取库位排号分配失败,入库站:" + sourceStaNo);
        }
    }
    /**
     * @param waitPakin 组托的物料
     * @param arr       保存顺序层
     * @param d         下标
     * @param locType   物料是否为特殊物料
     * @param locType1  1.满托  2.空托
     * @return
     */
    public LocMast getLocNo2(WaitPakin waitPakin, Integer[] arr, Integer d, Integer locType, Integer locType1) {
        LocMast locMast = null;
        try {
            //一.查询入库货物是否是特殊摆放货物
            if (locType == 2) {
                //查找层标记的
                LocMast locMast1 = locMastService.selectOne(new EntityWrapper<LocMast>()
                        .eq("lev1", arr[d])
                        .eq("loc_sts", "O")
                        .eq("loc_type1", 2)
                        .eq("loc_attribute", 1));
                if (!Cools.isEmpty(locMast1)) {
                    locMast = locMast1;
                }
            } else {
                List<LocMast> locMasts = new ArrayList<>();
                //二.空栈板摆放规则
                //1.该层相同空栈板
                //2.获得locAttribute库位属性为1的所有库位
                //3.查看组里是否还有空位
                if (locType1 == 2) {
                    locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                            .eq("lev1", arr[d])
                            .eq("loc_sts", "D")
                            .eq("loc_type1", 1)
                            .eq("loc_attribute", 1));
                    if (!Cools.isEmpty(locMasts)) {
                        for (LocMast locMast1 : locMasts) {
                            //4.查看该组是否有预约入库和预约出库的库位,有的话直接跳过该组
                            List<LocMast> locMasts2 = locMastService.selectList(new EntityWrapper<LocMast>()
                                    .eq("group1", locMast1.getGroup1())
                                    .in("loc_sts", "P", "Q", "R", "S"));
                            if (!Cools.isEmpty(locMasts2)) {
                                continue;
                            }
                            //5.找出同一组的空库位
                            //6.对深浅库位进行排序
                            List<LocMast> locMasts1 = locMastService.selectList(new EntityWrapper<LocMast>()
                                    .eq("group1", locMast1.getGroup1())
                                    .eq("loc_sts", "O")
                                    .orderBy("locAttribute"));
                            if (Cools.isEmpty(locMasts1)) {
                                continue;
                            }
                            //7.查看
                            locMast = locMasts1.get(0);
                        }
                    }
                } else {
                    //三.正常货物入库
                    //1.该层相同物料摆放
                    //2.获得locAttribute库位属性为1的所有库位
                    //3.查看组里是否还有空位
                    locMasts = locMastService.querySame(waitPakin.getMatnr(), arr[d]);
                    if (!Cools.isEmpty(locMasts)) {
                        for (LocMast locMast1 : locMasts) {
                            //4.查看该组是否有预约入库和预约出库的库位,有的话直接跳过该组
                            List<LocMast> locMasts2 = locMastService.selectList(new EntityWrapper<LocMast>()
                                    .eq("group1", locMast1.getGroup1())
                                    .in("loc_sts", "P", "Q", "R", "S"));
                            if (!Cools.isEmpty(locMasts2)) {
                                continue;
                            }
                            //5.找出同一组的空库位
                            //6.对深浅库位进行排序
                            List<LocMast> locMasts1 = locMastService.selectList(new EntityWrapper<LocMast>()
                                    .eq("group1", locMast1.getGroup1())
                                    .eq("loc_sts", "O")
                                    .orderBy("locAttribute"));
                            if (Cools.isEmpty(locMasts1)) {
                                continue;
                            }
                            //7.查看
                            locMast = locMasts1.get(0);
                        }
                    }
                }
                //四.没有相同物料,进行正常找库
                if (Cools.isEmpty(locMast)) {
                    //查找该层所有空的"loc_attribute",1
                    List<LocMast> locMastList = locMastService.selectList(new EntityWrapper<LocMast>()
                            .eq("lev1", arr[d])
                            .eq("loc_sts", "O")
                            .eq("loc_type1", 1)
                            .eq("loc_attribute", 1)
                            .orderBy("row1", false)
                            .orderBy("bay1", false));
                    if (!Cools.isEmpty(locMastList)) {
                        locMast = locMastList.get(0);
                    }
                }
                //该层没有找到库位时进入递归换层找库位
                if (Cools.isEmpty(locMast)) {
                    ++d;
                    if (d > 6) {
                        throw new CoolException("没有空库位");
                    }
                    if (d == 6 && locType == 2) {
                        return getLocNo2(waitPakin, arr, 0, 1, locType1);
                    }
                    return getLocNo2(waitPakin, arr, d, locType, locType1);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return locMast;
    }
}