自动化立体仓库 - WMS系统
#
yxFwq
2025-04-01 74fd6eb7fb0322078f7946f51073f20e90231df1
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
@@ -8,11 +8,9 @@
import com.core.common.SnowflakeIdWorker;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.EmptyPlateOutParam;
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.param.*;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.OutboundAllocationUtil;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.*;
import com.zy.common.model.enums.IoWorkType;
@@ -41,10 +39,16 @@
    // 库位排号分配默认类别
    private static final int DEFAULT_ROW_NO_TYPE = 1;
    public static final List<Integer> OVER_TORN_STA_NO_LIST = new ArrayList<Integer>() {{
        add(126);add(131);add(310);add(312);
    }};
    @Autowired
    private MatService matService;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private DocTypeService docTypeService;
    @Autowired
    private WrkDetlService wrkDetlService;
    @Autowired
@@ -90,8 +94,8 @@
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(param.getDevpNo(), true);
        // 检索库位
        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);
//        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(), param.getList().get(0).getMatnr(),null,null, locTypeDto);
        // 生成工作号
        int workNo = dto.getWorkNo();
        // 生成工作档
@@ -161,19 +165,342 @@
        BasDevp staNo = basDevpService.checkSiteStatus(param.getOutSite());
        // 获取库位明细
        List<LocDetlDto> locDetlDtos = new ArrayList<>();
        List<String> locNoList = new ArrayList<>();
        for (StockOutParam.LocDetl paramLocDetl : param.getLocDetls()) {
            if (!locNoList.contains(paramLocDetl.getLocNo())){
                locNoList.add(paramLocDetl.getLocNo());
            }
            if (!Cools.isEmpty(paramLocDetl.getLocNo(), paramLocDetl.getMatnr(), paramLocDetl.getCount())) {
                LocDetl one = locDetlService.selectItem(paramLocDetl.getLocNo(), paramLocDetl.getMatnr(), paramLocDetl.getBatch());
                if (null != one) locDetlDtos.add(new LocDetlDto(one, paramLocDetl.getCount()));
                if (null != one) locDetlDtos.add(new LocDetlDto(one, paramLocDetl.getCount(), param.getOrderNo() , paramLocDetl.getPio()));
            }
        }
        List<String> locNoOtherListOne = new ArrayList<>();
        for (String locNo :locNoList) {
            //小料箱伴生出库
            if (Utils.getRow(locNo) <= 8) {
                String locNoOther = staNoOther(locNo);
                if (!locNoList.contains(locNoOther)) {
                    locNoOtherListOne.add(locNoOther);
                }
            }
        }
        if (!locDetlDtos.isEmpty()) {
            // 启动出库开始 101.出库
            stockOut(staNo, locDetlDtos, null, userId);
            LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no", locDetlDtos.get(0).getLocDetl().getLocNo()));
            if (locMast.getLocSts().equals("F") || locMast.getLocSts().equals("D") ){
                // 启动出库开始 101.出库
                stockOut(staNo, locDetlDtos, null, userId);
            }else {
                throw new CoolException("所选库位存在状态不为F、D的库位,库位号:"+locMast.getLocNo()+" 、当前状态:"+locMast.getLocSts()+"-"+locMast.getLocSts$());
            }
        } else {
            throw new CoolException("库存不存在");
        }
        for (String locNo:locNoOtherListOne){
            // 获取工作号
            int workNo = commonService.getWorkNo(WorkNoType.PAKOUT.type);
            //伴生入库工作号
            int workNoRu = commonService.getWorkNo(0);
            // 获取库位
            LocMast locMast = locMastService.selectById(locNo);
            if (Cools.isEmpty(locMast)) {
                throw new CoolException(locNo+"库位不存在");
            }
            if (locMast.getLocSts().equals("D")){
                // 获取源站
                Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                        .eq("type_no", 110)
                        .eq("stn_no", param.getOutSite())
                        .eq("crn_no", locMast.getCrnNo());
                StaDesc staDesc = staDescService.selectOne(wrapper);
                Integer sourceStaNo = staDesc.getCrnStn();
                if (Cools.isEmpty(sourceStaNo)) {
                    throw new CoolException("检索源站失败");
                }
                Date now = new Date();
                // 保存工作档
                WrkMast wrkMast = new WrkMast();
                wrkMast.setWrkNo(workNo);
                wrkMast.setIoTime(now);
                wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
                wrkMast.setIoType(110); // 入出库状态: 110.空板出库
                wrkMast.setIoPri(10D);
                wrkMast.setSourceStaNo(sourceStaNo); // 源站
                wrkMast.setStaNo(crnStaRu(locMast.getCrnNo())); // 目标站  堆垛机入库口
                wrkMast.setCrnNo(locMast.getCrnNo());
                wrkMast.setSourceLocNo(locNo); // 源库位
                wrkMast.setFullPlt("N"); // 满板:Y
                wrkMast.setPicking("N"); // 拣料
                wrkMast.setExitMk("N"); // 退出
                wrkMast.setEmptyMk("Y"); // 空板
                wrkMast.setLinkMis("N");
                wrkMast.setAppeUser(userId);
                wrkMast.setAppeTime(now);
                wrkMast.setModiUser(userId);
                wrkMast.setModiTime(now);
                wrkMast.setWorkNoOther(workNoRu);
                boolean res = wrkMastService.insert(wrkMast);
                if (!res) {
                    throw new CoolException("保存工作档失败");
                }
                // 更新库位状态 D.空板 -> R.出库预约
                if (locMast.getLocSts().equals("D")){
                    locMast.setLocSts("R");
                    locMast.setModiUser(userId);
                    locMast.setModiTime(now);
                    if (!locMastService.updateById(locMast)) {
                        throw new CoolException("更新库位状态失败");
                    }
                }
                // 生成工作档
                WrkMast wrkMastRu = new WrkMast();
                wrkMastRu.setWrkNo(workNoRu);
                wrkMastRu.setIoTime(new Date());
                wrkMastRu.setWrkSts(2L); // 工作状态:生成入库ID
                wrkMastRu.setIoType(10); // 入出库状态:10.空板入库
                wrkMastRu.setIoPri(13D); // 优先级
                wrkMastRu.setCrnNo(wrkMast.getCrnNo());
                wrkMastRu.setSourceStaNo(wrkMast.getSourceStaNo());
                wrkMastRu.setStaNo(wrkMast.getStaNo());
//        wrkMast.setLocNo(dto.getLocNo());
                wrkMastRu.setFullPlt("N"); // 满板
                wrkMastRu.setPicking("N"); // 拣料
                wrkMastRu.setExitMk("N"); // 退出
                wrkMastRu.setEmptyMk("Y"); // 空板
                wrkMastRu.setLinkMis("Y");
                wrkMastRu.setCtnType(wrkMast.getCtnType()); // 容器类型
                // 操作人员数据
                wrkMastRu.setAppeTime(new Date());
                wrkMastRu.setModiTime(new Date());
                boolean resOther = wrkMastService.insert(wrkMastRu);
                if (!resOther) {
                    throw new CoolException("保存工作档失败");
                }
            }else if (locMast.getLocSts().equals("F")){
                // 获取源站
                Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                        .eq("type_no", 101)
                        .eq("stn_no", param.getOutSite())
                        .eq("crn_no", locMast.getCrnNo());
                StaDesc staDesc = staDescService.selectOne(wrapper);
                Integer sourceStaNo = staDesc.getCrnStn();
                if (Cools.isEmpty(sourceStaNo)) {
                    throw new CoolException("检索源站失败");
                }
                Date now = new Date();
                List<LocDetl> locDetlList = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", locNo));
// 保存工作档
                WrkMast wrkMast = new WrkMast();
                wrkMast.setWrkNo(workNo);
                wrkMast.setIoTime(now);
                wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
                wrkMast.setIoType(101); // 入出库状态: 101.满板出库
                wrkMast.setIoPri(13D);
                wrkMast.setSourceStaNo(sourceStaNo); // 源站
                wrkMast.setStaNo(crnStaRu(locMast.getCrnNo())); // 目标站  堆垛机入库口
                wrkMast.setCrnNo(locMast.getCrnNo());
                wrkMast.setSourceLocNo(locNo); // 源库位
                wrkMast.setFullPlt("Y"); // 满板:Y
                wrkMast.setPicking("N"); // 拣料
                wrkMast.setExitMk("N"); // 退出
                wrkMast.setEmptyMk("N"); // 空板
                wrkMast.setLinkMis("N");
                wrkMast.setAppeUser(userId);
                wrkMast.setAppeTime(now);
                wrkMast.setModiUser(userId);
                wrkMast.setModiTime(now);
                wrkMast.setWorkNoOther(workNoRu);
                boolean res = wrkMastService.insert(wrkMast);
                if (!res) {
                    throw new CoolException("保存工作档失败");
                }
                // 更新库位状态 F.满板 -> R.出库预约
                if (locMast.getLocSts().equals("F")){
                    locMast.setLocSts("R");
                    locMast.setModiUser(userId);
                    locMast.setModiTime(now);
                    if (!locMastService.updateById(locMast)) {
                        throw new CoolException("更新库位状态失败");
                    }
                }
                List<WaitPakin> waitPakins = new ArrayList<>();
                for (LocDetl locDetl:locDetlList){
                    Mat mat = matService.selectByMatnr(locDetl.getMatnr());
                    if (Cools.isEmpty(mat)) {
                        throw new CoolException("规格添加失败,请联系管理员");
                    }
                    WaitPakin waitPakin = new WaitPakin();
                    waitPakin.sync(locDetl);
                    waitPakin.setBatch(locDetl.getBatch());       //木箱编码  //批次  唯一值  箱号
                    waitPakin.setModel(locDetl.getModel());       //MES工作号  唯一值
                    waitPakin.setIoStatus("Y");     // 入出状态
                    waitPakin.setAnfme(locDetl.getAnfme());  // 数量
                    waitPakin.setStatus("Y");    // 状态
                    waitPakin.setAppeUser(userId);
                    waitPakin.setAppeTime(now);
                    waitPakin.setModiUser(userId);
                    waitPakin.setModiTime(now);
                    waitPakin.setLocNo(null);
                    if (!waitPakinService.insert(waitPakin)) {
                        throw new CoolException("保存入库通知档失败");
                    }
                    waitPakins.add(waitPakin);
                }
                // 生成工作档
                WrkMast wrkMastRu = new WrkMast();
                wrkMastRu.setWrkNo(workNoRu);
                wrkMastRu.setIoTime(new Date());
                wrkMastRu.setWrkSts(2L); // 工作状态:生成入库ID
                wrkMastRu.setIoType(1); // 入出库状态:1.入库
                wrkMastRu.setIoPri(13D); // 优先级
                wrkMastRu.setSourceStaNo(sourceStaNo); // 源站
                wrkMastRu.setStaNo(crnStaRu(locMast.getCrnNo())); // 目标站  堆垛机入库口
                wrkMastRu.setCrnNo(locMast.getCrnNo());
                wrkMastRu.setBarcode(locMast.getBarcode()); // 托盘码
                wrkMastRu.setFullPlt("Y"); // 满板:Y
                wrkMastRu.setPicking("N"); // 拣料
                wrkMastRu.setExitMk("N"); // 退出
                wrkMastRu.setEmptyMk("N"); // 空板
                wrkMastRu.setLinkMis("Y");
                // 操作人员数据
                wrkMastRu.setAppeTime(now);
                wrkMastRu.setModiTime(now);
                boolean resOther = wrkMastService.insert(wrkMastRu);
                if (!resOther) {
                    throw new CoolException("保存工作档失败");
                }
                // 生成工作档明细
                waitPakins.forEach(waitPakin -> {
                    WrkDetl wrkDetl = new WrkDetl();
                    wrkDetl.sync(waitPakin);
                    wrkDetl.setWrkNo(wrkMastRu.getWrkNo());
                    wrkDetl.setIoTime(wrkMastRu.getIoTime());
                    wrkDetl.setAppeTime(now);
                    wrkDetl.setModiTime(now);
                    if (!wrkDetlService.insert(wrkDetl)) {
                        throw new CoolException("保存工作明细失败");
                    }
                });
            }else {
                throw new CoolException("所选库位存在状态不为D的库位,库位号:"+locMast.getLocNo()+" 、当前状态:"+locMast.getLocSts()+"-"+locMast.getLocSts$());
            }
        }
    }
    @Override
    @Transactional
    public void startupFullTakeStoreOrder(StockOutParam param, Long userId) {
        if (Cools.isEmpty(param) || Cools.isEmpty(param.getLocDetls())){
            throw new CoolException("参数为空");
        }
        if (Cools.isEmpty(param.getOrderNo())){
            throw new CoolException("订单号参数为空");
        }
        DocType docType = docTypeService.selectOrAdd("手动出库单", Boolean.FALSE);
        Order order = orderService.selectByNo(param.getOrderNo());
        if (Cools.isEmpty(order)){
            Date now = new Date();
            order = new Order(
                    String.valueOf(snowflakeIdWorker.nextId()),    // 编号[非空]
                    param.getOrderNo(),    // 订单编号
                    DateUtils.convert(now),    // 单据日期
                    docType.getDocId(),    // 单据类型
                    null,    // 项目编号
                    null,    //
                    null,    // 调拨项目编号
                    null,    // 初始票据号
                    null,    // 票据号
                    null,    // 客户编号
                    null,    // 客户
                    null,    // 联系方式
                    null,    // 操作人员
                    null,    // 合计金额
                    null,    // 优惠率
                    null,    // 优惠金额
                    null,    // 销售或采购费用合计
                    null,    // 实付金额
                    null,    // 付款类型
                    null,    // 业务员
                    null,    // 结算天数
                    null,    // 邮费支付类型
                    null,    // 邮费
                    null,    // 付款时间
                    null,    // 发货时间
                    null,    // 物流名称
                    null,    // 物流单号
//                    2L,    // 订单状态
                    1L,    // 订单状态
                    1,    // 状态
                    userId,    // 添加人员
                    now,    // 添加时间
                    userId,    // 修改人员
                    now,    // 修改时间
                    null    // 备注
            );
            if (!orderService.insert(order)) {
                throw new CoolException("保存订单主档失败");
            }
            // 单据明细档
            List<DetlDto> list = new ArrayList<>();
            List<StockOutParam.LocDetl> locDetls = param.getLocDetls();
            int i=0;
            for (StockOutParam.LocDetl locDetl : locDetls) {
                i++;
                Mat mat = matService.selectByMatnr(locDetl.getMatnr());
                if (Cools.isEmpty(mat)) {
                    throw new CoolException(locDetl.getMatnr() + "物料编码检索失败,请先添加商品");
                }
                OrderDetl orderDetl = new OrderDetl();
                orderDetl.sync(mat);
                orderDetl.setSuppCode(String.valueOf(i));  // 行号
                orderDetl.setManu(locDetl.getLocNo());  //库位号
                orderDetl.setBatch(locDetl.getBatch()); //木箱编码
                orderDetl.setAnfme(locDetl.getAnfme());//出库数量
                orderDetl.setModel(locDetl.getModel());//批次
                orderDetl.setSpecs(locDetl.getSpecs());//规格
                orderDetl.setBrand(locDetl.getBrand());//木箱类型
                orderDetl.setBarcode(locDetl.getZpallet());//木箱类型
                orderDetl.setWeight(locDetl.getWeight());
//                orderDetl.setWorkQty(locDetl.getAnfme());
                orderDetl.setWorkQty(0.0);
                orderDetl.setOrderId(order.getId());
                orderDetl.setOrderNo(order.getOrderNo());
                orderDetl.setOrigin(locDetl.getOrigin());
                orderDetl.setCreateBy(userId);
                orderDetl.setCreateTime(now);
                orderDetl.setUpdateBy(userId);
                orderDetl.setUpdateTime(now);
                orderDetl.setStatus(1);
                orderDetl.setQty(0.0D);
                if (!orderDetlService.insert(orderDetl)) {
                    throw new CoolException("生成单据明细失败,请联系管理员");
                }
            }
//            List<StockOutParam> stockOutParams = OutboundAllocationUtil.OutboundClassification(param);
//            for (StockOutParam stockOutParam : stockOutParams){
//                startupFullTakeStore(stockOutParam,userId);
//            }
        } else {
            throw new CoolException("订单号重复,订单"+param.getOrderNo()+"已存在!!!");
        }
    }
    @Override
    @Transactional
@@ -201,15 +528,23 @@
        for (OutLocDto dto : dtos) {
            // 判断入出库类型:101.全板出库 or 103.拣料出库
            if (ioWorkType == null) {
                ioType = dto.isAll() ? 101 : 103;
//                ioType = dto.isAll() ? 101 : 103;
                ioType = 101;
            } else if (ioWorkType.equals(IoWorkType.CHECK_OUT)) {
                ioType = 107;
            }
            assert ioType != null;
            // 获取库位
            LocMast locMast = locMastService.selectById(dto.getLocNo());
            Integer outSta = staNo.getDevNo();
//            //2号堆垛机全板出库站指定为204站,拣料站指定为202
//            if(locMast.getCrnNo()==2){
//                outSta = ioType == 101 ? 204 : 202;
//            }
            // 获取路径
            StaDesc staDesc = staDescService.queryCrnStn(ioType, locMast.getCrnNo(), staNo.getDevNo());
            StaDesc staDesc = staDescService.queryCrnStn(ioType, locMast.getCrnNo(), outSta);
            // 生成工作号
            int workNo = commonService.getWorkNo(WorkNoType.getWorkNoType(ioType));
            // 生成工作档
@@ -218,7 +553,7 @@
            wrkMast.setIoTime(now);
            wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
            wrkMast.setIoType(ioType); // 入出库状态
            wrkMast.setIoPri(13D); // 优先级:13
            wrkMast.setIoPri(dto.getLocDetlDtos().get(0).getPio()); // 优先级:13
            wrkMast.setCrnNo(locMast.getCrnNo());
            wrkMast.setSourceStaNo(staDesc.getCrnStn()); // 源站
            wrkMast.setStaNo(staDesc.getStnNo()); // 目标站
@@ -228,6 +563,10 @@
            wrkMast.setExitMk("N"); // 退出
            wrkMast.setEmptyMk("N"); // 空板
            wrkMast.setLinkMis("N");
            wrkMast.setSheetNo("0");
            if (!OVER_TORN_STA_NO_LIST.contains(staDesc.getStnNo())){
                wrkMast.setSheetNo("2");
            }
            wrkMast.setBarcode(locMast.getBarcode());
            wrkMast.setAppeUser(userId); // 操作人员数据
            wrkMast.setAppeTime(now);
@@ -241,7 +580,7 @@
                if (detlDto.getCount()==null || detlDto.getCount() <= 0.0D) {continue;}
                WrkDetl wrkDetl = new WrkDetl();
                wrkDetl.sync(detlDto.getLocDetl());
                wrkDetl.setOrderNo(""); // 手动出库不需要带出库存中的单据编号
                wrkDetl.setOrderNo(detlDto.getOrderNo()); // 手动出库不需要带出库存中的单据编号
                wrkDetl.setWrkNo(workNo);
                wrkDetl.setIoTime(now);
                Double anfme = ioType==101?detlDto.getLocDetl().getAnfme():detlDto.getCount();
@@ -333,7 +672,7 @@
                throw new CoolException("保存工作档明细失败");
            }
            // 修改订单明细
            if (!orderDetlService.increase(orderDetl.getOrderId(), orderDetl.getMatnr(), orderDetl.getBatch(), locDto.getAnfme())) {
            if (!orderDetlService.increaseWorkQty(orderDetl.getOrderId(), orderDetl.getMatnr(), orderDetl.getBatch(), locDto.getAnfme())) {
                throw new CoolException("修改订单明细数量失败");
            }
            orderService.updateSettle(orderDetl.getOrderId(), 2L, userId);
@@ -359,7 +698,7 @@
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
        // 检索库位
        LocTypeDto locTypeDto = new LocTypeDto(sourceStaNo);
        StartupDto dto = commonService.getLocNo(DEFAULT_ROW_NO_TYPE, 10, devpNo, null, locTypeDto, 0);
        StartupDto dto = commonService.getLocNo(DEFAULT_ROW_NO_TYPE, 10, devpNo, null,null,null, locTypeDto);
        int workNo = dto.getWorkNo();
        Date now = new Date();
        // 生成工作档
@@ -416,13 +755,26 @@
        if (Cools.isEmpty(param.getOutSite())) {
            throw new CoolException("站点不存在");
        }
        List<String> locNoOtherListOne = new ArrayList<>();
        for (String locNo : param.getLocNos()) {
            //小料箱伴生出库
            if (Utils.getRow(locNo)<=8){
                String locNoOther = staNoOther(locNo);
                if (!param.getLocNos().contains(locNoOther)){
                    locNoOtherListOne.add(locNoOther);
                }
            }
            // 获取工作号
            int workNo = commonService.getWorkNo(WorkNoType.PAKOUT.type);
            // 获取库位
            LocMast locMast = locMastService.selectById(locNo);
            if (Cools.isEmpty(locMast)) {
                throw new CoolException(locNo+"库位不存在");
            }
            if (!locMast.getLocSts().equals("D")){
                throw new CoolException("所选库位存在状态不为D的库位,库位号:"+locMast.getLocNo()+" 、当前状态:"+locMast.getLocSts()+"-"+locMast.getLocSts$());
            }
            // 获取源站
            Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
@@ -441,7 +793,7 @@
            wrkMast.setIoTime(now);
            wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
            wrkMast.setIoType(110); // 入出库状态: 110.空板出库
            wrkMast.setIoPri(10D);
            wrkMast.setIoPri(12D);
            wrkMast.setSourceStaNo(sourceStaNo); // 源站
            wrkMast.setStaNo(param.getOutSite()); // 目标站
            wrkMast.setCrnNo(locMast.getCrnNo());
@@ -469,6 +821,316 @@
                }
            }
        }
        for (String locNo:locNoOtherListOne){
            // 获取工作号
            int workNo = commonService.getWorkNo(WorkNoType.PAKOUT.type);
            //伴生入库工作号
            int workNoRu = commonService.getWorkNo(0);
            // 获取库位
            LocMast locMast = locMastService.selectById(locNo);
            if (Cools.isEmpty(locMast)) {
                throw new CoolException(locNo+"库位不存在");
            }
            if (locMast.getLocSts().equals("D")){
                // 获取源站
                Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                        .eq("type_no", 110)
                        .eq("stn_no", param.getOutSite())
                        .eq("crn_no", locMast.getCrnNo());
                StaDesc staDesc = staDescService.selectOne(wrapper);
                Integer sourceStaNo = staDesc.getCrnStn();
                if (Cools.isEmpty(sourceStaNo)) {
                    throw new CoolException("检索源站失败");
                }
                Date now = new Date();
                // 保存工作档
                WrkMast wrkMast = new WrkMast();
                wrkMast.setWrkNo(workNo);
                wrkMast.setIoTime(now);
                wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
                wrkMast.setIoType(110); // 入出库状态: 110.空板出库
                wrkMast.setIoPri(10D);
                wrkMast.setSourceStaNo(sourceStaNo); // 源站
                wrkMast.setStaNo(crnStaRu(locMast.getCrnNo())); // 目标站  堆垛机入库口
                wrkMast.setCrnNo(locMast.getCrnNo());
                wrkMast.setSourceLocNo(locNo); // 源库位
                wrkMast.setFullPlt("N"); // 满板:Y
                wrkMast.setPicking("N"); // 拣料
                wrkMast.setExitMk("N"); // 退出
                wrkMast.setEmptyMk("Y"); // 空板
                wrkMast.setLinkMis("N");
                wrkMast.setAppeUser(userId);
                wrkMast.setAppeTime(now);
                wrkMast.setModiUser(userId);
                wrkMast.setModiTime(now);
                wrkMast.setWorkNoOther(workNoRu);
                boolean res = wrkMastService.insert(wrkMast);
                if (!res) {
                    throw new CoolException("保存工作档失败");
                }
                // 更新库位状态 D.空板 -> R.出库预约
                if (locMast.getLocSts().equals("D")){
                    locMast.setLocSts("R");
                    locMast.setModiUser(userId);
                    locMast.setModiTime(now);
                    if (!locMastService.updateById(locMast)) {
                        throw new CoolException("更新库位状态失败");
                    }
                }
                // 生成工作档
                WrkMast wrkMastRu = new WrkMast();
                wrkMastRu.setWrkNo(workNoRu);
                wrkMastRu.setIoTime(new Date());
                wrkMastRu.setWrkSts(2L); // 工作状态:生成入库ID
                wrkMastRu.setIoType(10); // 入出库状态:10.空板入库
                wrkMastRu.setIoPri(13D); // 优先级
                wrkMastRu.setCrnNo(wrkMast.getCrnNo());
                wrkMastRu.setSourceStaNo(wrkMast.getSourceStaNo());
                wrkMastRu.setStaNo(wrkMast.getStaNo());
//        wrkMast.setLocNo(dto.getLocNo());
                wrkMastRu.setFullPlt("N"); // 满板
                wrkMastRu.setPicking("N"); // 拣料
                wrkMastRu.setExitMk("N"); // 退出
                wrkMastRu.setEmptyMk("Y"); // 空板
                wrkMastRu.setLinkMis("Y");
                wrkMastRu.setCtnType(wrkMast.getCtnType()); // 容器类型
                // 操作人员数据
                wrkMastRu.setAppeTime(new Date());
                wrkMastRu.setModiTime(new Date());
                boolean resOther = wrkMastService.insert(wrkMastRu);
                if (!resOther) {
                    throw new CoolException("保存工作档失败");
                }
            }else if (locMast.getLocSts().equals("F")){
                // 获取源站
                Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                        .eq("type_no", 110)
                        .eq("stn_no", param.getOutSite())
                        .eq("crn_no", locMast.getCrnNo());
                StaDesc staDesc = staDescService.selectOne(wrapper);
                Integer sourceStaNo = staDesc.getCrnStn();
                if (Cools.isEmpty(sourceStaNo)) {
                    throw new CoolException("检索源站失败");
                }
                Date now = new Date();
                List<LocDetl> locDetlList = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", locNo));
// 保存工作档
                WrkMast wrkMast = new WrkMast();
                wrkMast.setWrkNo(workNo);
                wrkMast.setIoTime(now);
                wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
                wrkMast.setIoType(101); // 入出库状态: 101.满板出库
                wrkMast.setIoPri(13D);
                wrkMast.setSourceStaNo(sourceStaNo); // 源站
                wrkMast.setStaNo(crnStaRu(locMast.getCrnNo())); // 目标站  堆垛机入库口
                wrkMast.setCrnNo(locMast.getCrnNo());
                wrkMast.setSourceLocNo(locNo); // 源库位
                wrkMast.setFullPlt("Y"); // 满板:Y
                wrkMast.setPicking("N"); // 拣料
                wrkMast.setExitMk("N"); // 退出
                wrkMast.setEmptyMk("N"); // 空板
                wrkMast.setLinkMis("N");
                wrkMast.setAppeUser(userId);
                wrkMast.setAppeTime(now);
                wrkMast.setModiUser(userId);
                wrkMast.setModiTime(now);
                wrkMast.setWorkNoOther(workNoRu);
                boolean res = wrkMastService.insert(wrkMast);
                if (!res) {
                    throw new CoolException("保存工作档失败");
                }
                // 更新库位状态 F.满板 -> R.出库预约
                if (locMast.getLocSts().equals("F")){
                    locMast.setLocSts("R");
                    locMast.setModiUser(userId);
                    locMast.setModiTime(now);
                    if (!locMastService.updateById(locMast)) {
                        throw new CoolException("更新库位状态失败");
                    }
                }
                List<WaitPakin> waitPakins = new ArrayList<>();
                for (LocDetl locDetl:locDetlList){
                    Mat mat = matService.selectByMatnr(locDetl.getMatnr());
                    if (Cools.isEmpty(mat)) {
                        throw new CoolException("规格添加失败,请联系管理员");
                    }
                    WaitPakin waitPakin = new WaitPakin();
                    waitPakin.sync(locDetl);
                    waitPakin.setBatch(locDetl.getBatch());       //木箱编码  //批次  唯一值  箱号
                    waitPakin.setModel(locDetl.getModel());       //卷号  唯一值
                    waitPakin.setIoStatus("Y");     // 入出状态
                    waitPakin.setAnfme(locDetl.getAnfme());  // 数量
                    waitPakin.setStatus("Y");    // 状态
                    waitPakin.setAppeUser(userId);
                    waitPakin.setAppeTime(now);
                    waitPakin.setModiUser(userId);
                    waitPakin.setModiTime(now);
                    waitPakin.setLocNo(null);
                    if (!waitPakinService.insert(waitPakin)) {
                        throw new CoolException("保存入库通知档失败");
                    }
                    waitPakins.add(waitPakin);
                }
                // 生成工作档
                WrkMast wrkMastRu = new WrkMast();
                wrkMastRu.setWrkNo(workNoRu);
                wrkMastRu.setIoTime(new Date());
                wrkMastRu.setWrkSts(2L); // 工作状态:生成入库ID
                wrkMastRu.setIoType(1); // 入出库状态:1.入库
                wrkMastRu.setIoPri(13D); // 优先级
                wrkMastRu.setSourceStaNo(sourceStaNo); // 源站
                wrkMastRu.setStaNo(crnStaRu(locMast.getCrnNo())); // 目标站  堆垛机入库口
                wrkMastRu.setCrnNo(locMast.getCrnNo());
                wrkMastRu.setBarcode(locMast.getBarcode()); // 托盘码
                wrkMastRu.setFullPlt("Y"); // 满板:Y
                wrkMastRu.setPicking("N"); // 拣料
                wrkMastRu.setExitMk("N"); // 退出
                wrkMastRu.setEmptyMk("N"); // 空板
                wrkMastRu.setLinkMis("Y");
                // 操作人员数据
                wrkMastRu.setAppeTime(now);
                wrkMastRu.setModiTime(now);
                boolean resOther = wrkMastService.insert(wrkMastRu);
                if (!resOther) {
                    throw new CoolException("保存工作档失败");
                }
                // 生成工作档明细
                waitPakins.forEach(waitPakin -> {
                    WrkDetl wrkDetl = new WrkDetl();
                    wrkDetl.sync(waitPakin);
                    wrkDetl.setWrkNo(wrkMastRu.getWrkNo());
                    wrkDetl.setIoTime(wrkMastRu.getIoTime());
                    wrkDetl.setAppeTime(now);
                    wrkDetl.setModiTime(now);
                    if (!wrkDetlService.insert(wrkDetl)) {
                        throw new CoolException("保存工作明细失败");
                    }
                });
            }else {
                throw new CoolException("所选库位存在状态不为D的库位,库位号:"+locMast.getLocNo()+" 、当前状态:"+locMast.getLocSts()+"-"+locMast.getLocSts$());
            }
        }
    }
    public Integer crnStaRu(Integer crnNo){
        switch (crnNo){
            case 1:
                return 153;
            case 2:
                return 145;
            default:
                return null;
        }
    }
    public String staNoOther(String locNo){
        int row = Utils.getRow(locNo);
        if (row%4==0 || row%4==1){
            return getDeepLoc2(locNo,row);
        }else {
            return getDeepLoc(locNo,row);
        }
    }
    /**
     * 获取 浅库位对应的深库位号
     */
    public static String getDeepLoc(String shallowLoc,int row) {
        if (row == 2 || row == 6) {
            return Utils.zerofill(String.valueOf(row-1), 2) + shallowLoc.substring(2);
        } else if (row == 3 || row == 7) {
            return Utils.zerofill(String.valueOf(row+1), 2) + shallowLoc.substring(2);
        }else {
            return shallowLoc;
        }
    }
    /**
     * 获取 深库位对应的浅库位号
     */
    public static String getDeepLoc2(String shallowLoc,int row) {
        if (row == 1 || row == 5) {
            return Utils.zerofill(String.valueOf(row+1), 2) + shallowLoc.substring(2);
        } else if (row == 4 || row == 8) {
            return Utils.zerofill(String.valueOf(row-1), 2) + shallowLoc.substring(2);
        }else {
            return null;
        }
    }
    @Override
    @Transactional
    public WrkMast emptyPlateOut(EmptyPlateOutParam param) {
        WrkMast wrkMast = new WrkMast();
        if (Cools.isEmpty(param.getOutSite())) {
            throw new CoolException("站点不存在");
        }
        for (String locNo : param.getLocNos()) {
            // 获取工作号
            int workNo = commonService.getWorkNo(0);
            // 获取库位
            LocMast locMast = locMastService.selectById(locNo);
            if (Cools.isEmpty(locMast)) {
                throw new CoolException(locNo+"库位不存在");
            }
            // 获取源站
            Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                    .eq("type_no", 110)
                    .eq("stn_no", param.getOutSite())
                    .eq("crn_no", locMast.getCrnNo());
            StaDesc staDesc = staDescService.selectOne(wrapper);
            Integer sourceStaNo = staDesc.getCrnStn();
            if (Cools.isEmpty(sourceStaNo)) {
                throw new CoolException("检索源站失败");
            }
            Date now = new Date();
            // 保存工作档
            wrkMast.setWrkNo(workNo);
            wrkMast.setIoTime(now);
            wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
            wrkMast.setIoType(110); // 入出库状态: 110.空板出库
            wrkMast.setIoPri(10D);
            wrkMast.setSourceStaNo(sourceStaNo); // 源站
            wrkMast.setStaNo(param.getOutSite()); // 目标站
            wrkMast.setCrnNo(locMast.getCrnNo());
            wrkMast.setSourceLocNo(locNo); // 源库位
            wrkMast.setFullPlt("N"); // 满板:Y
            wrkMast.setPicking("N"); // 拣料
            wrkMast.setExitMk("N"); // 退出
            wrkMast.setEmptyMk("Y"); // 空板
            wrkMast.setLinkMis("N");
            wrkMast.setAppeUser(1L);
            wrkMast.setAppeTime(now);
            wrkMast.setModiUser(1L);
            wrkMast.setModiTime(now);
            wrkMast.setMemo("生成自动空板出库");
            boolean res = wrkMastService.insert(wrkMast);
            if (!res) {
                throw new CoolException("保存工作档失败");
            }
            // 更新库位状态 D.空板 -> R.出库预约
            if (locMast.getLocSts().equals("D")){
                locMast.setLocSts("R");
                locMast.setModiUser(1L);
                locMast.setModiTime(now);
                if (!locMastService.updateById(locMast)) {
                    throw new CoolException("更新库位状态失败");
                }
            }
        }
        return wrkMast;
    }
    @Override
@@ -481,12 +1143,17 @@
        for (StockOutParam.LocDetl paramLocDetl : param.getLocDetls()) {
            if (!Cools.isEmpty(paramLocDetl.getLocNo(), paramLocDetl.getMatnr(), paramLocDetl.getCount())) {
                LocDetl one = locDetlService.selectItem(paramLocDetl.getLocNo(), paramLocDetl.getMatnr(), paramLocDetl.getBatch());
                if (null != one) locDetlDtos.add(new LocDetlDto(one, paramLocDetl.getCount()));
                if (null != one) locDetlDtos.add(new LocDetlDto(one, paramLocDetl.getCount(),param.getOrderNo()));
            }
        }
        if (!locDetlDtos.isEmpty()) {
            // 启动出库开始 107.盘点出库
            stockOut(staNo, locDetlDtos, IoWorkType.CHECK_OUT, userId);
            LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no", locDetlDtos.get(0).getLocDetl().getLocNo()));
            if (locMast.getLocSts().equals("F")){
                // 启动出库开始 107.盘点出库
                stockOut(staNo, locDetlDtos, IoWorkType.CHECK_OUT, userId);
            }else {
                throw new CoolException("所选库位存在状态不为F的库位,库位号:"+locMast.getLocNo()+" 、当前状态:"+locMast.getLocSts()+"-"+locMast.getLocSts$());
            }
        } else {
            throw new CoolException("库位物料不存在");
        }
@@ -503,6 +1170,9 @@
        LocMast loc = locMastService.selectById(locNo);
        if (Cools.isEmpty(loc)){
            throw new CoolException("未找到库位");
        }
        if (!loc.getLocSts().equals("O") || (!sourceLoc.getLocSts().equals("F") && !sourceLoc.getLocSts().equals("D"))){
            throw new CoolException("库位状态已改变");
        }
        if (!sourceLoc.getCrnNo().equals(loc.getCrnNo())) {
            throw new CoolException("移转库位属于不同堆垛机");
@@ -587,14 +1257,17 @@
        if (wrkMast.getWrkSts() < 4 || (wrkMast.getWrkSts() > 10 && wrkMast.getIoType()==11)) {
            wrkMast.setWrkSts(4L);
        // 出库
        } else if (wrkMast.getWrkSts() > 10) {
        } else if (wrkMast.getWrkSts() > 10 && wrkMast.getIoType()!=202) {
            wrkMast.setWrkSts(14L);
        }else if (wrkMast.getIoType()==202){
            wrkMast.setWrkSts(57L);
        }
        Date now = new Date();
        wrkMast.setCrnStrTime(DateUtils.calculate(now, 1L, TimeUnit.SECONDS, true));
        wrkMast.setCrnEndTime(now);
        wrkMast.setModiTime(now);
        wrkMast.setModiUser(userId);
        wrkMast.setSheetNo("2");
        // 完成操作人员记录
        wrkMast.setManuType("手动完成");
        if (!wrkMastService.updateById(wrkMast)) {
@@ -731,6 +1404,23 @@
        if (Cools.isEmpty(wrkMast)){
            throw new CoolException(workNo+"工作档不存在");
        }
        if (Cools.isEmpty(wrkMast.getLocNo()) && Cools.isEmpty(wrkMast.getSourceLocNo())){
            int devCount = basDevpService.selectCount(new EntityWrapper<BasDevp>().eq("wrk_no", wrkMast.getWrkNo()));
            if (devCount!=0){
                throw new CoolException("取消失败,工作号:"+wrkMast.getWrkNo()+"在输送线上运行中!!!");
            }
            try{
                wrkMastService.deleteById(wrkMast.getWrkNo());
                List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(wrkMast.getWrkNo());
                if (!wrkDetls.isEmpty()) {
//                    wrkDetlService.deleteById(wrkMast.getWrkNo());
                    wrkDetlService.delete(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo()));
                }
            }catch (Exception e){
                throw new CoolException("取消失败,异常"+e);
            }
            return;
        }
        String locNo = ""; // 待修改目标库位
        String locSts = ""; // 待修改目标库位状态
        // 入库取消(修改目标库位)
@@ -751,7 +1441,7 @@
                locMastService.updateById(locMast);
            }
        // 出库取消(修改源库位)
        } else if (wrkMast.getWrkSts() > 10 && wrkMast.getWrkSts() != 14) {
        } else if (wrkMast.getWrkSts() > 10 && wrkMast.getWrkSts() != 14 && wrkMast.getIoType()!=202) {
            locNo = wrkMast.getSourceLocNo();
            // 出库 ===>> F.在库
            if (wrkMast.getIoType() > 100 && wrkMast.getIoType() != 110) {
@@ -772,19 +1462,28 @@
                locMast.setModiUser(userId);
                locMastService.updateById(locMast);
            }
        } else if (wrkMast.getIoType()==202 || wrkMast.getIoType()==212){
        } else {
            throw new CoolException("当前工作状态无法取消");
        }
        //取消入库工作档时,查询组托表,如果有将状态改为待处理
        if(wrkMast.getIoType() == 1) {
            WaitPakin waitPakin = waitPakinService.selectOne(new EntityWrapper<WaitPakin>().eq("zpallet", wrkMast.getBarcode()));
            if (!Cools.isEmpty(waitPakin)) {
                waitPakin.setIoStatus("N");
                waitPakinService.update(waitPakin, new EntityWrapper<WaitPakin>().eq("zpallet", wrkMast.getBarcode()));
            List<WaitPakin> waitPakins=waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("zpallet", wrkMast.getBarcode()));
            for (WaitPakin waitPakin:waitPakins){
                if (!Cools.isEmpty(waitPakin)) {
                    waitPakin.setIoStatus("N");
                    waitPakin.setLocNo("");
                    waitPakinService.update(waitPakin, new EntityWrapper<WaitPakin>()
//                            .eq("order_no", waitPakin.getOrderNo())
                            .eq("zpallet",waitPakin.getZpallet())
                            .eq("matnr", waitPakin.getMatnr())
                            .eq("batch", waitPakin.getBatch()));
                }
            }
        }
        //取消出库工作档时,查询单据管理表,回滚作业中数量
        if(wrkMast.getIoType() == 101 || wrkMast.getIoType() == 103) {
            List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(wrkMast.getWrkNo());
            for (WrkDetl wrkDetl : wrkDetls) {
@@ -850,6 +1549,9 @@
            }
            // 删除工作档明细
            boolean wrkDetlRes = wrkDetlService.delete(new EntityWrapper<WrkDetl>().eq("wrk_no", workNo));
        }
        if (wrkMast.getIoType()==202 || wrkMast.getIoType()==212){
            return;
        }
        // 修改库位状态
@@ -1028,4 +1730,31 @@
        return targetLoc.getLocNo();
    }
    @Override
    @Transactional
    public void turnMatLocDetl(EmptyPlateOutParam param, Long userId) {
        Mat mat = matService.selectOne(new EntityWrapper<Mat>().eq("id", param.getMatId()));
        if (Cools.isEmpty(mat)){
            throw new CoolException("目标库位商品编码有误!");
        }
        List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("matnr", param.getLocDetls().get(0).getMatnr()));
        if (Cools.isEmpty(locDetls) || locDetls.size()<1){
            throw new CoolException("待修改商品无库存,无需修改!  规格:"+param.getLocDetls().get(0).getMatnr());
        }
        try {
            locDetlService.updateMatTurn(param.getLocDetls().get(0).getMatnr(),mat.getMatnr());
        }catch (Exception e){
            throw new CoolException("对数据库修改出错!");
        }
        for (LocDetl locDetl:locDetls){
            // 保存调整记录
            AdjDetl adjDetl = new AdjDetl();
            adjDetl.setLocNo(locDetl.getLocNo());
            adjDetl.setMatnr(mat.getMatnr());
            adjDetl.setMatnrOld(param.getLocDetls().get(0).getMatnr());
            adjDetl.setAdjQty(locDetl.getAnfme());
            adjDetlService.save(adjDetl, userId);
        }
    }
}