自动化立体仓库 - WMS系统
lty
9 天以前 f3a7b17ceb5da091ec7987a7a78b23996364b687
#4.22需求变更V1
10个文件已修改
693 ■■■■■ 已修改文件
src/main/java/com/zy/api/controller/WcsApiController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/api/service/WcsApiService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/api/service/impl/WcsApiServiceImpl.java 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/LocDetlMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/WorkService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/AutoEmptyOutHandler.java 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/service/CommonService.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/WcsController.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/api/controller/WcsApiController.java
@@ -67,7 +67,8 @@
        if (Objects.isNull(params)) {
            return R.error("参数不能为空!!");
        }
        return wcsApiService.backLocs(params);
//        return wcsApiService.backLocs(params);
        return wcsApiService.backLocsV2(params);
    }
@@ -95,7 +96,7 @@
        if (Objects.isNull(params)) {
            return R.error("参数不能为空!!");
        }
        return wcsApiService.receviceTaskFromWcs(params);
        return wcsApiService.receviceTaskFromWcsV2(params);
    }
src/main/java/com/zy/api/service/WcsApiService.java
@@ -25,6 +25,7 @@
     * @return com.core.common.R
     */
    R backLocs(String params);
    R backLocsV2(String params);
    /**
     * 下发任务至WCS
@@ -53,6 +54,7 @@
     * @return com.core.common.R
     */
    R receviceTaskFromWcs(ReceviceTaskParams params);
    R receviceTaskFromWcsV2(ReceviceTaskParams params);
    //输入库位自动冻结算出相邻库位序号
    Integer[] freezeLocAround(Integer locId);
src/main/java/com/zy/api/service/impl/WcsApiServiceImpl.java
@@ -145,6 +145,25 @@
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R backLocsV2(String params) {
        WrkMast mast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("barcode", params));
        if (Objects.isNull(mast)) {
            throw new CoolException("任务不存在!!");
        }
        if(Cools.isEmpty(mast.getIsSuplus())){
            throw new CoolException("未指定回库类型!!");
        }
        LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no",mast.getLocNo()));
        if(mast.getCrnNo() != locMast.getCrnNo()){ //若源库位不在本巷道
            return workService.backLocOperationV2(mast.getWrkNo() + "", mast.getAppeUser());
        }
        return workService.backLocOperation(mast.getWrkNo() + "", mast.getAppeUser());
    }
    /**
     * 下发任务至WCS
     *
@@ -365,6 +384,7 @@
                        }
                        if (!Cools.isEmpty(weight)) {
                            Double val = Math.round((weight - matnr.getSafeQty()) * 10000) / 10000.0;
                            //TODO 重量判断计算
                            if (val.compareTo(0.0) > 0) {
                                WrkDetl wrkDetl = new WrkDetl();
                                if (Objects.isNull(locDetl)) {
@@ -417,7 +437,7 @@
                                } else {
                                    throw new CoolException("任务号截取失败,请检查主任务档任档wrkCode字段");
                                }
                            }else{
                            }else{  //TODO 计算异常后这里是什么流程
                                String wrkNo = mast.getWrkCode();
                                WrkMast orgWrk = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", wrkNo));
                                if (Objects.isNull(orgWrk)) {
@@ -532,6 +552,175 @@
        }
        return R.ok();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R receviceTaskFromWcsV2(ReceviceTaskParams params) {
        log.info("wcs任务反馈="+JSON.toJSONString(params));
        if (Objects.isNull(params.getSuperTaskNo())) {
            throw new CoolException("WMS任务号不能为空!!");
        }
        if (Objects.isNull(params.getNotifyType())) {
            throw new CoolException("动作类型不能为空!!");
        }
        WrkMast mast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", params.getSuperTaskNo()));
        if (Objects.isNull(mast)) {
            throw new CoolException("任务档不存在!!");
        }
        if (params.getNotifyType().equals("task")) {
            //任务
            if (params.getMsgType().equals("task_complete")) {
                //称重
                if ((mast.getIoType()==1||mast.getIoType()==10)&&mast.getWrkSts() == 2 && Cools.isEmpty(mast.getStaNo())) {
                    Double weight = 0.0;
                    if (!Cools.isEmpty(params.getData())){
                        JSONObject jsonObject = JSONObject.parseObject(params.getData());
                        weight=jsonObject.getDouble("weight");
                    }
                    if (mast.getIoType() == 10) {//空板任务完成
                        //空板入库任务档
                        LocDetl locDetl = locDetlService.selectOne(new EntityWrapper<LocDetl>()
                                .eq("zpallet", mast.getBarcode())
                                .eq("loc_no", mast.getSourceLocNo()));
                        WrkDetl mainWrkDetl = null;
                        if (Objects.isNull(locDetl) && !Cools.isEmpty(mast.getWrkCode())) {
                            mainWrkDetl = wrkDetlService.selectOne(new EntityWrapper<WrkDetl>()
                                    .eq("wrk_no", mast.getWrkCode())
                                    .eq("zpallet", mast.getBarcode()));
                            if (Objects.isNull(mainWrkDetl)) {
                                mainWrkDetl = wrkDetlService.selectOne(new EntityWrapper<WrkDetl>()
                                        .eq("wrk_no", mast.getWrkCode()));
                            }
                            if (!Objects.isNull(mainWrkDetl)) {
                                log.info("locDetl为空,回退查询主任务明细,wrkNo={}, mainWrkNo={}, barcode={}",
                                        mast.getWrkNo(), mast.getWrkCode(), mast.getBarcode());
                            }
                        }
                        if (Objects.isNull(locDetl) && Objects.isNull(mainWrkDetl)) {
                            throw new CoolException("明细数据不存在!!");
                        }
                        String matnrNo = Objects.isNull(locDetl) ? mainWrkDetl.getMatnr() : locDetl.getMatnr();
                        Mat matnr = matService.selectOne(new EntityWrapper<Mat>().eq("matnr", matnrNo));
                        if (Objects.isNull(matnr)) {
                            throw new CoolException("物料基础信息不存在!!");
                        }
                        if (!Cools.isEmpty(weight)) {
                            //取消重量判断改变回库类型
                            String wrkNo = mast.getWrkCode();
                            WrkMast orgWrk = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", wrkNo));
                            if (Objects.isNull(orgWrk)) {
                                throw new CoolException("数据错误,主任务档不存在或已删除!!");
                            }
                            mast.setOveMk("Y");
                            orgWrk.setOveMk("Y");
                            if (!wrkMastService.updateById(orgWrk)) {
                                throw new CoolException("任务档修改失败!!");
                            }
                        }
                    } else {  //入库/回库有料任务完成
                        WrkDetl wrkDetl = wrkDetlService.selectOne(new EntityWrapper<WrkDetl>().eq("wrk_no", mast.getWrkNo()));
                        if (Objects.isNull(wrkDetl)) {
                            throw new CoolException("数据错误,任务明细不存在!!");
                        }
                        Mat matnr = matService.selectOne(new EntityWrapper<Mat>().eq("matnr", wrkDetl.getMatnr()));
                        if (Objects.isNull(matnr)) {
                            throw new CoolException("物料基础信息不存在!!");
                        }
                        Double realQty = Math.round((wrkDetl.getStockQty() - wrkDetl.getAnfme()) * 10000) / 10000.0;
                        if (!Cools.isEmpty(weight)) {
                            Double val = Math.round((weight - matnr.getSafeQty()) * 10000) / 10000.0;
                            //称重后,计算出真实长度
                            realQty = val * matnr.getVolume();
                            if (realQty<matnr.getSafeQty()){//不改为空板,仍作为设为matnr.getSafeQty()
                                wrkDetl.setAnfme(matnr.getSafeQty()*matnr.getVolume());
                            }else{
                                wrkDetl.setAnfme(realQty);
                            }
                            wrkDetl.setWeight(weight);
                            if (!wrkDetlService.update(wrkDetl, new EntityWrapper<WrkDetl>().eq("wrk_no", mast.getWrkNo()).eq("matnr", wrkDetl.getMatnr()).eq("barcode", wrkDetl.getBarcode()))) {
                                throw new CoolException("任务档明细修改失败!!");
                            }
                        }
                        mast.setOveMk("Y");
                        if (!wrkMastService.updateById(mast)) {
                            throw new CoolException("任务档修改失败!!");
                        }
                        if (!Cools.isEmpty(mast.getWrkCode())) {
                            String wrkNo = mast.getWrkCode();
                            WrkMast orgWrk = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", wrkNo));
                            if (Objects.isNull(orgWrk)) {
                                throw new CoolException("数据错误,主任务档不存在或已删除!!");
                            }
                            orgWrk.setOveMk("Y");
                            if (!wrkMastService.updateById(orgWrk)) {
                                throw new CoolException("任务档修改失败!!");
                            }
                            WrkDetl detl = wrkDetlService.selectOne(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkNo));
                            if (Objects.isNull(detl)) {
                                throw new CoolException("子任务档明细不存在!!");
                            }
                            //库存减去称重长度
                            Double v = Math.round((wrkDetl.getStockQty() - realQty) * 10000) / 10000.0;
                            //原出为数量与真实数量互换,保持一致性
                            if(v<= 0){
                                detl.setAnfme(matnr.getSafeQty());//设定为默认值
                            }else{
                                detl.setAnfme(v);
                            }
                            detl.setWeight(weight);
                            if (!wrkDetlService.update(detl, new EntityWrapper<WrkDetl>().eq("wrk_no", wrkNo).eq("matnr", detl.getMatnr()).eq("barcode", detl.getBarcode()))) {
                                throw new CoolException("原任务档明细修改失败!!");
                            }
                        } else {
                            throw new CoolException("任务号截取失败,请检查主任务档任档wrkCode字段");
                        }
                    }
                }
                if (!Objects.isNull(mast.getWrkCode())) {
                    if (mast.getOveMk().equals("N") && !Cools.isEmpty(mast.getIsSuplus())) {
                        throw new CoolException("任务未上报重量,无法完结任务!!");
                    }
                }
                if (mast.getIoType() == 1 || mast.getIoType() == 2 ||mast.getIoType() == 10) {
                    mast.setWrkSts(4L);
                } else if ((mast.getIoType() == 101||mast.getIoType()==110) && mast.getWrkSts()<14) {
                    mast.setWrkSts(14L);
                    if(Cools.isEmpty(mast.getStaNo())){
                        mast.setOveMk("Y");
                    }
                }
                if (!wrkMastService.updateById(mast)) {
                    throw new CoolException("任务状态修改失败!!");
                }
            } else if (params.getMsgType().equals("task_cancel")) {
                //todo 取消任务
            }else if (params.getMsgType().equals("task_arrive")) {
                //到达目的地
                //如果出库任务是跨区则需要生成新的入库任务入库
                if(!Cools.isEmpty(mast.getLocNo())){
                    mast.setOnlineYn("N");//等待生成跨区入库任务
                }
                mast.setWrkSts(14L);
                if(Cools.isEmpty(mast.getStaNo())){
                    mast.setOveMk("Y");
                }
                mast.setModiTime(new Date());
                if (!wrkMastService.updateById(mast)) {
                    throw new CoolException("任务状态修改失败!!");
                }
            }
        } else if (params.getNotifyType().equals("weight")) {
        }
        return R.ok();
    }
    //输入库位自动冻结算出相邻库位序号
    @Override
    public Integer[] freezeLocAround(Integer locId) {
src/main/java/com/zy/asrs/mapper/LocDetlMapper.java
@@ -50,6 +50,17 @@
    @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.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);
    @Select("select top 1 ld.* from asr_loc_detl ld left join asr_loc_mast lm on ld.loc_no = lm.loc_no " +
            "where lm.crn_no = #{crnNo} and lm.loc_sts = 'F' and lm.frozen = 0 and lm.deleted = 0 and lm.whs_type = 1 " +
            "and ld.appe_time is not null and (ld.frozen is null or ld.frozen = 0) " +
            "order by ld.appe_time asc, ld.id asc")
    LocDetl selectOldestLocDetl(@Param("crnNo") Integer crnNo);
    @Select("select count(1) from asr_loc_detl ld left join asr_loc_mast lm on ld.loc_no = lm.loc_no " +
            "where lm.crn_no = #{crnNo} and lm.frozen = 0 and lm.deleted = 0 and lm.whs_type = 1 " +
            "and ld.matnr = #{matnr} and (ld.frozen is null or ld.frozen = 0)")
    Integer countMatnrByCrnNo(@Param("crnNo") Integer crnNo, @Param("matnr") String matnr);
    List<String> selectSameDetlTodayBatch(@Param("matnr") String matnr,@Param("batch") String batch, @Param("start") Integer start, @Param("end") Integer end);
    List<LocDetl> getStockStatis(Map<String, Object> map);
src/main/java/com/zy/asrs/service/WorkService.java
@@ -99,6 +99,7 @@
     * @param userId
     */
    R backLocOperation(String workNo, Long userId);
    R backLocOperationV2(String workNo, Long userId);
    /**
     * 通知档手动生成任务
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
@@ -1506,6 +1506,7 @@
        if(Cools.isEmpty(locNo)) {
            return R.error("没有空库位");
        }
//        if()
        Date now = new Date();
        // 堆垛机站点(目标站)
@@ -1514,8 +1515,8 @@
        BeanUtils.copyProperties(wrkMast, mast);
        mast.setWrkNo(wokNo);
        // 更新工作档数据状态
        mast.setIoType(ioType); // 入出库类型: 103->53,104->54,107->57
        mast.setWrkSts(1L); // 工作状态: 2.设备上走
        mast.setIoType(ioType); // 1余料回库,10空轴回库
        mast.setWrkSts(1L); // 生成回库id
        mast.setSourceStaNo(""); // 源站
        mast.setStaNo(""); // 目标站
        mast.setSourceLocNo(wrkMast.getLocNo());
@@ -1581,6 +1582,115 @@
        return R.ok("生成回库任务成功!!");
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R backLocOperationV2(String workNo, Long userId) {
        WrkMast wrkMast = wrkMastService.selectById(workNo);
        if (Cools.isEmpty(wrkMast)) {
            return R.error(workNo+"工作档不存在");
        }
        if (wrkMast.getWrkSts() != 15) {
            return R.error("当前任务状态不能执行此操作!");
        }
        Integer ioType = 101;
        Integer wokNo;
        if (Objects.isNull(wrkMast.getIsSuplus())) {
            return R.error("回库类型不能为空!!");
        }
        wokNo = commonService.getWorkNo(0);
        LocMast locMast1 = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no", wrkMast.getLocNo()));
        // 获取目标站
        Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                .eq("type_no", ioType)
                .eq("stn_no", 1070) // 1070
                .eq("crn_no", locMast1.getCrnNo()); // 堆垛机号
        StaDesc staDesc = staDescService.selectOne(wrapper);
        if (Cools.isEmpty(staDesc)) {
            return R.error("出库路径不存在");
        }
        int count = wrkMastService.selectCount(new EntityWrapper<WrkMast>().eq("barcode", wrkMast.getBarcode()));
        if (count >= 2) {
            return R.error("任务档已生成,不可以重复生成相同的子任务!!");
        }
        WrkDetl detl = wrkDetlService.selectOne(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo()));
        LocDetl locDetl = new LocDetl();
        BeanUtils.copyProperties(detl, locDetl);
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo(locDetl);
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(staDesc.getCrnStn(), false);
        sourceStaNo.setLocType1((short) 1);
        LocTypeDto locTypeDto = new LocTypeDto(sourceStaNo);
        String locNo = wrkMast.getSourceLocNo();
        if(Cools.isEmpty(locNo)) {
            return R.error("没有空库位");
        }
        Date now = new Date();
        // 堆垛机站点(目标站)
        Integer staNo = staDesc.getCrnStn();
        WrkMast mast = new WrkMast();
        BeanUtils.copyProperties(wrkMast, mast);
        mast.setWrkNo(wokNo);
        // 更新工作档数据状态
        mast.setIoType(ioType); // 110先出库到1070
        mast.setWrkSts(11L); // 生成出库id
        mast.setSourceStaNo(String.valueOf(staDesc.getCrnStn())); // 源站
        mast.setStaNo(String.valueOf(staDesc.getStnNo())); // 目标站
        mast.setSourceLocNo(wrkMast.getLocNo()); //出库位
        mast.setLocNo(locNo); // 目标库位 = 出库时的源库位,用于判断巷道
        mast.setModiTime(now);
        mast.setWrkCode(null);
        mast.setPacked(workNo);
        mast.setModiUser(userId);
        if (!wrkMastService.insert(mast)) {
            return R.error("更新工作档数据状态失败");
        }
        List<WrkDetl> wrkDetls = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo()));
        if (Cools.isEmpty(wrkDetls)) {
            return R.error("数据错误,任务档明细不存在 !!");
        }
        LocAroundBind aroundBind = locAroundBindService.selectOne(new EntityWrapper<LocAroundBind>().eq("b_loc_no", mast.getSourceLocNo()));
        if (!Objects.isNull(aroundBind)) {
            aroundBind.setLocType(LocStsType.LOC_STS_TYPE_R.type);
            if (!locAroundBindService.updateById(aroundBind)) {
                return R.error("工位状态修改失败!!");
            }
        }
        wrkDetls.forEach(wrkDetl -> {
            WrkDetl wrkDetl1 = new WrkDetl();
            BeanUtils.copyProperties(wrkDetl, wrkDetl1);
            wrkDetl1.setAnfme(wrkDetl.getStockQty() - wrkDetl.getAnfme());
            wrkDetl1.setWrkNo(wokNo);
            if (!wrkDetlService.insert(wrkDetl1)) {
                throw new CoolException("任务档明细保存失败!!");
            }
        });
        //修改作业库位状态
        LocMast locMast = locMastService.selectById(wrkMast.getLocNo());
        locMast.setLocSts("R");
        locMast.setModiTime(now);
        locMast.setModiUser(userId);
        if (!locMastService.updateById(locMast)) {
            return R.error("修改库位状态失败");
        }
        if (Cools.isEmpty(mast)) {
            return R.error("没有生成任务");
        }
        return R.ok("生成回库任务成功!!");
    }
    @Override
    public StartupDto createWaitPainWrkMastStart(List<WaitPakin> list, Long userId) {
src/main/java/com/zy/asrs/task/handler/AutoEmptyOutHandler.java
@@ -1,16 +1,15 @@
package com.zy.asrs.task.handler;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.core.common.Cools;
import com.zy.asrs.entity.LocDetl;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.entity.StaDesc;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.entity.param.EmptyPlateOutParam;
import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.entity.param.StockOutParam;
import com.zy.asrs.mapper.LocDetlMapper;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.service.StaDescService;
import com.zy.asrs.service.WorkService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.task.AbstractHandler;
@@ -24,6 +23,7 @@
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Slf4j
@@ -38,9 +38,7 @@
    @Autowired
    private WorkService workService;
    @Autowired
    private BasDevpService basDevpService;
    @Autowired
    private StaDescService staDescService;
    private LocDetlMapper locDetlMapper;
    @Transactional
    public ReturnT<String> start() {
        try {
@@ -78,6 +76,30 @@
                                .orderBy("lev1,bay1")
                ).getRecords();
                if (Cools.isEmpty(locMastDList)) {
                    Config configInventory = configService.selectConfigByCode("InventoryAutoOut");
                    if (Cools.isEmpty(configInventory) || configInventory.getValue().equals("false")) {
                        continue;
                    }
                    LocDetl oldest = locDetlMapper.selectOldestLocDetl(crnNo);
                    if (Cools.isEmpty(oldest) || Cools.isEmpty(oldest.getLocNo()) || Cools.isEmpty(oldest.getMatnr()) || Cools.isEmpty(oldest.getAnfme())) {
                        continue;
                    }
                    StockOutParam stockOutParam = new StockOutParam();
                    stockOutParam.setOutSite(1076);
                    StockOutParam.LocDetl outDetl = new StockOutParam.LocDetl();
                    outDetl.setLocNo(oldest.getLocNo());
                    outDetl.setMatnr(oldest.getMatnr());
                    outDetl.setBatch(oldest.getBatch());
                    outDetl.setBrand(oldest.getBrand());
                    outDetl.setStandby1(oldest.getStandby1());
                    outDetl.setStandby2(oldest.getStandby2());
                    outDetl.setStandby3(oldest.getStandby3());
                    outDetl.setBoxType1(oldest.getBoxType1());
                    outDetl.setBoxType2(oldest.getBoxType2());
                    outDetl.setBoxType3(oldest.getBoxType3());
                    outDetl.setCount(oldest.getAnfme());
                    stockOutParam.setLocDetls(Arrays.asList(outDetl));
                    workService.startupFullTakeStore(stockOutParam, 1L);
                    continue;
                }
src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java
@@ -600,6 +600,13 @@
                            throw new CoolException("工位状态修改失败!!");
                        }
                    } else {
                        if(!Objects.isNull(wrkMast.getPacked())){ //不是本巷道的出库至1070,之前的跨巷道出库进行完结操作
                            WrkMast wrkMast1 = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no",wrkMast.getPacked()));
                            if(!Objects.isNull(wrkMast1)) {
                                wrkMast1.setOveMk("Y");
                                wrkMastService.updateById(wrkMast1);
                            }
                        }
//                    // 出库确认信号位
//                    if (Cools.isEmpty(wrkMast.getInvWh()) || wrkMast.getInvWh().equals("N")) {
//                        return SUCCESS;
src/main/java/com/zy/common/service/CommonService.java
@@ -9,6 +9,7 @@
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.result.FindLocNoAttributeVo;
import com.zy.asrs.entity.result.KeyValueVo;
import com.zy.asrs.mapper.LocDetlMapper;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.asrs.utils.VersionUtils;
@@ -53,6 +54,8 @@
    private LocMastService locMastService;
    @Autowired
    private LocDetlService locDetlService;
    @Autowired
    private LocDetlMapper locDetlMapper;
    @Autowired
    private SlaveProperties slaveProperties;
    @Autowired
@@ -134,9 +137,9 @@
             */
            switch (rowLastnoType.getType()) {
                case 1:
                    return getLocNoRun(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, 0, locTypeDto, 0);
                    return getLocNoRunV3(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, 0, locTypeDto, 0);
                case 2:
                    return getLocNoRun(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, 0, locTypeDto, 0);
                    return getLocNoRunV3(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, 0, locTypeDto, 0);
                case 3:
                    log.error("站点={} 未查询到对应的规则", sourceStaNo);
                    break;
@@ -144,6 +147,32 @@
                    return getLocNoRun4(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, 4, locTypeDto, 0);
                case 5:
                    return getLocNoRun5(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, 0, locTypeDto, 0);
                default:
                    log.error("站点={} 未查询到对应的规则", sourceStaNo);
                    break;
            }
        } catch (Exception e) {
            log.error("站点={} 未查询到对应的规则", sourceStaNo);
        }
        return null;
    }
    @Transactional
    public StartupDto getLocNoV2(Integer staDescId, Integer sourceStaNo, WrkMast wrkMast, LocTypeDto locTypeDto) {
        try {
            Integer whsType = Utils.GetWhsType(sourceStaNo);
            RowLastno rowLastno = rowLastnoService.selectById(whsType);
            RowLastnoType rowLastnoType = rowLastnoTypeService.selectById(rowLastno.getTypeId());
            /**
             * 库型 1: 标准堆垛机库  2: 同巷道找库位
             */
            switch (rowLastnoType.getType()) {
                case 1:
                    return getLocNoRunV2(whsType, staDescId, sourceStaNo, wrkMast, 0, locTypeDto, 0);
                case 2:
                    return getLocNoRunV2(whsType, staDescId, sourceStaNo, wrkMast, 0, locTypeDto, 0);
                default:
                    log.error("站点={} 未查询到对应的规则", sourceStaNo);
                    break;
@@ -259,6 +288,205 @@
        return startupDto;
    }
    @Transactional
    public StartupDto getLocNoRunV3(Integer whsType, Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, Integer moveCrnNo, LocTypeDto locTypeDto, int times) {
        StartupDto startupDto = new StartupDto();
        // 初始化参数
        int crnNo = 0;      //堆垛机号
        LocMast locMast = null;     // 目标库位
        RowLastno whsType1 = rowLastnoService.selectOne(new EntityWrapper<RowLastno>().eq("whs_type", 2));
        crnNo = whsType1.getCrnQty();
        String matnr = findLocNoAttributeVo == null ? null : findLocNoAttributeVo.getMatnr();
        Integer chosenCrnNo = null;
        Integer chosenCount = null;
        LocMast chosenLocMast = null;
        int sCrnNo = whsType1.getsCrnNo();
        int eCrnNo = whsType1.geteCrnNo();
        List<Integer> candidates = new ArrayList<>();
        for (int i = crnNo; i <= eCrnNo; i++) {
            candidates.add(i);
        }
        for (int i = sCrnNo; i < crnNo; i++) {
            candidates.add(i);
        }
        if(staDescId != 10){
            for (Integer candidate : candidates) {
                if (!basCrnpService.checkSiteError(candidate, true)) {
                    continue;
                }
                StaDesc staDesc = staDescService.selectOne(new EntityWrapper<StaDesc>()
                        .eq("type_no", staDescId)
                        .eq("stn_no", sourceStaNo)
                        .eq("crn_no", candidate));
                if (Cools.isEmpty(staDesc)) {
                    continue;
                }
                List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                        .eq("crn_no", candidate)
                        .eq("loc_sts", "O")
                        .eq("frozen", 0)
                        .eq("deleted", 0)
                        .eq("whs_type", 1)
                        .orderBy("lev1,bay1"));
                if (Cools.isEmpty(locMasts) || locMasts.size() <= 10) {
                    continue;
                }
                Integer count = null;
                if (!Cools.isEmpty(matnr)) {
                    count = locDetlMapper.countMatnrByCrnNo(candidate, matnr);
                }
                if (count == null) {
                    count = 0;
                }
                if (chosenCrnNo == null || count < chosenCount) {
                    chosenCrnNo = candidate;
                    chosenCount = count;
                    chosenLocMast = locMasts.get(0);
                }
            }
        }
        if (chosenCrnNo != null) {
            crnNo = chosenCrnNo;
            locMast = chosenLocMast;
        } else
//        else if (basCrnpService.checkSiteError(crnNo, true))
        {//若轮询找不到数量最少的巷道,退回原来方法
            BasCrnp basCrnp = basCrnpService.selectById(crnNo);
            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                    .eq("crn_no", basCrnp.getCrnNo())
                    .eq("loc_sts", "O")
                    .eq("frozen", 0)
                    .eq("deleted", 0)
                    .eq("whs_type", 1)
                    .orderBy("lev1,bay1"));
            if (!Cools.isEmpty(locMasts)) {
                if (locMasts.size() > 10) {
                    locMast = locMasts.get(0);
                }
            }
        }
        int crnNo1 = crnNo + 1;
        if (crnNo1> whsType1.geteCrnNo()) {
            crnNo1 = whsType1.getsCrnNo();
        }
        whsType1.setCrnQty(crnNo1);
        rowLastnoService.updateById(whsType1);
        Wrapper<StaDesc> wrapper = null;
        StaDesc staDesc = null;
        // 获取目标站
        wrapper = new EntityWrapper<StaDesc>()
                .eq("type_no", staDescId)
                .eq("stn_no", sourceStaNo)
                .eq("crn_no", crnNo);
        staDesc = staDescService.selectOne(wrapper);
        if (Cools.isEmpty(staDesc)) {
            log.error("入库路径不存在type_no={},stn_no={},crn_no={}", staDescId, sourceStaNo, crnNo);
        }
        // 递归查询
        if (Cools.isEmpty(locMast) || !locMast.getLocSts().equals("O")) {
            // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归
            if (times < 5) {
                times = times + 1;
                return getLocNoRun(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, moveCrnNo, 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.setLocNo(locNo);
        startupDto.setStaNo(staDesc.getCrnStn());
        return startupDto;
    }
    /**
     * 当回源库位不在本巷道时,出库至1070重新检索巷道根据1,2巷道之间分配,3,4巷道全局分配规则
     */
    @Transactional
    public StartupDto getLocNoRunV2(Integer whsType, Integer staDescId, Integer sourceStaNo, WrkMast wrkMast, Integer moveCrnNo, LocTypeDto locTypeDto, int times) {
        StartupDto startupDto = new StartupDto();
        List<WrkDetl> wrkDetl = wrkDetlService.selectByWrkNo(wrkMast.getWrkNo());
        WrkDetl detl = null;
        if(!wrkDetl.isEmpty()){
            detl = wrkDetl.get(0);
        }
        String matnr = detl == null ? null : detl.getMatnr();
        int[] candidates = wrkMast.getCrnNo() != null && wrkMast.getCrnNo() < 3 ? new int[]{1, 2} : new int[]{1, 2, 3, 4};
        Integer chosenCrnNo = null;
        Integer chosenCount = null;
        for (int candidate : candidates) {
            if (!basCrnpService.checkSiteError(candidate, true)) {
                continue;
            }
            StaDesc staDesc = staDescService.selectOne(new EntityWrapper<StaDesc>()
                    .eq("type_no", staDescId)
                    .eq("stn_no", sourceStaNo)
                    .eq("crn_no", candidate));
            if (Cools.isEmpty(staDesc)) {
                continue;
            }
            //判断该巷道是否存在空位
            LocMast candidateLoc = locMastService.selectOne(new EntityWrapper<LocMast>()
                    .eq("crn_no", candidate)
                    .eq("loc_sts", "O")
                    .eq("frozen", 0)
                    .eq("deleted", 0)
                    .eq("whs_type", 1)
                    .orderBy("lev1,bay1"));
            if (Cools.isEmpty(candidateLoc)) {
                continue;
            }
            Integer count = null;
            if (!Cools.isEmpty(matnr)) {
                count = locDetlMapper.countMatnrByCrnNo(candidate, matnr); //计算每个巷道的对应物料占多少库位
            }
            if (count == null) {
                count = 0;
            }
            if (chosenCrnNo == null || count < chosenCount) {
                chosenCrnNo = candidate;
                chosenCount = count;
            }
        }
        if (chosenCrnNo == null) {
            throw new CoolException("没有空库位");
        }
        StaDesc staDesc = staDescService.selectOne(new EntityWrapper<StaDesc>()
                .eq("type_no", staDescId)
                .eq("stn_no", sourceStaNo)
                .eq("crn_no", chosenCrnNo));
        if (Cools.isEmpty(staDesc)) {
            throw new CoolException("入库路径不存在");
        }
        LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                .eq("crn_no", chosenCrnNo)
                .eq("loc_sts", "O")
                .eq("frozen", 0)
                .eq("deleted", 0)
                .eq("whs_type", 1)
                .orderBy("lev1,bay1"));
        if (Cools.isEmpty(locMast)) {
            throw new CoolException("没有空库位");
        }
        String locNo = locMast.getLocNo();
        int workNo = getWorkNo(0);
        startupDto.setWorkNo(workNo);
        startupDto.setCrnNo(chosenCrnNo);
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setLocNo(locNo);
        startupDto.setStaNo(staDesc.getCrnStn());
        return startupDto;
    }
    public StartupDto getLocNoRun4(Integer whsType, Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, Integer moveCrnNo, LocTypeDto locTypeDto, int times) {
        // 初始化参数
src/main/java/com/zy/common/web/WcsController.java
@@ -71,7 +71,8 @@
            return R.error("源站编号不能为空");
        }
        List<WaitPakin> waitPakins = null;
        if (param.getIoType() == 1) {
        WrkMast wrkMastV2 = null;
        if (param.getIoType() == 1 && !param.getSourceStaNo().equals(1070)) {
            //处理托盘码
            //3S19000677895,M22003772,3  ,KP, 0A2030  ,0A2030202306050023
            //3S箱码号      ,端子物料号 ,数量,单位,供应商编号,供应商批次号
@@ -184,6 +185,18 @@
            if (countLoc > 0 || countWrk > 0) {
                return R.error(CodeRes.EXIST_500);
            }
        }else if(param.getIoType() != 10){
            //barcode放着wms工作号用于检索任务档
            wrkMastV2 = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no",param.getBarcode()));
            if (wrkMastV2 == null) {
                return R.error("1070站点wms工作号为空");
            }
            if(wrkMastV2.getIsSuplus().equals(0)){//若为空板回库,进入空板入库流程
                param.setIoType(10);
                param.setBarcode(wrkMastV2.getBarcode());
            }else{ //若为余料
                param.setIoType(1070);
            }
        }
        if (Cools.isEmpty(param.getLocType1())){
            return R.error("高低检测信号不能为空");
@@ -201,6 +214,9 @@
                break;
            case 10://空托盘入库
                dto = emptyPlateIn(param.getSourceStaNo(), locTypeDto, param.getBarcode());
                break;
            case 1070:
                dto = startupFullPutStoreV2(param.getSourceStaNo(), wrkMastV2, locTypeDto);//1070
                break;
            default:
                break;
@@ -349,6 +365,79 @@
        return dto;
    }
    @Transactional
    public StartupDto startupFullPutStoreV2(Integer devpNo, WrkMast wrkMast, LocTypeDto locTypeDto) {
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
        StartupDto dto = commonService.getLocNoV2( 1, devpNo,wrkMast, locTypeDto);
        List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(wrkMast.getWrkNo());
        if (Cools.isEmpty(dto)) {
            throw new CoolException("没有找到库位");
        }
        if (Cools.isEmpty(wrkDetls)) {
            throw new CoolException("工作明细不存在");
        }
        int workNo = dto.getWorkNo();
        Date now = new Date();
        // 生成工作档
        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() + "");//1070
        wrkMast.setStaNo(dto.getStaNo() + "");
        wrkMast.setLocNo(dto.getLocNo());
        wrkMast.setBarcode(wrkDetls.get(0).getZpallet()); // 托盘码
        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);
        boolean res = wrkMastService.insert(wrkMast);
        if (!res) {
            throw new CoolException("保存工作档失败");
        }
        for (WrkDetl srcDetl : wrkDetls) {
            WrkDetl newDetl = new WrkDetl();
            newDetl.sync(srcDetl);
            newDetl.setWrkNo(wrkMast.getWrkNo());
            newDetl.setIoTime(wrkMast.getIoTime());
            newDetl.setAppeTime(now);
            newDetl.setModiTime(now);
            if (!wrkDetlService.insert(newDetl)) {
                throw new CoolException("保存工作明细失败");
            }
        }
        // 更新源站点信息
        sourceStaNo.setWrkNo(workNo);
        sourceStaNo.setModiTime(now);
        if (!basDevpService.updateById(sourceStaNo)){
            throw new CoolException("更新源站失败");
        }
        // 更新目标库位状态
        LocMast locMast = locMastService.selectById(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()+"目标库位已被占用");
        }
        dto.setBarcode(wrkMast.getBarcode());
        dto.setTaskNo(wrkMast.getWrkNo());
        dto.setTaskPri(wrkMast.getIoPri().intValue());
        return dto;
    }
    @Transactional
    public StartupDto emptyPlateIn(Integer devpNo, LocTypeDto locTypeDto, String barcode) {
        // 源站点状态检测
@@ -357,6 +446,9 @@
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
        StartupDto dto = commonService.getLocNo( 10, devpNo, findLocNoAttributeVo, locTypeDto);
        if(Cools.isEmpty(dto)){
            throw new CoolException("未检索到库位");
        }
        int workNo = dto.getWorkNo();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();