自动化立体仓库 - WMS系统
dubin
2 天以前 6c8588d5f7f0de7e9489426c350472bf911a4933
towcs
3个文件已添加
22个文件已修改
735 ■■■■■ 已修改文件
src/main/java/com/zy/asrs/mapper/LocDetlMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/LocMastMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/LocDetlService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/LocMastService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/WrkMastService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/LocDetlServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/LocMastServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WrkMastServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/GetEquipmentStatus.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/OutWorkScheduler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/CreateOutTask.java 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/utils/Utils.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/CodeBuilder.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/StartupDto.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/WmsDevDto.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/service/CommonService.java 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/WcsController.java 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/param/NotifyDto.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/param/SearchLocParam.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/LocDetlMapper.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/LocMastMapper.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkMastMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/LocDetlMapper.java
@@ -39,6 +39,8 @@
    List<String> getSameDetlList(@Param("matnr") String matnr);
    List<String> getSameDetlListToWmsDev(@Param("matnr") String matnr,@Param("rows") int[] rows);
    List<LocDetl> getStockStatis(Map<String, Object> map);
    Integer getStockStatisCount(Map<String, Object> map);
src/main/java/com/zy/asrs/mapper/LocMastMapper.java
@@ -17,4 +17,6 @@
    List<String> queryGroupEmptyStock(Integer lev);
    List<Integer> getLevList();
    List<LocMast> selectLoc(@Param("rows") int[] rows);
}
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.zy.asrs.entity.WrkMast;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@@ -16,4 +17,5 @@
    List<WrkMast> selectToBeHistoryData();
    WrkMast selectByTaskNo(@Param("taskNo") String taskNo);
}
src/main/java/com/zy/asrs/service/LocDetlService.java
@@ -37,6 +37,11 @@
     */
    List<String> getSameDetlList(String matnr);
    /**
     * 获取相同规格货物
     */
    List<String> getSameDetlListToWmsDev(String matnr,int[] rows);
    Page<LocDetl> getStockStatis(Page<LocDetl> page);
    Double getSumAnfme(String matnr);
src/main/java/com/zy/asrs/service/LocMastService.java
@@ -16,4 +16,6 @@
    List<String> queryGroupEmptyStock(String sourceLocNo);
    List<Integer> getLevList();
    List<LocMast> selectLoc(int[] rows);
}
src/main/java/com/zy/asrs/service/WrkMastService.java
@@ -21,4 +21,6 @@
     * @return
     */
    int getStoreCount(Integer crnNo);
    WrkMast selectByTaskNo(String taskNo);
}
src/main/java/com/zy/asrs/service/impl/LocDetlServiceImpl.java
@@ -55,6 +55,11 @@
    }
    @Override
    public List<String> getSameDetlListToWmsDev(String matnr,int[] rows) {
        return this.baseMapper.getSameDetlListToWmsDev(matnr,rows);
    }
    @Override
    public Page<LocDetl> getStockStatis(Page<LocDetl> page) {
        page.setRecords(baseMapper.getStockStatis(page.getCondition()));
        page.setTotal(baseMapper.getStockStatisCount(page.getCondition()));
src/main/java/com/zy/asrs/service/impl/LocMastServiceImpl.java
@@ -31,4 +31,9 @@
    public List<Integer> getLevList() {
        return this.baseMapper.getLevList();
    }
    @Override
    public List<LocMast> selectLoc(int[] rows) {
        return this.baseMapper.selectLoc(rows);
    }
}
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
@@ -98,7 +98,7 @@
        StartupDto dto = commonService.getLocNo(DEFAULT_ROW_NO_TYPE, 1, findLocNoAttributeVo, locTypeDto, param.getBarcode());
        // 生成工作号
        int workNo = dto.getWorkNo();
        int workNo = dto.getTaskNo();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
        wrkMast.setWrkNo(workNo);
@@ -385,7 +385,7 @@
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
        StartupDto dto = commonService.getLocNo(DEFAULT_ROW_NO_TYPE, 10, findLocNoAttributeVo, locTypeDto, "");
        int workNo = dto.getWorkNo();
        int workNo = dto.getTaskNo();
        Date now = new Date();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
src/main/java/com/zy/asrs/service/impl/WrkMastServiceImpl.java
@@ -45,4 +45,9 @@
                .last(" and (wrk_sts in (1,2) or (wrk_sts=3 and wrk_no in (select wrk_no from asr_bas_devp)))"));
    }
    @Override
    public WrkMast selectByTaskNo(String taskNo) {
        return this.baseMapper.selectByTaskNo(taskNo);
    }
}
src/main/java/com/zy/asrs/task/GetEquipmentStatus.java
@@ -37,7 +37,7 @@
    @Autowired
    private BasDevpService basDevpService;
    @Scheduled(cron = "0/3 * * * * ? ")
//    @Scheduled(cron = "0/3 * * * * ? ")
    private void execute() {
        //获取设备信息
        String response ="";
src/main/java/com/zy/asrs/task/OutWorkScheduler.java
@@ -26,7 +26,7 @@
    /**
     * 出库任务下发
     */
    @Scheduled(cron = "0/3 * * * * ? ")
//    @Scheduled(cron = "0/3 * * * * ? ")
    private void execute() {
        List<WrkMast> wrkMasts=wrkMastService.selectList(new EntityWrapper<WrkMast>()
                .eq("wrk_sts",11)
src/main/java/com/zy/asrs/task/handler/CreateOutTask.java
New file
@@ -0,0 +1,199 @@
package com.zy.asrs.task.handler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.StartupDto;
import com.zy.common.service.CommonService;
import com.zy.common.utils.HttpHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
@Component
@Slf4j
public class CreateOutTask {
    @Value("${wcs.address.URL}")
    private String addrs;
    @Value("${wcs.address.createOutTask}")
    private String outTask;
    @Value("${wcs.address.createLocMoveTask}")
    private String locMoveTask;
    @Value("${wcs.address.devicesStatus}")
    private String devicesStatus;
    @Autowired
    private LocMastService locMastService;
    @Autowired
    private LocDetlService locDetlService;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private WrkDetlService wrkDetlService;
    @Scheduled(cron = "0/10 * * * * ? ")
    @Transactional
    public void outTask(){
        //调用wcs接口获取设备状态
        String statusResponse = "";
        try {
            statusResponse = new HttpHandler.Builder()
                    .setUri(addrs)
                    .setPath(devicesStatus)
                    .build()
                    .doPost();
            JSONObject jsonObject = JSON.parseObject(statusResponse);
            if (jsonObject.get("code").equals(200)){
                log.info("设备正常");
            }
        }catch (Exception e){
            log.error("设备异常");
        }
        log.info("开始调用WCS接口,派发出库/移库任务");
        Date now = new Date();
        boolean flag= false;
        List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>().eq("loc_sts", "F"));
        List<Integer> outSitelist = new ArrayList<>();
        outSitelist.add(1152);
        outSitelist.add(1169);
        outSitelist.add(1177);
        LocMast shallowLocMast = new LocMast();
        for (LocMast locMast : locMasts) {
        //判断库位是否有出库任务
        if (!Cools.isEmpty(wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("source_loc_no",locMast.getLocNo())))){
            continue;
        }
            //判断是否是深库位 触发移库任务
            if (Utils.isDeepLoc(locMast.getLocNo())) {
                String deepLoc = locMast.getLocNo();
                String shallowLocNo = Utils.getShallowLocNo(deepLoc);
                shallowLocMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no", shallowLocNo));
                if (shallowLocMast.getLocSts().equals("F") || shallowLocMast.getLocSts().equals("D")) {
                    flag = true;
                }
            }
            int outSite = ThreadLocalRandom.current().nextInt(0, outSitelist.size());
            List<LocDetl> locDetlList = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", locMast.getLocNo()));
            // 目标站点状态检测
            int workNo = commonService.getWorkNo(2);
            //生成工作档
            WrkMast wrkMast = new WrkMast();
            wrkMast.setWrkNo(workNo);
            wrkMast.setIoTime(now);
            wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
            wrkMast.setIoType(flag ? 11 : 101); // 入出库状态
            wrkMast.setIoPri(flag ? 20D : 15D); // 优先级
            wrkMast.setCrnNo(locMast.getCrnNo());
            wrkMast.setStaNo(outSitelist.get(outSite)); // 目标站
            wrkMast.setSourceLocNo(flag ? shallowLocMast.getLocNo() : locMast.getLocNo()); // 源库位
            wrkMast.setLocNo(flag ? getMoveLocNo(locMast.getLocNo()) : ""); //目标库位
            wrkMast.setFullPlt("Y"); // 满板:Y
            wrkMast.setPicking("N"); // 拣料
            wrkMast.setExitMk("N"); // 退出
            wrkMast.setEmptyMk("N"); // 空板
            wrkMast.setLinkMis("N");
            wrkMast.setBarcode(locMast.getBarcode());
            wrkMast.setAppeUser(9527L); // 操作人员数据
            wrkMast.setAppeTime(now);
            wrkMast.setModiUser(9527l);
            wrkMast.setModiTime(now);
            if (!wrkMastService.insert(wrkMast)) {
                throw new CoolException("保存工作档失败,出库库位号:" + locMast.getLocNo());
            }
            // 生成工作档明细
                for (LocDetl locDetl : locDetlList) {
                    if (locDetl.getAnfme() == null || locDetl.getAnfme() <= 0.0D) {
                        continue;
                    }
                    WrkDetl wrkDetl = new WrkDetl();
                    wrkDetl.sync(locDetl);
                    wrkDetl.setOrderNo(""); // 手动出库不需要带出库存中的单据编号
                    wrkDetl.setWrkNo(workNo);
                    wrkDetl.setIoTime(now);
                    Double anfme = locDetl.getAnfme();
                    wrkDetl.setAnfme(anfme); // 数量
                    wrkDetl.setAppeTime(now);
                    wrkDetl.setAppeUser(9527L);
                    wrkDetl.setModiTime(now);
                    wrkDetl.setModiUser(9527L);
                    if (!wrkDetlService.insert(wrkDetl)) {
                        throw new CoolException("保存工作档明细失败");
                    }
                }
                String response = "";
                StartupDto startupDto = new StartupDto();
                startupDto.setTaskNo(wrkMast.getWrkNo());
                startupDto.setStaNo(wrkMast.getStaNo());
                startupDto.setLocNo(Utils.locToLocNo(wrkMast.getSourceLocNo()));
                startupDto.setTaskPri(wrkMast.getIoPri());
                flag = false;
                try {
                    response = new HttpHandler.Builder()
                            .setUri(addrs)
                            .setPath(flag ? locMoveTask : outTask)
                            .setJson(JSON.toJSONString(startupDto))
                            .build()
                            .doPost();
                    JSONObject jsonObject = JSON.parseObject(response);
                    if (jsonObject.get("code").equals(200)) {
                        wrkMast.setWrkSts(12L);
                        if (!wrkMastService.updateById(wrkMast)) {
                            throw new CoolException("工作档状态修改失败,工作号:{}" + wrkMast.getWrkNo());
                        }
                        // 修改库位状态:   F.在库 ====>>> R.出库预约/P.拣料/盘点/并板出库中
                        locMast = locMastService.selectById(flag?shallowLocMast.getLocNo():locMast.getLocNo());
                        if (locMast.getLocSts().equals("F")) {
                            locMast.setLocSts("R");
                            locMast.setModiUser(9527L);
                            locMast.setModiTime(now);
                            if (!locMastService.updateById(locMast)) {
                                throw new CoolException("预约库位状态失败,库位号:" + locMast.getLocNo());
                            }
                        } else {
                            throw new CoolException(locMast.getLocNo() + "库位不是在库状态");
                        }
                        log.info("出库/移库任务派发成功");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                }
        }
    }
    //移库任务找空库位 深库位
    public String getMoveLocNo(String locNo){
        LocMast targetLocMast = new LocMast();
        int deepRow = Utils.getRow(locNo);
        //先找深库位这一排还有没有空位库
        targetLocMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_sts", "O").eq("row1", deepRow));
        if (targetLocMast == null){
            targetLocMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_sts", "O").eq("row1", deepRow + 3));
        }
        if (targetLocMast == null){
            targetLocMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_sts", "O").eq("row1", deepRow + 1));
        }
        if (targetLocMast == null){
            targetLocMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_sts", "O").eq("row1", deepRow + 2));
        }
        return targetLocMast.getLocNo();
    }
}
src/main/java/com/zy/asrs/utils/Utils.java
@@ -86,6 +86,27 @@
        return copy;
    }
    public static 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 static String getShallowLocNo(String locNo){
        int shallowRow = 0;
        int deepRow = Utils.getRow(locNo);
        if (deepRow == 1 || (deepRow - 1) % 4 == 0){
            shallowRow = deepRow + 1;
        }else if (deepRow % 4 == 0){
            shallowRow = deepRow - 1;
        }
        int shallowBay = Utils.getBay(locNo);
        int shallowLev = Utils.getLev(locNo);
        return Utils.getLocNo(shallowRow, shallowBay, shallowLev);
    }
    public static LocGroupOrder findGroupOrder(SlaveProperties slaveProperties, String locNo) {
        int row1 = Utils.getRow(locNo);
        int bay1 = Utils.getBay(locNo);
@@ -114,4 +135,18 @@
        return checkOrder;
    }
    //判断是否是深库位
    public static boolean isDeepLoc(String locNo){
        int i = getRow(locNo);
        if (i == 1 || i == 4 || i == 5 || i == 8 || i == 9 || i == 12 || i == 13 || i == 16 || i == 17 || i == 20 || i == 21 || i == 24 || i == 25 || i == 28 || i == 29 || i == 32 || i == 33 || i == 36 || i == 37 || i == 40){
            return true;
        }
        return false;
    }
    public static String loc(String locNo){
        String[] split = locNo.split("-");
        return Utils.getLocNo(Integer.parseInt(split[0]),Integer.parseInt(split[1]),Integer.parseInt(split[2]));
    }
}
src/main/java/com/zy/common/CodeBuilder.java
@@ -2,11 +2,14 @@
import com.core.generators.CoolGenerator;
import com.core.generators.constant.SqlOsType;
import com.zy.asrs.service.LocMastService;
import org.springframework.beans.factory.annotation.Autowired;
/**
 * Created by vincent on 2019-06-04
 */
public class CodeBuilder {
    private LocMastService locMastService;
    public static void main(String[] args) throws Exception {
        CoolGenerator generator = new CoolGenerator();
@@ -25,4 +28,14 @@
        generator.build();
    }
//    public static void  loc(String[] args) throws Exception{
//        for (int row = 24;row < 25;row ++){
//            for (int bay = 2;bay < 3;bay ++){
//                for (int lev = 1;lev < 2;lev ++){
//
//                }
//            }
//        }
//    }
}
src/main/java/com/zy/common/model/StartupDto.java
@@ -16,6 +16,8 @@
    private String locNo;
    private Integer workNo;
    private Integer taskNo;
    private  Double taskPri;
}
src/main/java/com/zy/common/model/WmsDevDto.java
New file
@@ -0,0 +1,10 @@
package com.zy.common.model;
import lombok.Data;
@Data
public class WmsDevDto {
    private String locNo;
    private Integer taskNo;
    private Integer taskPri;
}
src/main/java/com/zy/common/service/CommonService.java
@@ -16,6 +16,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -122,6 +123,34 @@
     * @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 staDescId            路径ID
     * @param sourceStaNo          源站
     * @param findLocNoAttributeVo 属性
     * @param locTypeDto           类型
     * @return locNo 检索到的库位号
     */
    @Transactional
    public StartupDto searchLocNoByCrnNo(Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, LocTypeDto locTypeDto) {
@@ -158,11 +187,61 @@
        // 生成工作号
        int workNo = getWorkNo(0);
        // 返回dto
        startupDto.setWorkNo(workNo);
        startupDto.setTaskNo(workNo);
        startupDto.setCrnNo(locMast.getCrnNo());
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setLocNo(locNo);
        startupDto.setTaskPri(13.0);
        return startupDto;
    }
    @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(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;
    }
    //搜索满托盘库位
@@ -249,6 +328,91 @@
        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(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;
                    }
                }
                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;
src/main/java/com/zy/common/web/WcsController.java
@@ -9,10 +9,12 @@
import com.zy.asrs.entity.result.FindLocNoAttributeVo;
import com.zy.asrs.entity.result.StorageResult;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.common.CodeRes;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.StartupDto;
import com.zy.common.service.CommonService;
import com.zy.common.web.param.NotifyDto;
import com.zy.common.web.param.SearchLocParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -51,6 +53,8 @@
    private  LocDetlService locDetlService;
    @Autowired
    private  BasCrnpService basCrnpService;
    @Autowired
    private WorkService workService;
    @Value("${led.ip}")
    private String ledIp;
@@ -76,11 +80,21 @@
    @PostMapping("/pakin/loc/v1")
    @ResponseBody
    @Transactional
    public synchronized R getLocNo(@RequestBody(required = false) SearchLocParam param) {
        WaitPakin waitPakin = new WaitPakin();
        log.info("收到WCS入库接口请求====>>入参:{}", param);
        if (Cools.isEmpty(param.getIoType())) {
            return R.error("入出库类型不能为空");
        }
        //wcs调用此接口向组托表插入一条数据模拟组托
        waitPakin.setZpallet(param.getBarcode());
        waitPakin.setAnfme(100.0D);
        waitPakin.setMatnr("50001LR-71");
        waitPakin.setMaktx("气泡袋");
        waitPakin.setSpecs("50001LR-71");
        waitPakin.setModel("skv");
        waitPakinService.insert(waitPakin);
//        if (Cools.isEmpty(param.getIoType())) {
//            return R.error("入出库类型不能为空");
//        }
        if (Cools.isEmpty(param.getSourceStaNo())) {
            return R.error("源站编号不能为空");
        }
@@ -114,10 +128,11 @@
        switch (param.getIoType()) {
            case 1://满托盘入库
                assert waitPakins != null;
                dto = startupFullPutStore(param.getSourceStaNo(), param.getBarcode(), locTypeDto, waitPakins);
//                dto = startupFullPutStore(param.getSourceStaNo(), param.getBarcode(), locTypeDto, waitPakins);
                dto = startupFullPutStoreToWmsDev(param.getSourceStaNo(), param.getBarcode(), locTypeDto, waitPakins,param.getRow());
                break;
            case 10://空托盘入库
                dto = emptyPlateIn(param.getSourceStaNo(), param.getBarcode());
                dto = emptyPlateIn(param.getSourceStaNo(), param.getBarcode(),param.getRow());
                break;
            default:
                break;
@@ -136,16 +151,47 @@
        LocTypeDto locTypeDto = new LocTypeDto();
        locTypeDto.setLocType1(param.getLocType1());
        StartupDto dto = startupPickIn(param.getSourceStaNo(), param.getBarcode(), locTypeDto);;
        StartupDto dto = startupPickIn(param.getSourceStaNo(), param.getBarcode(), locTypeDto,param.getRow());;
        log.info("WCS拣选盘点入库接口返参:{},托盘码:{}", dto, param.getBarcode());
        return R.ok().add(dto);
    }
    @PostMapping("/taskWrk/state")
    @ResponseBody
    public R taskWrkState(@RequestBody(required = false) NotifyDto notifyDto){
        log.info("收到WCS请求上报接口======>>工作号:{},入参:{}",notifyDto.getSuperTaskNo(),notifyDto);
        if (Cools.isEmpty(notifyDto.getNotifyType())){
            return R.error("通知类型不能为空");
        }
        if (Cools.isEmpty(notifyDto.getTaskNo())){
            return R.error("任务号不能为空");
        }
        WrkMast wrkMast = new WrkMast();
        switch (notifyDto.getMsgType()){
            case "task_complete":
                wrkMast = wrkMastService.selectByTaskNo(notifyDto.getSuperTaskNo());
                if (wrkMast != null && (wrkMast.getIoType() == 1 || wrkMast.getIoType() == 11)){
                    wrkMast.setWrkSts(4L);
                    if (!wrkMastService.updateById(wrkMast)){
                        return R.error("修改工作档失败====>4");
                    }
                }else if (wrkMast != null && (wrkMast.getIoType() == 101)){
                    wrkMast.setWrkSts(14L);
                    if (!wrkMastService.updateById(wrkMast)){
                        return R.error("修改工作档失败====>14");
                    }
                }
            case "task_cancel":
                workService.cancelWrkMast(notifyDto.getSuperTaskNo(), 9527L);
        }
        return R.ok();
    }
    /**
     * 全板入库
     */
    @Transactional
    public StartupDto startupFullPutStore(Integer devpNo, String barcode, LocTypeDto locTypeDto, List<WaitPakin> waitPakins) {
    public StartupDto startupFullPutStore(Integer devpNo, String barcode, LocTypeDto locTypeDto, List<WaitPakin> waitPakins,int[] row) {
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
        // 检索库位
@@ -159,7 +205,7 @@
        if (dto == null) {
            throw new CoolException("找不到空库位");
        }
        int workNo = dto.getWorkNo();
        int workNo = dto.getTaskNo();
        Date now = new Date();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
@@ -167,7 +213,7 @@
        wrkMast.setIoTime(new Date());
        wrkMast.setWrkSts(2L); // 工作状态:生成入库ID
        wrkMast.setIoType(1); // 入出库状态:1.入库
        wrkMast.setIoPri(30D); // 优先级
        wrkMast.setIoPri(13D); // 优先级
        wrkMast.setCrnNo(dto.getCrnNo());
        wrkMast.setSourceStaNo(dto.getSourceStaNo());
        wrkMast.setStaNo(dto.getStaNo());
@@ -225,10 +271,98 @@
    }
    /**
     * 全板入库-wms-dev
     */
    @Transactional
    public StartupDto startupFullPutStoreToWmsDev(Integer devpNo, String barcode, LocTypeDto locTypeDto, List<WaitPakin> waitPakins,int[] row) {
        // 源站点状态检测
        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());
        StartupDto dto = commonService.getLocNoToWmsDev(1, devpNo, findLocNoAttributeVo, locTypeDto, barcode,row);
        if (dto == null) {
            throw new CoolException("找不到空库位");
        }
        int workNo = dto.getTaskNo();
        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.setCrnNo(dto.getCrnNo());
        wrkMast.setSourceStaNo(dto.getSourceStaNo());
        wrkMast.setStaNo(dto.getStaNo());
        wrkMast.setLocNo(loc(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("保存工作明细失败");
            }
        });
        // 更新入库通知档 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(loc(dto.getLocNo()));
        if (locMast.getLocSts().equals("O")) {
            locMast.setLocSts("S"); // S.入库预约
            locMast.setModiTime(now);
            if (!locMastService.updateById(locMast)) {
                throw new CoolException("改变库位状态失败");
            }
        } else {
            throw new CoolException(dto.getLocNo() + "目标库位已被占用");
        }
        return dto;
    }
    public String loc(String locNo){
        String[] split = locNo.split("-");
        return Utils.getLocNo(Integer.parseInt(split[0]),Integer.parseInt(split[1]),Integer.parseInt(split[2]));
    }
    /**
     * 拣选入库
     */
    @Transactional
    public StartupDto startupPickIn(Integer devpNo, String barcode, LocTypeDto locTypeDto) {
    public StartupDto startupPickIn(Integer devpNo, String barcode, LocTypeDto locTypeDto,int[] row) {
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
@@ -258,7 +392,7 @@
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
        int workNo = dto.getWorkNo();
        int workNo = dto.getTaskNo();
        wrkMast.setWrkNo(workNo);
        wrkMast.setWrkSts(2L); // 工作状态:生成入库ID
        wrkMast.setIoType(wrkMastOut.getIoType() - 50); // 入出库状态:53.拣料再入库
@@ -310,7 +444,7 @@
    }
    @Transactional
    public StartupDto emptyPlateIn(Integer devpNo, String barcode) {
    public StartupDto emptyPlateIn(Integer devpNo, String barcode,int[] row) {
        // 检索库位
        Integer[] arr=arr();
src/main/java/com/zy/common/web/param/NotifyDto.java
New file
@@ -0,0 +1,42 @@
package com.zy.common.web.param;
import lombok.Data;
@Data
public class NotifyDto {
    private Long id;
    //通知类型
    private String notifyType;
    //设备号
    private Integer device;
    //工作号
    private String taskNo;
    //上级系统工作号
    private String superTaskNo;
    //消息类型
    private String msgType;
    //消息描述
    private String msgDesc;
    //消息数据
    private String data;
    //失败重试次数
    private Integer failTimes = 3;
    //重试次数
    private Integer retryTimes = 0;
    //重试间隔默认30s
    private Integer retryTime = 30;
    //上次重试时间
    private Long lastRetryTime = 0L;
}
src/main/java/com/zy/common/web/param/SearchLocParam.java
@@ -7,8 +7,8 @@
 */
@Data
public class SearchLocParam {
    private Integer ioType;
    //ioType全部默认为1
    private Integer ioType = 1;
    private Integer sourceStaNo;
@@ -17,4 +17,7 @@
    // 库位规格( 0:未知, 1:低库位, 2:高库位)
    private Short locType1;
    //库位排
    private int[] row;
}
src/main/resources/application.yml
@@ -1,5 +1,5 @@
server:
  port: 8081
  port: 8080
  servlet:
    context-path: /@pom.build.finalName@
@@ -12,7 +12,7 @@
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
    url: jdbc:sqlserver://127.0.0.1:1433;databasename=qlasrs-sxk
    username: sa
    password: spcyy@2025
    password: sa@123
  mvc:
    static-path-pattern: /**
  redis:
@@ -43,7 +43,7 @@
#License相关配置
license:
  subject: qlasrs-sxk
  subject: wmsdev
  publicAlias: publicCert
  storePass: public_zhongyang_123456789
  licensePath: license.lic
@@ -53,26 +53,33 @@
wcs-slave:
  # 由浅入深
  locGroupAscOrder: [
    {rowList: [1],minBay: 1,maxBay: 16},
    {rowList: [3,4,5,6],minBay: 1,maxBay: 16},
    {rowList: [10,9,8,7],minBay: 1,maxBay: 16},
    {rowList: [10,9,8,7,6,5,4,3],minBay: 17,maxBay: 22},
    {rowList: [12,13],minBay: 1,maxBay: 22},
    {rowList: [15,14],minBay: 1,maxBay: 22},
    {rowList: [17,18,19,20,21,22,23],minBay: 1,maxBay: 22},
    {rowList: [2],minBay: 1,maxBay: 22},
    {rowList: [11],minBay: 1,maxBay: 22},
    {rowList: [16],minBay: 1,maxBay: 22},
    {rowList: [1],minBay: 2,maxBay: 60},
    {rowList: [3,4,5,6],minBay: 2,maxBay: 60},
    {rowList: [10,9,8,7],minBay: 2,maxBay: 60},
    {rowList: [10,9,8,7,6,5,4,3],minBay: 2,maxBay: 60},
    {rowList: [12,13],minBay: 2,maxBay: 60},
    {rowList: [15,14],minBay: 2,maxBay: 60},
    {rowList: [17,18,19,20,21,22,23,24],minBay: 2,maxBay: 60},
    {rowList: [2],minBay: 2,maxBay: 60},
    {rowList: [11],minBay: 2,maxBay: 60},
    {rowList: [16],minBay: 2,maxBay: 60},
    {rowList: [25,26,27,28],minBay: 2,maxBay: 60},
    {rowList: [29,30,31,32],minBay: 2,maxBay: 60},
    {rowList: [33,34,35,36],minBay: 2,maxBay: 60},
    {rowList: [37,38,39,40],minBay: 2,maxBay: 60},
  ]
#wcs对接
wcs:
  #地址
  address:
    URL: http://127.0.0.1:8080/wcs
    URL: http://192.168.4.69:9090/wcs
    #出库移库任务下发
    outboundTaskSend: open/outboundTaskSend
    deviceStatus : open/deviceStatus
    createOutTask: openapi/createOutTask
    createLocMoveTask: openapi/createLocMoveTask
    devicesStatus: openapi/devicesStatus
led:
  ip: 192.168.1.198
src/main/resources/mapper/LocDetlMapper.xml
@@ -149,6 +149,19 @@
        ORDER BY ld.appe_time ASC
    </select>
    <select id="getSameDetlListToWmsDev" 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'
        AND lm.row1 IN
        <foreach collection="rows" item="row" open="(" separator="," close=")">
            #{row}
        </foreach>
        ORDER BY ld.appe_time ASC
    </select>
    <select id="getStockStatis" resultType="com.zy.asrs.entity.LocDetl">
        select * from
        (
src/main/resources/mapper/LocMastMapper.xml
@@ -41,4 +41,15 @@
        select DISTINCT lev1 from asr_loc_mast
    </select>
    <select id="selectLoc" resultMap="BaseResultMap">
        select * from asr_loc_mast where 1 = 1
        AND loc_sts = 'O'
        AND row1 IN
        <if test="rows != null">
            <foreach collection="rows" item="row" open="(" separator="," close=")">
                #{row}
            </foreach>
        </if>
        order by bay1 asc, lev1 asc
    </select>
</mapper>
src/main/resources/mapper/WrkMastMapper.xml
@@ -76,4 +76,8 @@
        order by modi_time,wrk_no asc
    </select>
    <select id="selectByTaskNo" resultMap="BaseResultMap">
        select *
        from asr_wrk_mast where wrk_no = #{taskNo}
    </select>
</mapper>