自动化立体仓库 - WMS系统
Junjie
2025-09-13 b0a40b8b4f2921d449e2d750cfeb56979cd563e1
#四向库入库规则
1个文件已添加
6个文件已删除
17个文件已修改
1866 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/WorkController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/result/FindLocNoAttributeVo.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/LocDetlMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/WaitPakinMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/LocDetlService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/WaitPakinService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/WorkService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/LocDetlServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WaitPakinServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/CheckDeepScheduler.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/ErrorStockScheduler.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/PlcLogScheduler.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/CheckDeepHandler.java 255 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/ErrorStockHandler.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/PlcLogHandler.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/utils/Utils.java 161 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/properties/SlaveProperties.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/service/CommonService.java 684 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/WcsController.java 348 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/param/SearchLocParam.java 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/LocDetlMapper.xml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WaitPakinMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/WorkController.java
@@ -144,18 +144,4 @@
        return R.ok();
    }
//    @RequestMapping("/create/waitPain/wrkMast/start")
//    @ManagerAuth(memo = "生成任务")
//    public R createWaitPainWrkMastStart(@RequestBody List<WaitPakin> list) {
//        StartupDto startupDto = workService.createWaitPainWrkMastStart(list, getUserId());
//        return R.ok("任务号:" + startupDto.getWorkNo() + ";目标库位:" + startupDto.getLocNo());
//    }
    @RequestMapping("/deal/preHave/start")
    @ManagerAuth(memo = "先入品处理")
    public R dealPreHave(@RequestParam Integer wrkNo) {
        String locNo = workService.dealPreHaveStart(wrkNo, getUserId());
        return R.ok("任务重新入库,目标库位:" + locNo);
    }
}
src/main/java/com/zy/asrs/entity/result/FindLocNoAttributeVo.java
New file
@@ -0,0 +1,18 @@
package com.zy.asrs.entity.result;
import lombok.Data;
@Data
public class FindLocNoAttributeVo {
    private String matnr = "";
    private String specs = "";
    private String batch = "";
    private String grade = "";
    private String brand = "";
}
src/main/java/com/zy/asrs/mapper/LocDetlMapper.java
@@ -37,6 +37,8 @@
    @Select("SELECT ld.loc_no FROM asr_loc_detl ld LEFT JOIN asr_loc_mast lm ON ld.loc_no = lm.loc_no WHERE (1 = 1 AND ld.matnr = #{matnr} AND lm.bay1 >= 10 AND lm.bay1 <=20 AND (lm.row1 >= #{start} AND lm.row1 <= #{end})  AND lm.loc_sts = 'F' AND DateDiff(dd, ld.appe_time, getdate()) = 0) ORDER BY ld.appe_time ASC")
    List<String> selectSameDetlToday(@Param("matnr") String matnr, @Param("start") Integer start, @Param("end") Integer end);
    List<String> getSameDetlList(@Param("matnr") String matnr);
    List<LocDetl> getStockStatis(Map<String, Object> map);
    Integer getStockStatisCount(Map<String, Object> map);
src/main/java/com/zy/asrs/mapper/WaitPakinMapper.java
@@ -9,4 +9,6 @@
@Repository
public interface WaitPakinMapper extends BaseMapper<WaitPakin> {
    int updateIoStatus(String ioStatus, String locNo, String zpallet);
}
src/main/java/com/zy/asrs/service/LocDetlService.java
@@ -32,6 +32,11 @@
     */
    List<String> getSameDetlToday(String matnr, Integer start, Integer end);
    /**
     * 获取相同规格货物
     */
    List<String> getSameDetlList(String matnr);
    Page<LocDetl> getStockStatis(Page<LocDetl> page);
    Double getSumAnfme(String matnr);
src/main/java/com/zy/asrs/service/WaitPakinService.java
@@ -5,4 +5,6 @@
public interface WaitPakinService extends IService<WaitPakin> {
    boolean updateIoStatus(String ioStatus, String locNo, String zpallet);
}
src/main/java/com/zy/asrs/service/WorkService.java
@@ -82,9 +82,4 @@
     */
    StartupDto createWaitPainWrkMastStart(List<WaitPakin> list, Long userId);
    /**
     * 通知档手动生成任务
     */
    String dealPreHaveStart(Integer wrkNo, Long userId);
}
src/main/java/com/zy/asrs/service/impl/LocDetlServiceImpl.java
@@ -8,6 +8,7 @@
import com.zy.asrs.service.LocDetlService;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -48,6 +49,10 @@
        return this.baseMapper.selectSameDetlToday(matnr, start, end);
    }
    @Override
    public List<String> getSameDetlList(String matnr) {
        return this.baseMapper.getSameDetlList(matnr);
    }
    @Override
    public Page<LocDetl> getStockStatis(Page<LocDetl> page) {
src/main/java/com/zy/asrs/service/impl/WaitPakinServiceImpl.java
@@ -9,4 +9,9 @@
@Service("waitPakinService")
public class WaitPakinServiceImpl extends ServiceImpl<WaitPakinMapper, WaitPakin> implements WaitPakinService {
    @Override
    public boolean updateIoStatus(String ioStatus, String locNo, String zpallet) {
        return this.baseMapper.updateIoStatus(ioStatus, locNo, zpallet) > 0;
    }
}
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
@@ -12,6 +12,7 @@
import com.zy.asrs.entity.param.FullStoreParam;
import com.zy.asrs.entity.param.LocDetlAdjustParam;
import com.zy.asrs.entity.param.StockOutParam;
import com.zy.asrs.entity.result.FindLocNoAttributeVo;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.*;
@@ -91,7 +92,11 @@
        // 检索库位
        LocTypeDto locTypeDto = new LocTypeDto(sourceStaNo);
        List<String> matnrs = param.getList().stream().map(FullStoreParam.MatCodeStore::getMatnr).distinct().collect(Collectors.toList());
        StartupDto dto = commonService.getLocNo(DEFAULT_ROW_NO_TYPE, 1, param.getDevpNo(), matnrs, locTypeDto, 0);
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
        findLocNoAttributeVo.setMatnr(matnrs.get(0));
        StartupDto dto = commonService.getLocNo(DEFAULT_ROW_NO_TYPE, 1, findLocNoAttributeVo, locTypeDto, param.getBarcode());
        // 生成工作号
        int workNo = dto.getWorkNo();
        // 生成工作档
@@ -381,7 +386,10 @@
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
        // 检索库位
        LocTypeDto locTypeDto = new LocTypeDto(sourceStaNo);
        StartupDto dto = commonService.getLocNo(DEFAULT_ROW_NO_TYPE, 10, devpNo, null, locTypeDto, 0);
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
        StartupDto dto = commonService.getLocNo(DEFAULT_ROW_NO_TYPE, 10, findLocNoAttributeVo, locTypeDto, "");
        int workNo = dto.getWorkNo();
        Date now = new Date();
        // 生成工作档
@@ -966,101 +974,6 @@
        LocTypeDto locTypeDto = new LocTypeDto();
        locTypeDto.setLocType1((short) 1);
        return null;
    }
    @Override
    @Transactional
    public String dealPreHaveStart(Integer wrkNo, Long userId) {
        WrkMast wrkMast = wrkMastService.selectById(wrkNo);
        if (wrkMast == null) {
            throw new CoolException("任务已失效");
        }
        String locNo = wrkMast.getLocNo();
        LocMast locMast = locMastService.selectById(locNo);
        assert locMast != null;
        RowLastno rowLastno = rowLastnoService.findBySection(locMast.getRow1());
        assert rowLastno != null;
        // 目标库位
        LocMast targetLoc = null;
        for (int curRow = rowLastno.getsRow(); curRow<=rowLastno.geteRow(); curRow++) {
            if (Utils.isShallowLoc(slaveProperties, curRow)) {
                Integer deepRow = Utils.getDeepRow(slaveProperties, curRow);
                targetLoc = locMastService.queryFreeLocMast(deepRow, locMast.getLocType1());
                // 因库位移转、需预留空库位
                if (!locMastService.checkEmptyCount(targetLoc)) {
                    continue;
                }
            }
            if (Cools.isEmpty(targetLoc)) {
                targetLoc = locMastService.queryFreeLocMast(curRow, locMast.getLocType1());
                // 因库位移转、需预留空库位
                if (!locMastService.checkEmptyCount(targetLoc)) {
                    continue;
                }
                // 目标库位 ===>> 浅库位, 则校验其深库位是否为 F D X
                if (null != targetLoc && Utils.isShallowLoc(slaveProperties, targetLoc.getLocNo())) {
                    LocMast deepLoc = locMastService.selectById(Utils.getDeepLoc(slaveProperties, targetLoc.getLocNo()));
                    if (!deepLoc.getLocSts().equals("F") && !deepLoc.getLocSts().equals("D") && !deepLoc.getLocSts().equals("X")) {
                        continue;
                    }
                }
                // 目标库位 ===>> 深库位, 则校验其浅库位是否为 O
                if (null != targetLoc && Utils.isDeepLoc(slaveProperties, targetLoc.getLocNo())) {
                    LocMast shallowLoc = locMastService.selectById(Utils.getShallowLoc(slaveProperties, targetLoc.getLocNo()));
                    if (!shallowLoc.getLocSts().equals("O")) {
                        continue;
                    }
                }
            }
            if (!Cools.isEmpty(targetLoc)) {
                break;
            }
        }
        if (targetLoc == null) {
            throw new CoolException("操作失败,当前仓库找不到空库位");
        }
        Date now = new Date();
        // 修改工作档
        StaDesc staDesc = staDescService.queryCrnStn(targetLoc.getCrnNo());
        if (Cools.isEmpty(staDesc)) {
            throw new CoolException("入库路径不存在");
        }
        wrkMast.setWrkSts(2L);
        wrkMast.setLocNo(targetLoc.getLocNo());
        wrkMast.setStaNo(staDesc.getCrnStn());
        wrkMast.setCrnNo(targetLoc.getCrnNo());
        wrkMast.setModiTime(now);
        wrkMast.setModiUser(userId);
        wrkMast.setPreHave("N");
        if (!wrkMastService.updateById(wrkMast)) {
            throw new CoolException("修改工作档失败");
        }
        // 修改库位状态 O ===>>> S
        if (targetLoc.getLocSts().equals("O")){
            targetLoc.setLocSts("S"); // S.入库预约
            targetLoc.setModiUser(userId);
            targetLoc.setModiTime(now);
            if (!locMastService.updateById(targetLoc)){
                throw new CoolException("改变库位状态失败");
            }
        } else {
            throw new CoolException(targetLoc.getLocNo()+"目标库位已被占用");
        }
        // 禁用异常库位
//        locMast.setLocSts("X"); // X.禁用
//        locMast.setModiUser(userId);
//        locMast.setModiTime(now);
//        if (!locMastService.updateById(locMast)){
//            throw new CoolException("改变库位状态失败");
//        }
        return targetLoc.getLocNo();
    }
}
src/main/java/com/zy/asrs/task/CheckDeepScheduler.java
File was deleted
src/main/java/com/zy/asrs/task/ErrorStockScheduler.java
File was deleted
src/main/java/com/zy/asrs/task/PlcLogScheduler.java
File was deleted
src/main/java/com/zy/asrs/task/handler/CheckDeepHandler.java
File was deleted
src/main/java/com/zy/asrs/task/handler/ErrorStockHandler.java
File was deleted
src/main/java/com/zy/asrs/task/handler/PlcLogHandler.java
File was deleted
src/main/java/com/zy/asrs/utils/Utils.java
@@ -6,6 +6,7 @@
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
@@ -37,103 +38,6 @@
    }
    /**
     * 判断是否为深库位
     */
    public static boolean isDeepLoc(SlaveProperties slaveProperties, String locNo){
        if (slaveProperties.isDoubleDeep()) {
            int row = getRow(locNo);
            return slaveProperties.getDoubleLocs().contains(row);
        } else {
            return false;
        }
    }
    /**
     * 判断是否为深库位
     */
    public static boolean isDeepLoc(SlaveProperties slaveProperties, Integer row){
        if (slaveProperties.isDoubleDeep()) {
            return slaveProperties.getDoubleLocs().contains(row);
        } else {
            return false;
        }
    }
    /**
     * 判断是否为浅库位
     */
    public static boolean isShallowLoc(SlaveProperties slaveProperties, String locNo){
        if (slaveProperties.isDoubleDeep()) {
            int row = getRow(locNo);
            return !slaveProperties.getDoubleLocs().contains(row);
        } else {
            return false;
        }
    }
    /**
     * 判断是否为浅库位
     */
    public static boolean isShallowLoc(SlaveProperties slaveProperties, Integer row){
        if (slaveProperties.isDoubleDeep()) {
            return !slaveProperties.getDoubleLocs().contains(row);
        } else {
            return false;
        }
    }
    /**
     * 获取 深库位对应的浅库位号
     */
    public static String getShallowLoc(SlaveProperties slaveProperties, String deepLoc) {
        int row = getRow(deepLoc);
        int remainder = (int) Arith.remainder(row, slaveProperties.getGroupCount());
        int shallowRow = remainder == 1 ? (row + 1) : (row - 1);
        return zerofill(String.valueOf(shallowRow), 2) + deepLoc.substring(2);
    }
    /**
     * 获取 深库位排对应的浅库位排
     */
    public static Integer getShallowRow(SlaveProperties slaveProperties, Integer deepRow) {
        int remainder = (int) Arith.remainder(deepRow, slaveProperties.getGroupCount());
        return remainder == 1 ? (deepRow + 1) : (deepRow - 1);
    }
    /**
     * 获取 浅库位对应的深库位号
     */
    public static String getDeepLoc(SlaveProperties slaveProperties, String shallowLoc) {
        int row = getRow(shallowLoc);
        int remainder = (int) Arith.remainder(row, slaveProperties.getGroupCount());
        int targetRow;
        if (remainder == 2) {
            targetRow = row - 1;
        } else if (remainder == 3) {
            targetRow = row + 1;
        } else {
            throw new RuntimeException(shallowLoc + "不是浅库位,系统繁忙");
        }
        return zerofill(String.valueOf(targetRow), 2) + shallowLoc.substring(2);
    }
    /**
     * 获取 浅库位排对应的深库位排
     */
    public static Integer getDeepRow(SlaveProperties slaveProperties, Integer shallowRow) {
        int remainder = (int) Arith.remainder(shallowRow, slaveProperties.getGroupCount());
        int targetRow;
        if (remainder == 2) {
            targetRow = shallowRow - 1;
        } else if (remainder == 3) {
            targetRow = shallowRow + 1;
        } else {
            throw new RuntimeException(shallowRow + "不是浅库位排,系统繁忙");
        }
        return targetRow;
    }
    /**
     * 通过库位号获取 排
     */
    public static int getRow(String locNo) {
@@ -144,32 +48,51 @@
    }
    /**
     * 当检索到双深库位的浅库位时,如果深库位无货,则放入对应的深库位
     * 通过库位号获取 列
     */
    public static void toDeepIfEmptyByShallow(String shallowLoc) {
        int row = getRow(shallowLoc);
        int remainder = (int) Arith.remainder(row, 4);
        int targetRow = 0;
        if (remainder == 2) {
            targetRow = row - 1;
        } else if (remainder == 3) {
            targetRow = row + 1;
        } else {
            throw new RuntimeException(shallowLoc + "不是浅库位,系统繁忙");
    public static int getBay(String locNo) {
        if (!Cools.isEmpty(locNo)) {
            return Integer.parseInt(locNo.substring(2, 5));
        }
        String targetLoc = zerofill(String.valueOf(targetRow), 2) + shallowLoc.substring(2);
        throw new RuntimeException("库位解析异常");
    }
    public static void main(String[] args) {
        SlaveProperties slaveProperties = new SlaveProperties();
        slaveProperties.setDoubleDeep(true);
        List<Integer> list = new ArrayList<>();
        list.add(1);list.add(4);list.add(5);list.add(8);list.add(9);list.add(12);
        slaveProperties.setDoubleLocs(list);
        slaveProperties.setGroupCount(4);
        Integer deepRow = getDeepRow(slaveProperties, 6);
        System.out.println(deepRow);
    /**
     * 通过库位号获取 层
     */
    public static int getLev(String locNo) {
        if (!Cools.isEmpty(locNo)) {
            return Integer.parseInt(locNo.substring(5, 7));
        }
        throw new RuntimeException("库位解析异常");
    }
    public static String getLocNo(Number row, Number bay, Number lev) {
        return zerofill(String.valueOf(row), 2) + zerofill(String.valueOf(bay), 3) + zerofill(String.valueOf(lev), 2);
    }
    public static List<Integer> getLocRowGroupAsc(SlaveProperties slaveProperties, Integer row) {
        List<List<Integer>> locGroupAsc = slaveProperties.getLocGroupAsc();
        for (List<Integer> group : locGroupAsc) {
            if (group.contains(row)) {
                List<Integer> copy = new ArrayList<>(group);
                return copy;
            }
        }
        throw new RuntimeException(row + "排,未定义库位组");
    }
    public static List<Integer> getLocRowGroupDesc(SlaveProperties slaveProperties, Integer row) {
        List<List<Integer>> locGroupAsc = slaveProperties.getLocGroupAsc();
        for (List<Integer> group : locGroupAsc) {
            if (group.contains(row)) {
                List<Integer> copy = new ArrayList<>(group);
                Collections.reverse(copy);
                return copy;
            }
        }
        throw new RuntimeException(row + "排,未定义库位组");
    }
}
src/main/java/com/zy/common/properties/SlaveProperties.java
@@ -15,10 +15,6 @@
@ConfigurationProperties(prefix = "wcs-slave")
public class SlaveProperties {
    private boolean doubleDeep;
    private List<Integer> doubleLocs = new ArrayList<>();
    private int groupCount;
    private List<List<Integer>> locGroupAsc = new ArrayList<>();
}
src/main/java/com/zy/common/service/CommonService.java
@@ -1,26 +1,21 @@
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.List;
/**
@@ -90,405 +85,196 @@
        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 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());
//        }
        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;
        // 目标库位
        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.setCrnNo(locMast.getCrnNo());
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setStaNo(staNo.getDevNo());
        startupDto.setLocNo(locNo);
        return startupDto;
    }
    //搜索满托盘库位
    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.getLocRowGroupDesc(slaveProperties, Utils.getRow(locNo));
            for (Integer row : locRowGroupDesc) {
                String deepLocNo = Utils.getLocNo(row, Utils.getBay(locNo), Utils.getLev(locNo));
                LocMast deepLoc = locMastService.selectById(deepLocNo);
                if (deepLoc.getLocSts().equals("F")) {
                    continue;
                } else if (deepLoc.getLocSts().equals("O")) {
                    targetLocMast = deepLoc;
                    break;
                }else {
                    break;
                }
            }
        }
        if(targetLocMast == null) {
            //相近物料匹配失败,搜索可用空库位组
            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                    .eq("loc_sts", "O")
                    .orderBy("lev1", true)
                    .orderBy("bay1", true));
            for (LocMast locMast : locMasts) {
                String locNo = locMast.getLocNo();
                //获取通道组
                List<Integer> locRowGroupDesc = Utils.getLocRowGroupDesc(slaveProperties, Utils.getRow(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.getLocSts().equals("O")) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    Integer firstRow = locRowGroupDesc.get(0);
                    String deepLocNo = Utils.getLocNo(firstRow, Utils.getBay(locNo), Utils.getLev(locNo));
                    LocMast deepLoc = locMastService.selectById(deepLocNo);
                    targetLocMast = deepLoc;
                    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.getLocRowGroupDesc(slaveProperties, Utils.getRow(locNo));
            for (Integer row : locRowGroupDesc) {
                String deepLocNo = Utils.getLocNo(row, Utils.getBay(locNo), Utils.getLev(locNo));
                LocMast deepLoc = locMastService.selectById(deepLocNo);
                if (deepLoc.getLocSts().equals("F")) {
                    continue;
                } else if (deepLoc.getLocSts().equals("O")) {
                    targetLocMast = deepLoc;
                    break;
                }else {
                    break;
                }
            }
        }
        if(targetLocMast == null) {
            //相近物料匹配失败,搜索可用空库位组
            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                    .eq("loc_sts", "O")
                    .orderBy("lev1", true)
                    .orderBy("bay1", true));
            for (LocMast locMast : locMasts) {
                String locNo = locMast.getLocNo();
                //获取通道组
                List<Integer> locRowGroupDesc = Utils.getLocRowGroupDesc(slaveProperties, Utils.getRow(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.getLocSts().equals("O")) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    targetLocMast = locMast;
                    break;
                }
            }
        }
        return targetLocMast;
    }
    public static String zerofill(String msg, Integer count) {
        if (msg.length() == count) {
@@ -502,158 +288,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;
    }
}
src/main/java/com/zy/common/web/WcsController.java
@@ -6,6 +6,7 @@
import com.core.common.R;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.result.FindLocNoAttributeVo;
import com.zy.asrs.entity.result.StorageResult;
import com.zy.asrs.service.*;
import com.zy.common.CodeRes;
@@ -46,131 +47,58 @@
    private  LocDetlService locDetlService;
    @Autowired
    private  BasCrnpService basCrnpService;
    @PostMapping("/pakin/loc/returnWarehouse")
    @ResponseBody
    public synchronized StorageResult returnWarehouse(@RequestBody(required = false) SearchLocParam param) {
        StorageResult storageResult=new StorageResult();
        if (Cools.isEmpty(param.getTaskNo())) {
            storageResult.setReturnStatus(1);
            storageResult.setErrorMessage("传入工作号为空");
            return storageResult;
        }
        WrkMast wrkMast =wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                .eq("wrk_no",param.getTaskNo())
                .in("io_type",103,107));
        WrkMast wrkMast537 =wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                .eq("wrk_no",param.getTaskNo())
                .in("io_type",53,57));
        if (Cools.isEmpty(wrkMast)&&Cools.isEmpty(wrkMast537)){
            storageResult.setReturnStatus(1);
            storageResult.setErrorMessage("没有找到盘点拣料任务---------"+param.getTaskNo());
            return storageResult;
        }
        SearchLocParam searchLocParam = new SearchLocParam();
        searchLocParam.setBoxNo(Cools.isEmpty(wrkMast)?wrkMast537.getBarcode() : wrkMast.getBarcode());
        searchLocParam.setWcsIoType(1);//满板
        searchLocParam.setWcsSourceStaNo(Cools.isEmpty(wrkMast)?wrkMast537.getSourceStaNo() : wrkMast.getStaNo());
        searchLocParam.setWcsStatus(0);
        return getLocNo(searchLocParam);
    }
    @PostMapping("/pakin/loc/v1")
    @ResponseBody
    public synchronized StorageResult getLocNo(@RequestBody(required = false) SearchLocParam param) {
        StorageResult storageResult=new StorageResult();
    public synchronized R getLocNo(@RequestBody(required = false) SearchLocParam param) {
        log.info("收到WCS入库接口请求====>>入参:{}", param);
        if (Cools.isEmpty(param.getWcsIoType())) {
            storageResult.setReturnStatus(1);
            storageResult.setErrorMessage("入出库类型不能为空");
            return storageResult;
        if (Cools.isEmpty(param.getIoType())) {
            return R.error("入出库类型不能为空");
        }
        if (Cools.isEmpty(param.getWcsSourceStaNo())) {
            storageResult.setReturnStatus(1);
            storageResult.setErrorMessage("源站编号不能为空");
            return storageResult;
        if (Cools.isEmpty(param.getSourceStaNo())) {
            return R.error("源站编号不能为空");
        }
        BasDevp basDevp=basDevpService.selectOne(new EntityWrapper<BasDevp>().eq("dev_no",param.getWcsSourceStaNo()));
        //
        List<WrkMast> wrkMasts=wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("sta_no",param.getWcsSourceStaNo()).in("wrk_sts",11,12,13));
        if(!Cools.isEmpty(wrkMasts)){
            storageResult.setReturnStatus(1);
            storageResult.setErrorMessage("有出库任务禁止入库");
            basDevp.setArea("有出库任务禁止入库");
            basDevpService.updateById(basDevp);
            return storageResult;
        }
        int ioType = 0;
        List<WaitPakin> waitPakins = null;
        if (param.getWcsIoType() == 1) {
            //拣料和盘点入库
            WrkMast wrkMast1037 =wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                    .eq("barcode", param.getBoxNo())
                    .in("io_type",103,107));
            WrkMast wrkMast537 =wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                    .eq("barcode", param.getBoxNo())
                    .in("io_type",53,57));
            if (wrkMast537 != null) {
                StorageResult.Results results=new StorageResult.Results();
                results.setTaskNo(wrkMast537.getWrkNo());
                results.setShelfUnitId(wrkMast537.getLocNo()+"");
                storageResult.setResults(results);
                return storageResult;
        if (param.getIoType() == 1) {
            if (Cools.isEmpty(param.getBarcode())) {
                return R.error("条码不能为空");
            }
            if(Cools.isEmpty(wrkMast1037)) {
                if (Cools.isEmpty(param.getBoxNo())) {
                    storageResult.setReturnStatus(1);
                    storageResult.setErrorMessage("条码不能为空");
                    basDevp.setArea("条码不能为空");
                    basDevpService.updateById(basDevp);
                    return storageResult;
            waitPakins = waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("zpallet", param.getBarcode()));
            if (Cools.isEmpty(waitPakins)) {
                WrkMast wrkMast = wrkMastService.selectByBarcode(param.getBarcode());
                if (wrkMast != null && wrkMast.getIoType() == 103) {
                    return R.parse(CodeRes.PICK_600);
                }
                waitPakins = waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("zpallet", param.getBoxNo()));
                if (Cools.isEmpty(waitPakins)) {
                    WrkMast wrkMast = wrkMastService.selectByBarcode(param.getBoxNo());
                    if (wrkMast != null && wrkMast.getIoType() == 103) {
                        storageResult.setReturnStatus(1);
                        storageResult.setErrorMessage(CodeRes.PICK_600);
                        basDevp.setArea(CodeRes.PICK_600);
                        basDevpService.updateById(basDevp);
                        return storageResult;
                    }
                    storageResult.setReturnStatus(1);
                    storageResult.setErrorMessage(CodeRes.NO_COMB_700);
                    basDevp.setArea(CodeRes.NO_COMB_700);
                    basDevpService.updateById(basDevp);
                    return storageResult;
                }
                int countLoc = locDetlService.selectCount(new EntityWrapper<LocDetl>().eq("zpallet", param.getBoxNo()));
                int countWrk = wrkDetlService.selectCount(new EntityWrapper<WrkDetl>().eq("zpallet", param.getBoxNo()));
                if (countLoc > 0 || countWrk > 0) {
                    storageResult.setReturnStatus(1);
                    storageResult.setErrorMessage(CodeRes.EXIST_500);
                    basDevp.setArea(CodeRes.NO_COMB_700);
                    basDevpService.updateById(basDevp);
                    return storageResult;
                }
            }else {
                ioType = wrkMast1037.getIoType();
                return R.parse(CodeRes.NO_COMB_700);
            }
            int countLoc = locDetlService.selectCount(new EntityWrapper<LocDetl>().eq("zpallet", param.getBarcode()));
            int countWrk = wrkDetlService.selectCount(new EntityWrapper<WrkDetl>().eq("zpallet", param.getBarcode()));
            if (countLoc > 0 || countWrk > 0) {
                return R.error(CodeRes.EXIST_500);
            }
        }
        if (Cools.isEmpty(param.getLocType1())) {
            return R.error("高低检测信号不能为空");
        }
        LocTypeDto locTypeDto = new LocTypeDto();
        locTypeDto.setLocType1(param.getLocType1());
        switch (param.getWcsIoType()) {
        StartupDto dto = null;
        switch (param.getIoType()) {
            case 1://满托盘入库
                assert waitPakins != null;
                storageResult = startupFullPutStore(param.getWcsSourceStaNo(), param.getBoxNo(), waitPakins,ioType);
                dto = startupFullPutStore(param.getSourceStaNo(), param.getBarcode(), locTypeDto, waitPakins);
                break;
            case 2://空托盘入库
                storageResult = emptyPlateIn(param.getWcsSourceStaNo(), param.getBoxNo());
            case 10://空托盘入库
                dto = emptyPlateIn(param.getSourceStaNo(), param.getBarcode());
                break;
            default:
                break;
        }
        log.info("WCS入库接口返参:{},托盘码:{}", storageResult, param.getBoxNo());
        return storageResult;
        log.info("WCS入库接口返参:{},托盘码:{}", dto, param.getBarcode());
        return R.ok().add(dto);
    }
@@ -178,144 +106,98 @@
     * 全板入库
     */
    @Transactional
    public StorageResult startupFullPutStore(Integer devpNo, String barcode, List<WaitPakin> waitPakins,Integer ioType) {
        BasDevp basDevp=basDevpService.selectOne(new EntityWrapper<BasDevp>().eq("dev_no",devpNo));
    public StartupDto startupFullPutStore(Integer devpNo, String barcode, LocTypeDto locTypeDto, List<WaitPakin> waitPakins) {
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
        // 检索库位
//        List<String> matnrs = waitPakins.stream().map(WaitPakin::getMatnr).distinct().collect(Collectors.toList());
//        List<String> batchs = waitPakins.stream().map(WaitPakin::getBatch).distinct().collect(Collectors.toList());
        WaitPakin waitPakin1 = waitPakins.get(0);
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
        findLocNoAttributeVo.setMatnr(waitPakin1.getMatnr());
        StorageResult storageResult=new StorageResult();
        Integer[] arr=arr();
        LocMast locMast1=new LocMast();
        Integer workNo = 0;
        //判断是否是拣料或者是盘点
        if(ioType==103||ioType==107) {
            WrkDetl wrkDetl=wrkDetlService.selectOne(new EntityWrapper<WrkDetl>().eq("zpallet", barcode));
            int type=Cools.isEmpty(wrkDetl.getBeBatch())?1:wrkDetl.getBeBatch();
            // 检索库位
            WaitPakin waitPakin1=new WaitPakin();
            waitPakin1.sync(wrkDetl);
            locMast1 =commonService.getLocNo2(waitPakin1,arr,0,type,1);
            if (locMast1 == null) {
                basDevp.setArea("未找到空库位");
                basDevpService.updateById(basDevp);
                throw new CoolException("未找到空库位");
        StartupDto dto = commonService.getLocNo(1, devpNo, findLocNoAttributeVo, locTypeDto, barcode);
        if (dto == null) {
            throw new CoolException("找不到空库位");
        }
        int workNo = dto.getWorkNo();
        Date now = new Date();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
        wrkMast.setWrkNo(workNo);
        wrkMast.setIoTime(new Date());
        wrkMast.setWrkSts(2L); // 工作状态:生成入库ID
        wrkMast.setIoType(1); // 入出库状态:1.入库
        wrkMast.setIoPri(30D); // 优先级
        wrkMast.setCrnNo(dto.getCrnNo());
        wrkMast.setSourceStaNo(dto.getSourceStaNo());
        wrkMast.setStaNo(dto.getStaNo());
        wrkMast.setLocNo(dto.getLocNo());
        wrkMast.setBarcode(barcode); // 托盘码
        wrkMast.setFullPlt("Y"); // 满板:Y
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setEmptyMk("N"); // 空板
        wrkMast.setLinkMis("Y");
        wrkMast.setCtnType(sourceStaNo.getCtnType()); // 容器类型
        // 操作人员数据
        wrkMast.setAppeTime(now);
        wrkMast.setModiTime(now);
        wrkMast.setModiUser(waitPakin1.getModiUser());
        wrkMast.setAppeUser(waitPakin1.getAppeUser());
        boolean res = wrkMastService.insert(wrkMast);
        if (!res) {
            throw new CoolException("保存工作档失败");
        }
        // 生成工作档明细
        waitPakins.forEach(waitPakin -> {
            WrkDetl wrkDetl = new WrkDetl();
            wrkDetl.sync(waitPakin);
            wrkDetl.setWrkNo(wrkMast.getWrkNo());
            wrkDetl.setIoTime(wrkMast.getIoTime());
            wrkDetl.setAppeTime(now);
            wrkDetl.setModiTime(now);
            if (!wrkDetlService.insert(wrkDetl)) {
                throw new CoolException("保存工作明细失败");
            }
            //更新货物所在库位的深浅号
            wrkDetl.setSource(locMast1.getLocAttribute());
            wrkDetlService.update(wrkDetl,new EntityWrapper<WrkDetl>().eq("wrk_no", wrkDetl.getWrkNo()));
            WrkMast wrkMast=wrkMastService.selectByBarcode(barcode);
            workNo = wrkMast.getWrkNo();
            int mbz=basDevp.getDevNo()*10+Integer.valueOf(wrkMast.getSourceLocNo().substring(6));
            String ykw=wrkMast.getLocNo();
            wrkMast.setIoType(ioType-50);
            wrkMast.setWrkSts(1L);//入库
            wrkMast.setModiTime(new Date());
            wrkMast.setSourceStaNo(basDevp.getDevNo()); // 源站
            wrkMast.setStaNo(mbz); // 目标站
            wrkMast.setLocNo(locMast1.getLocNo()); // 目标库位 = 出库时的源库位
            wrkMast.setSourceLocNo(ykw); // 源库位
            wrkMastService.updateById(wrkMast);
        }else{
            int type=Cools.isEmpty(waitPakins.get(0).getBeBatch())?1:waitPakins.get(0).getBeBatch();
            // 检索库位
            locMast1 =commonService.getLocNo2(waitPakins.get(0),arr,0,type,1);
            if (locMast1 == null) {
                basDevp.setArea("未找到空库位");
                basDevpService.updateById(basDevp);
                throw new CoolException("未找到空库位");
            }
            int mbz=devpNo*10+Integer.valueOf(locMast1.getLocNo().substring(6));
            //正常入库
            workNo = commonService.getWorkNo(0);
            Date now = new Date();
            // 生成工作档
            WrkMast wrkMast = new WrkMast();
            wrkMast.setWrkNo(workNo);
            wrkMast.setIoTime(new Date());
            wrkMast.setWrkSts(2L); // 工作状态:生成入库ID
            wrkMast.setIoType(1); // 入出库状态:1.入库
            wrkMast.setIoPri(13D); // 优先级
            wrkMast.setSourceStaNo(devpNo);
            wrkMast.setStaNo(mbz);
            wrkMast.setLocNo(locMast1.getLocNo());
            wrkMast.setBarcode(barcode); // 托盘码
            wrkMast.setFullPlt("Y"); // 满板:Y
            wrkMast.setPicking("N"); // 拣料
            wrkMast.setExitMk("N"); // 退出
            wrkMast.setEmptyMk("N"); // 空板
            wrkMast.setLinkMis("Y");
            wrkMast.setCtnType(1); // 容器类型
            // 操作人员数据
            wrkMast.setAppeTime(now);
            wrkMast.setModiTime(now);
            boolean res = wrkMastService.insert(wrkMast);
            if (!res) {
                basDevp.setArea("保存工作档失败");
                basDevpService.updateById(basDevp);
                throw new CoolException("保存工作档失败");
            }
            // 生成工作档明细
            int source = locMast1.getLocAttribute();
            waitPakins.forEach(waitPakin -> {
                WrkDetl wrkDetl = new WrkDetl();
                wrkDetl.sync(waitPakin);
                wrkDetl.setWrkNo(wrkMast.getWrkNo());
                wrkDetl.setIoTime(wrkMast.getIoTime());
                wrkDetl.setAppeTime(now);
                wrkDetl.setModiTime(now);
                wrkDetl.setSource(source);
                if (!wrkDetlService.insert(wrkDetl)) {
                    basDevp.setArea("保存工作明细失败");
                    basDevpService.updateById(basDevp);
                    throw new CoolException("保存工作明细失败");
                }
            });
            // 更新入库通知档 ioStatus ===>> Y
            Wrapper<WaitPakin> wrapper = new EntityWrapper<WaitPakin>()
                    .eq("zpallet", barcode);
            WaitPakin setParam = new WaitPakin();
            setParam.setLocNo(locMast1.getLocNo());
            setParam.setIoStatus("Y");
            setParam.setModiTime(now);
            if (!waitPakinService.update(setParam, wrapper)) {
                basDevp.setArea("更新通知档失败");
                basDevpService.updateById(basDevp);
                throw new CoolException("更新通知档失败");
            }
        });
        // 更新入库通知档 ioStatus ===>> Y
        if (!waitPakinService.updateIoStatus("Y", dto.getLocNo(), barcode)) {
            throw new CoolException("更新通知档失败");
        }
        // 更新源站点信息
        sourceStaNo.setWrkNo(workNo);
        sourceStaNo.setModiTime(now);
        if (!basDevpService.updateById(sourceStaNo)) {
            throw new CoolException("更新源站失败");
        }
        // 更新目标库位状态
        LocMast locMast = locMastService.selectById(locMast1.getLocNo());
        if (locMast.getLocSts().equals("O")){
        LocMast locMast = locMastService.selectById(dto.getLocNo());
        if (locMast.getLocSts().equals("O")) {
            locMast.setLocSts("S"); // S.入库预约
            locMast.setModiTime(new Date());
            if (!locMastService.updateById(locMast)){
                basDevp.setArea("改变库位状态失败");
                basDevpService.updateById(basDevp);
            locMast.setModiTime(now);
            if (!locMastService.updateById(locMast)) {
                throw new CoolException("改变库位状态失败");
            }
        } else {
            basDevp.setArea(locMast1.getLocNo()+"目标库位已被占用");
            basDevpService.updateById(basDevp);
            throw new CoolException(locMast1.getLocNo()+"目标库位已被占用");
            throw new CoolException(dto.getLocNo() + "目标库位已被占用");
        }
        StorageResult.Results results=new StorageResult.Results();
        results.setTaskNo(workNo);
        results.setShelfUnitId(locMast1.getLocNo());
        results.setBarcode(barcode);
        storageResult.setResults(results);
        return storageResult;
        return dto;
    }
    @Transactional
    public StorageResult emptyPlateIn(Integer devpNo, String barcode) {
        StorageResult storageResult=new StorageResult();
    public StartupDto emptyPlateIn(Integer devpNo, String barcode) {
        // 检索库位
        Integer[] arr=arr();
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
        LocTypeDto locTypeDto = new LocTypeDto();
        // 检索库位
        LocMast locMast1 =commonService.getLocNo2(null,arr,0,1,2);
        StartupDto dto = commonService.getLocNo(1, devpNo, findLocNoAttributeVo, locTypeDto, barcode);
        String locNo = dto.getLocNo();
        int workNo = commonService.getWorkNo(0);
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
@@ -325,7 +207,7 @@
        wrkMast.setIoType(10); // 入出库状态:10.空板入库
        wrkMast.setIoPri(13D); // 优先级
        wrkMast.setSourceStaNo(devpNo);
        wrkMast.setLocNo(locMast1.getLocNo());
        wrkMast.setLocNo(locNo);
        wrkMast.setFullPlt("N"); // 满板
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
@@ -341,7 +223,7 @@
            throw new CoolException("保存工作档失败");
        }
        // 更新目标库位状态
        LocMast locMast = locMastService.selectById(locMast1.getLocNo());
        LocMast locMast = locMastService.selectById(locNo);
        if (locMast.getLocSts().equals("O")){
            locMast.setLocSts("S"); // S.入库预约
            locMast.setModiTime(new Date());
@@ -349,13 +231,9 @@
                throw new CoolException("改变库位状态失败");
            }
        } else {
            throw new CoolException(locMast1.getLocNo()+"目标库位已被占用");
            throw new CoolException(locNo + "目标库位已被占用");
        }
        StorageResult.Results results=new StorageResult.Results();
        results.setTaskNo(workNo);
        results.setShelfUnitId(locMast1.getLocNo());
        storageResult.setResults(results);
        return storageResult;
        return dto;
    }
    @Transactional
src/main/java/com/zy/common/web/param/SearchLocParam.java
@@ -1,6 +1,5 @@
package com.zy.common.web.param;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
/**
@@ -9,25 +8,13 @@
@Data
public class SearchLocParam {
    @JSONField(name = "taskNo")
    private Integer taskNo;
    private Integer ioType;
    //托盘码
    @JSONField(name = "BoxNo")
    private String boxNo;
    //执行状态   0:成功 1:失败
    @JSONField(name = "WCSStatus")
    private Integer wcsStatus=0;
    //错误信息   具体的错误信息(超高,超重等)
    @JSONField(name = "WCSErrorMessage")
    private String wcsErrorMessage="";
    private Integer sourceStaNo;
    //源站点
    @JSONField(name = "WCSSourceStaNo")
    private Integer wcsSourceStaNo;
    private String barcode;
    //空板满板 1.满板 2.空板
    @JSONField(name = "WCSIoType")
    private Integer wcsIoType;
    // 库位规格( 0:未知, 1:低库位, 2:高库位)
    private Short locType1;
}
src/main/resources/application.yml
@@ -51,12 +51,7 @@
# 下位机配置
wcs-slave:
  # 双深
  doubleDeep: true
  # 双深库位排号
  doubleLocs: 1,4,5,8
  # 一个堆垛机负责的货架排数
  groupCount: 4
  locGroupAsc: [[5,4,3,2,1],[7],[8],[10,11],[12],[14],[15],[17]]
#wcs对接
wcs:
@@ -65,7 +60,6 @@
    URL: http://127.0.0.1:9092/wcs
    #出库移库任务下发
    outboundTaskSend: open/outboundTaskSend
    deviceStatus : open/deviceStatus
#erp对接
src/main/resources/mapper/LocDetlMapper.xml
@@ -140,6 +140,15 @@
        <include refid="stockOutCondition"></include>
    </select>
    <select id="getSameDetlList" resultType="java.lang.String">
        SELECT ld.loc_no FROM asr_loc_detl ld
        LEFT JOIN asr_loc_mast lm ON ld.loc_no = lm.loc_no
        WHERE 1 = 1
        AND ld.matnr = #{matnr}
        AND lm.loc_sts = 'F'
        ORDER BY ld.appe_time ASC
    </select>
    <select id="getStockStatis" resultType="com.zy.asrs.entity.LocDetl">
        select * from
        (
src/main/resources/mapper/WaitPakinMapper.xml
@@ -49,4 +49,11 @@
        <result column="memo" property="memo" />
    </resultMap>
    <update id="updateIoStatus">
        update cust_wait_pakin
        set io_status = #{ioStatus}
          ,loc_no = #{locNo}
        where zpallet = #{zpallet}
    </update>
</mapper>