自动化立体仓库 - WMS系统
lty
2025-01-03 bdbf9db4113d375bb6cec9aab787db5adb14c480
#出库规则完成,盘点拣料出库测试完成
1个文件已添加
8个文件已修改
287 ■■■■■ 已修改文件
pom.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/OutTaskParam.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java 228 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/WCSReportHandler.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/OutLocDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/service/CommonService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/image/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/index.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/login.html 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -115,7 +115,7 @@
    </dependencies>
    <build>
        <finalName>wms</finalName>
        <finalName>ddthasrs</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
src/main/java/com/zy/asrs/entity/param/OutTaskParam.java
New file
@@ -0,0 +1,23 @@
package com.zy.asrs.entity.param;
import lombok.Data;
import java.util.Date;
@Data
public class OutTaskParam {
    //创建时间
    private Date createTime;
    //每次请求的唯一ID,防止重复任务
    private String uuid;
    //优先级
    private double ioPri;
    //出库口
    private int staNo;
    //托盘码
    private String barcode;
    //库位号
    private String locNo;
}
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
@@ -8,10 +8,7 @@
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.Utils;
import com.zy.common.model.*;
@@ -172,24 +169,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 +198,133 @@
            }
        }
        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(0L); // 工作状态:0.待接收
            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));
                // 生成工作档
                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("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("保存工作档明细失败");
                    }
                }
                // 修改库位状态
                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,13 +487,14 @@
            if (!locMast.getLocSts().equals("D")){
                throw new CoolException("所选库位存在状态不为D的库位,库位号:"+locMast.getLocNo()+" 、当前状态:"+locMast.getLocSts()+"-"+locMast.getLocSts$());
            }
            boolean res1 = false;
            boolean res1 = true;
            if(param.getOutSite()==100){
                res1 = true;
                res1 = false;
            }
            List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
                    .eq("lev1", locMast.getLev1())
                    .orderBy("bay1",res1));
                    .eq("bay1", locMast.getBay1())
                    .eq("lev1",locMast.getLev1())
                    .orderBy("row1",res1));
            for (LocMast locMast1 : locMasts) {
                if (locMast1.getLocNo().equals(locMast.getLocNo())) {
                    break;
src/main/java/com/zy/asrs/task/handler/WCSReportHandler.java
@@ -66,7 +66,7 @@
        }else if(wrkMast.getIoType() == 10 ){//空板入库
            workIssuedResult.setPriorityCode(12);//优先级
            task.setTaskType(0);//入库
            task.setStartNode("200");
            task.setStartNode(inDevp);
            task.setEndNode(wrkMast.getLocNo());//目标库位
        }else if(wrkMast.getIoType() == 101 ){//出库
@@ -85,7 +85,7 @@
            workIssuedResult.setPriorityCode(13);//优先级
            task.setTaskType(1);//出库
            task.setStartNode(wrkMast.getSourceLocNo());//源库位
            task.setEndNode("100");
            task.setEndNode(outDevp);
        }
        tasks.add(task);
        workIssuedResult.setTasks(tasks);
src/main/java/com/zy/common/model/OutLocDto.java
@@ -60,4 +60,6 @@
        return sameNumber == locDetls.size();
    }
    public void setPriority(double priority) {
    }
}
src/main/java/com/zy/common/service/CommonService.java
@@ -128,7 +128,7 @@
             */
            switch (rowLastnoType.getType()) {
                case 4:
                    return getLocNoRun4(whsType, staDescId, sourceStaNo, matnr, batch, grade, 4, locTypeDto, 3);
                    return getLocNoRun4(whsType, staDescId, sourceStaNo, matnr, batch, grade, 4, locTypeDto, 2);
            }
        } catch (CoolException ex) {
            log.error("入库失败,错误信息: {}", ex.getMessage(), ex);
@@ -556,9 +556,15 @@
        // 如果没有相近物料,则按规则轮询货架
        if (null == locMast) {
            LocMast locMast1 = new LocMast();
            if(sourceStaNo == 101){
            if(times != 0){
                locMast1=locMastService.selectOne(new EntityWrapper<LocMast>()
                        .eq("row1", 1)
                        .eq("loc_sts","O")
                        .eq("loc_type1", locTypeDto.getLocType1())
                        .orderBy("lev1,bay1 ASC"));
            } else {
                locMast1=locMastService.selectOne(new EntityWrapper<LocMast>()
                        .eq("row1", 8)
                        .eq("loc_sts","O")
                        .eq("loc_type1", locTypeDto.getLocType1())
                        .orderBy("lev1,bay1 ASC"));
@@ -573,13 +579,11 @@
        // 2.库位当前所属尺寸无空库位时,调整尺寸参数,向上兼容检索库位
        if (Cools.isEmpty(locMast)) {
            // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归
            times = times - 1;
            if (times >0) {
            if (times >= 0) {
                return getLocNoRun4(whsType,staDescId, sourceStaNo, matnr, batch, grade,moveCrnNo,locTypeDto,times);
            }
            log.error("系统没有空库位!!! 尺寸规格: {}, 轮询次数:{}", JSON.toJSONString(locTypeDto), times);
            log.error("系统没有空库位!!! 尺寸规格: {},", JSON.toJSONString(locTypeDto));
            throw new CoolException("没有空库位");
        }
        String locNo = locMast.getLocNo();
src/main/webapp/static/image/logo.png

src/main/webapp/views/index.html
@@ -6,7 +6,7 @@
  <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<!--  <link rel="icon" type="image/x-icon" href="../static/image/favicon.ico" />-->
  <link rel="icon" type="image/x-icon" href="../static/image/favicon.ico" />
  <link rel="stylesheet" href="../static/layui/css/layui.css" media="all">
  <link rel="stylesheet" href="../static/css/admin.css?v=318" media="all">
  <link rel="stylesheet" href="../static/css/loader.css" media="all">
@@ -26,7 +26,7 @@
  <!-- 头部 -->
  <div class="layui-header">
    <div class="layui-logo">
<!--      <img src="../static/image/logo.png" style="display: inline-block; width: 40%;height: auto">-->
      <img src="../static/image/logo.png" style="display: inline-block; width: 80%;height: auto">
      <!--          <span style="margin-top: 0; letter-spacing: 10px">中扬立库</span>-->
      <!--          <img src="../static/image/logo.svg"/>-->
      <!--          <cite>中扬 - Zoneyung</cite>-->
src/main/webapp/views/login.html
@@ -10,7 +10,7 @@
    <meta name="theme-color" content="#111111">
    <meta name="msapplication-TileImage" content="/sketch-threejs/img/common/ms_tileimage.png">
    <meta name="msapplication-TileColor" content="#111111">
<!--    <link rel="icon" type="image/x-icon" href="../static/image/favicon.ico" />-->
    <link rel="icon" type="image/x-icon" href="../static/image/favicon.ico" />
    <link rel="stylesheet" href="../static/css/font/font-awesome-4.7.0/css/font-awesome.css">
    <link rel="stylesheet" href="../static/css/main.min.css">
    <link rel="stylesheet" href="../static/css/login.css">
@@ -53,7 +53,7 @@
                    z-index: 100;
                    top: 22px;
                    left: 20px;">
<!--        <img src="../static/image/logo.png" alt="" style="width: 20%">-->
        <img src="../static/image/logo.png" alt="" style="width: 20%">
      </div>
      <div class="p-sketch-outline">
        <h2 class="p-sketch-outline__title">Automatic Storage and Retrieval System</h2>
@@ -66,8 +66,8 @@
    <!-- 侧边栏 -->
    <div id="sidebar">
      <div class="login-contain">
        <div class="login-box">
<!--          <img src="../static/image/logo.png" alt="" style="width: 80%">-->
        <div class="login-box">x
          <img src="../static/image/logo.png" alt="" style="width: 80%">
<!--          <span class="login100-form-title p-t-20 p-b-45">中扬立库</span>-->
<!--          <span class="login100-form-title p-t-20 p-b-45" style="margin: 15px 0;color: #868686;font-size: 24px">WMS</span>-->
          <div class="wrap-input100 validate-input m-b-10" data-validate="请输入用户名">