自动化立体仓库 - WMS系统
#
lty
9 小时以前 585023c7abdd062c51ecf33b6b2119f3a4fbf993
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
@@ -1,5 +1,7 @@
package com.zy.asrs.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.BaseRes;
@@ -8,10 +10,8 @@
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.entity.result.WrkCancel;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.*;
@@ -19,12 +19,16 @@
import com.zy.common.model.enums.WorkNoType;
import com.zy.common.properties.SlaveProperties;
import com.zy.common.service.CommonService;
import com.zy.common.utils.HttpHandler;
import com.zy.common.web.WcsController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -77,6 +81,14 @@
    private SlaveProperties slaveProperties;
    @Autowired
    private WaitPakinService waitPakinService;
    @Autowired
    private ApiLogService apiLogService;
    @Value("${wcs-slave.cancel}")
    private String cancel;
    @Value("${wcs-slave.url}")
    private String url;
    @Value("${wcs-slave.warehouse}")
    private String warehouse;
    @Override
    @Transactional
@@ -172,24 +184,8 @@
            }
        }
        if (!locDetlDtos.isEmpty()) {
            LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no", locDetlDtos.get(0).getLocDetl().getLocNo()));
            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                    .eq("lev1", locMast.getLev1())
                    .orderBy("bay1",false));
            for (LocMast locMast1 : locMasts) {
                if (locMast1.getLocNo().equals(locMast.getLocNo())) {
                    break;
                }
                if (locMast1.getLocSts().equals("D") || locMast1.getLocSts().equals("F")) {
                    throw new CoolException(locMast.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$());
            }
            // 启动出库开始 101.出库
            stockOut(staNo, locDetlDtos, null, userId);
        } else {
            throw new CoolException("库存不存在");
        }
@@ -217,81 +213,134 @@
            }
        }
        Integer ioType = null;
        // 生成工作档
        for (OutLocDto dto : dtos) {
            // 判断入出库类型:101.全板出库 or 103.拣料出库
            if (ioWorkType == null) {
                ioType = dto.isAll() ? 101 : 103;
            } 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;
//            }
        // 按列和层分组库位
        Map<String, List<OutLocDto>> locGroups = dtos.stream()
                .collect(Collectors.groupingBy(dto -> {
                    String column = dto.getLocNo().substring(3, 6); // 列号
                    String level = dto.getLocNo().substring(6);    // 层号
                    return column + "-" + level;                  // 组合成唯一的组标识
                }));
            // 获取路径
            StaDesc staDesc = staDescService.queryCrnStn(ioType, locMast.getCrnNo(), outSta);
            // 生成工作号
            int workNo = commonService.getWorkNo(WorkNoType.getWorkNoType(ioType));
            // 生成工作档
            WrkMast wrkMast = new WrkMast();
            wrkMast.setWrkNo(workNo);
            wrkMast.setIoTime(now);
            wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
            wrkMast.setIoType(ioType); // 入出库状态
            wrkMast.setIoPri(13D); // 优先级:13
            wrkMast.setCrnNo(locMast.getCrnNo());
            wrkMast.setSourceStaNo(staDesc.getCrnStn()); // 源站
            wrkMast.setStaNo(staDesc.getStnNo()); // 目标站
            wrkMast.setSourceLocNo(dto.getLocNo()); // 源库位
            wrkMast.setFullPlt("Y"); // 满板:Y
            wrkMast.setPicking("N"); // 拣料
            wrkMast.setExitMk("N"); // 退出
            wrkMast.setEmptyMk("N"); // 空板
            wrkMast.setLinkMis("N");
            wrkMast.setBarcode(locMast.getBarcode());
            wrkMast.setAppeUser(userId); // 操作人员数据
            wrkMast.setAppeTime(now);
            wrkMast.setModiUser(userId);
            wrkMast.setModiTime(now);
            if (!wrkMastService.insert(wrkMast)) {
                throw new CoolException("保存工作档失败,出库库位号:"+dto.getLocNo());
            }
            // 生成工作档明细
            for (LocDetlDto detlDto : dto.getLocDetlDtos()) {
                if (detlDto.getCount()==null || detlDto.getCount() <= 0.0D) {continue;}
                WrkDetl wrkDetl = new WrkDetl();
                wrkDetl.sync(detlDto.getLocDetl());
                wrkDetl.setOrderNo(""); // 手动出库不需要带出库存中的单据编号
                wrkDetl.setWrkNo(workNo);
                wrkDetl.setIoTime(now);
                Double anfme = ioType==101?detlDto.getLocDetl().getAnfme():detlDto.getCount();
                wrkDetl.setAnfme(anfme); // 数量
                wrkDetl.setAppeTime(now);
                wrkDetl.setAppeUser(userId);
                wrkDetl.setModiTime(now);
                wrkDetl.setModiUser(userId);
                if (!wrkDetlService.insert(wrkDetl)) {
                    throw new CoolException("保存工作档明细失败");
        // 遍历每组
        for (Map.Entry<String, List<OutLocDto>> entry : locGroups.entrySet()) {
            String groupKey = entry.getKey(); // 组标识,例如 "003-02" 表示第3列第2层
            List<OutLocDto> groupDtos = entry.getValue();
            // 组内优先级重新从100开始
            double priority = 100;
            // 排序组内库位(排号倒序)
            groupDtos.sort(Comparator.comparing((OutLocDto dto) -> Integer.valueOf(dto.getLocNo().substring(0, 2))).reversed());
            for (OutLocDto dto : groupDtos) {
                String locNo = dto.getLocNo();
                // 深库位规则检查,仅检查当前列和层内的前库位
                int currentRow = Integer.valueOf(locNo.substring(0, 2));
                for (int i = currentRow + 1; i <= 5; i++) { // 深库位为 1-5 排
                    String frontLoc = String.format("%02d%s", i, locNo.substring(2));
                    LocMast locMastFront = locMastService.selectOne(new EntityWrapper<LocMast>()
                            .eq("loc_no", frontLoc).eq("loc_sts", "F"));
                    if (!Cools.isEmpty(locMastFront)) {
                        throw new CoolException(locNo + " 的前库位 " + frontLoc + " 有货");
                    }
                    // 判断前库位是否有入库任务
                    WrkMast wrkMastFront = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("loc_no", frontLoc));
                    if (!Cools.isEmpty(wrkMastFront)) {
                        throw new CoolException(locNo + " 的前库位 " + frontLoc + " 有入库任务");
                    }
                }
            }
            // 修改库位状态:   F.在库 ====>>> R.出库预约/P.拣料/盘点/并板出库中
            locMast = locMastService.selectById(dto.getLocNo());
            if (locMast.getLocSts().equals("F")) {
                locMast.setLocSts(ioType==101?"R":"P");
                locMast.setModiUser(userId);
                locMast.setModiTime(now);
                if (!locMastService.updateById(locMast)) {
                    throw new CoolException("预约库位状态失败,库位号:"+dto.getLocNo());
                // 计算优先级
                dto.setPriority(priority);
                priority--; // 下一个任务优先级递增
                // 获取库位
                LocMast locMast = locMastService.selectById(dto.getLocNo());
                if (Cools.isEmpty(locMast)) {
                    throw new CoolException(dto.getLocNo() + "库位不存在");
                }
            } else {
                throw new CoolException(dto.getLocNo() + "库位不是在库状态");
                if (!locMast.getLocSts().equals("F")) {
                    throw new CoolException(dto.getLocNo() + "托盘非在库状态");
                }
                // 判断入出库类型
                if (ioWorkType == null) {
                    ioType = dto.isAll() ? 101 : 103;
                } else if (ioWorkType.equals(IoWorkType.CHECK_OUT)) {
                    ioType = 107;
                }
                assert ioType != null;
                Integer outSta = staNo.getDevNo();
                // 获取路径
                StaDesc staDesc = staDescService.queryCrnStn(ioType, locMast.getCrnNo(), outSta);
                // 生成工作号
                int workNo = commonService.getWorkNo(WorkNoType.getWorkNoType(ioType));
                String pick = ioType == 101 ? "N":"Y";
                // 生成工作档
                WrkMast wrkMast = new WrkMast();
                wrkMast.setWrkNo(workNo);
                wrkMast.setIoTime(now);
                wrkMast.setWrkSts(0L);
                wrkMast.setIoType(ioType);
                wrkMast.setIoPri(priority);
                wrkMast.setCrnNo(locMast.getCrnNo());
                wrkMast.setSourceStaNo(staDesc.getCrnStn());
                wrkMast.setStaNo(staDesc.getStnNo());
                wrkMast.setSourceLocNo(dto.getLocNo());
                wrkMast.setFullPlt("Y");
                wrkMast.setPicking(pick);
                wrkMast.setExitMk("N");
                wrkMast.setEmptyMk("N");
                wrkMast.setLinkMis("N");
                wrkMast.setBarcode(locMast.getBarcode());
                wrkMast.setAppeUser(userId);
                wrkMast.setAppeTime(now);
                wrkMast.setModiUser(userId);
                wrkMast.setModiTime(now);
                if (!wrkMastService.insert(wrkMast)) {
                    throw new CoolException("保存工作档失败,出库库位号:" + dto.getLocNo());
                }
                // 生成工作档明细
                for (LocDetlDto detlDto : dto.getLocDetlDtos()) {
                    if (detlDto.getCount() == null || detlDto.getCount() <= 0.0D) {
                        continue;
                    }
                    WrkDetl wrkDetl = new WrkDetl();
                    wrkDetl.sync(detlDto.getLocDetl());
                    wrkDetl.setOrderNo("");
                    wrkDetl.setWrkNo(workNo);
                    wrkDetl.setIoTime(now);
                    Double anfme = ioType == 101 ? detlDto.getLocDetl().getAnfme() : detlDto.getCount();
                    wrkDetl.setAnfme(anfme);
                    wrkDetl.setAppeTime(now);
                    wrkDetl.setAppeUser(userId);
                    wrkDetl.setModiTime(now);
                    wrkDetl.setModiUser(userId);
                    if (!wrkDetlService.insert(wrkDetl)) {
                        throw new CoolException("保存工作档明细失败");
                    }
                }
                // 修改库位状态
                locMast = locMastService.selectById(dto.getLocNo());
                if (locMast.getLocSts().equals("F")) {
                    locMast.setLocSts(ioType == 101 ? "R" : "P");
                    locMast.setModiUser(userId);
                    locMast.setModiTime(now);
                    if (!locMastService.updateById(locMast)) {
                        throw new CoolException("预约库位状态失败,库位号:" + dto.getLocNo());
                    }
                } else {
                    throw new CoolException(dto.getLocNo() + "库位不是在库状态");
                }
            }
        }
    }
@@ -454,9 +503,14 @@
            if (!locMast.getLocSts().equals("D")){
                throw new CoolException("所选库位存在状态不为D的库位,库位号:"+locMast.getLocNo()+" 、当前状态:"+locMast.getLocSts()+"-"+locMast.getLocSts$());
            }
            boolean res1 = true;
            if(param.getOutSite()==100){
                res1 = false;
            }
            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                    .eq("lev1", locMast.getLev1())
                    .orderBy("bay1",false));
                    .eq("bay1", locMast.getBay1())
                    .eq("lev1",locMast.getLev1())
                    .orderBy("row1",res1));
            for (LocMast locMast1 : locMasts) {
                if (locMast1.getLocNo().equals(locMast.getLocNo())) {
                    break;
@@ -480,7 +534,7 @@
            WrkMast wrkMast = new WrkMast();
            wrkMast.setWrkNo(workNo);
            wrkMast.setIoTime(now);
            wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
            wrkMast.setWrkSts(0L); // 工作状态:0.待发送
            wrkMast.setIoType(110); // 入出库状态: 110.空板出库
            wrkMast.setIoPri(10D);
            wrkMast.setSourceStaNo(sourceStaNo); // 源站
@@ -696,12 +750,13 @@
        if (wrkMast.getWrkSts() == 4 || wrkMast.getWrkSts() == 14) {
            throw new CoolException("当前工作档已完成");
        }
        // 入库 + 库位转移
        if (wrkMast.getWrkSts() < 4 || (wrkMast.getWrkSts() > 10 && wrkMast.getIoType()==11)) {
            wrkMast.setWrkSts(4L);
        // 出库
        } else if (wrkMast.getWrkSts() > 10) {
        if (wrkMast.getIoType() > 100) {
            wrkMast.setWrkSts(14L);
            // 入库 + 库位转移
        } else if (wrkMast.getIoType()==1 || wrkMast.getIoType()==10 || wrkMast.getIoType()==11) {
            wrkMast.setWrkSts(4L);
        }
        Date now = new Date();
        wrkMast.setCrnStrTime(DateUtils.calculate(now, 1L, TimeUnit.SECONDS, true));
@@ -847,7 +902,7 @@
        String locNo = ""; // 待修改目标库位
        String locSts = ""; // 待修改目标库位状态
        // 入库取消(修改目标库位)
        if (wrkMast.getWrkSts() < 4) {
        if (wrkMast.getIoType() < 100) {
            locNo = wrkMast.getLocNo();
            locSts = "O";
@@ -864,10 +919,10 @@
                locMastService.updateById(locMast);
            }
        // 出库取消(修改源库位)
        } else if (wrkMast.getWrkSts() > 10 && wrkMast.getWrkSts() != 14) {
        } else if (wrkMast.getIoType() > 100 && wrkMast.getWrkSts() != 14) {
            locNo = wrkMast.getSourceLocNo();
            // 出库 ===>> F.在库
            if (wrkMast.getIoType() > 100 && wrkMast.getIoType() != 110) {
            if (wrkMast.getIoType() == 101 || wrkMast.getIoType() == 103) {
                locSts = "F";
            // 空板出库 ===>> D.空桶/空栈板
            } else if (wrkMast.getIoType() == 110) {
@@ -899,8 +954,7 @@
                    waitPakinService.update(waitPakin, new EntityWrapper<WaitPakin>()
//                            .eq("order_no", waitPakin.getOrderNo())
                            .eq("zpallet",waitPakin.getZpallet())
                            .eq("matnr", waitPakin.getMatnr())
                            .eq("batch", waitPakin.getBatch()));
                            .eq("matnr", waitPakin.getMatnr()));
                }
            }
        }
@@ -985,6 +1039,51 @@
        if (!wrkMastRes || !locMastRes) {
            throw new CoolException("保存数据失败");
        }
        //wms取消任务 同时调用wcs任务取消接口通知wcs
        WrkCancel wrkCancel = new WrkCancel();
        Date date = new Date();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        wrkCancel.setTaskId(workNo); // 任务号
        wrkCancel.setMsgTime(dateFormat.format(date)); // 取消时间
        wrkCancel.setWarehouse(warehouse); // 仓库编码
        String response = "";
        boolean flag = false;
        try {
            response = new HttpHandler.Builder()
                    .setUri(url)
                    .setPath(cancel)
                    .setJson(JSON.toJSONString(wrkCancel))
                    .build()
                    .doPost();
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.getInteger("returnStatus") == 0){
                flag = true;
            }else {
                log.error("wms取消任务下发wcs失败--->url:{};request:{};response:{}", url+"/"+cancel, JSON.toJSONString(wrkCancel), response);
                throw new CoolException("wms取消任务下发wcs失败");
            }
        }catch (Exception e){
            log.error("fail", e);
        }finally {
            try {
                //保存接口日志
                apiLogService.save(
                        "wms下发任务给wcs",
                        url+"/"+cancel,
                        null,
                        "127.0.0.1",
                        JSON.toJSONString(wrkCancel),
                        response,
                        flag
                );
            }catch (Exception e){
                log.error("",e);
            }
        }
    }
    @Override