Explorar o código

代码生成模板修改,库位分配逻辑实现

andy %!s(int64=3) %!d(string=hai) anos
pai
achega
c4440bd2d1

+ 8 - 0
ruoyi-generator/src/main/resources/vm/java/service.java.vm

@@ -27,6 +27,14 @@ public interface I${ClassName}Service
      */
      List<${ClassName}> select${ClassName}List(${ClassName} ${className});
 
+    /**
+     * 查询${functionName}
+     *
+     * @param ${className} ${functionName}
+     * @return ${functionName}集合
+     */
+    ${ClassName} select${ClassName}ByModel(${ClassName} ${className});
+
     /**
      * 新增${functionName}
      * 

+ 17 - 0
ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm

@@ -55,6 +55,23 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service
         return ${className}Mapper.select${ClassName}List(${className});
     }
 
+    /**
+     * 查询${functionName}
+     *
+     * @param ${className} ${functionName}
+     * @return ${functionName}
+     */
+    @Override
+    public ${ClassName} select${ClassName}ByModel(${ClassName} ${className})
+    {
+        List<${ClassName}> list = ${className}Mapper.select${ClassName}List(${className});
+        if (list!=null && list.size()>0) {
+            return list.get(0);
+        } else {
+            return null;
+        }
+    }
+
     /**
      * 新增${functionName}
      * 

+ 17 - 17
ruoyi-ui/src/views/ams/locationPriority/index.vue

@@ -1,10 +1,10 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
-      <el-form-item label="路径规划名称" prop="flowName">
+      <el-form-item label="名称" prop="flowName">
         <el-input
           v-model="queryParams.flowName"
-          placeholder="请输入路径规划名称"
+          placeholder="请输入名称"
           clearable
           size="small"
           @keyup.enter.native="handleQuery"
@@ -55,7 +55,7 @@
     <el-table v-loading="loading" :data="locationPriorityList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="编号" align="center" prop="id" />
-      <el-table-column label="路径规划名称" align="center" prop="flowName" />
+      <el-table-column label="名称" align="center" prop="flowName" />
       <el-table-column label="所属区域" align="center" prop="locationZoneName" />
       <el-table-column label="状态" align="center" prop="status">
         <template slot-scope="scope">
@@ -92,13 +92,13 @@
       @pagination="getList"
     />
 
-    <!-- 添加或修改路径规划对话框 -->
+    <!-- 添加或修改对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="700px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="110px">
         <el-row>
           <el-col :span="12">
-            <el-form-item label="路径规划名称" prop="flowName">
-              <el-input v-model="form.flowName" placeholder="请输入路径规划名称" />
+            <el-form-item label="名称" prop="flowName">
+              <el-input v-model="form.flowName" placeholder="请输入名称" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -220,7 +220,7 @@
         <el-form-item label="自定义字段5" prop="userdefine5">
           <el-input v-model="form.userdefine5" placeholder="请输入自定义字段5" />
         </el-form-item>-->
-        <el-divider content-position="center">路径规划信息</el-divider>
+        <el-divider content-position="center">信息</el-divider>
         <el-row :gutter="10" class="mb8">
           <el-col :span="1.5">
             <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAddLocationPriorityDetails">添加</el-button>
@@ -300,10 +300,10 @@ export default {
       // 表单校验
       rules: {
         flowName: [
-          { required: true, message: "路径规划不能为空", trigger: "blur" }
+          { required: true, message: "名称不能为空", trigger: "blur" }
         ],
         locationZone: [
-          { required: true, message: "所属不能为空", trigger: "blur" }
+          { required: true, message: "所属区域不能为空", trigger: "blur" }
         ],
         sku: [
           { required: true, message: "物料不能为空", trigger: "blur" }
@@ -328,7 +328,7 @@ export default {
         this.skuCombo = response.data
       });
     },
-    /** 查询路径规划列表 */
+    /** 查询列表 */
     getList() {
       this.loading = true;
       listLocationPriority(this.queryParams).then(response => {
@@ -390,7 +390,7 @@ export default {
     handleAdd() {
       this.reset();
       this.open = true;
-      this.title = "添加路径规划";
+      this.title = "添加出入库策略";
       // 加载批次属性明细
       listLotattConfig().then(response => {
         this.locationPriorityDetailsList = response.data;
@@ -408,7 +408,7 @@ export default {
         this.form.locationZone = parseInt(this.form.locationZone)
         this.locationPriorityDetailsList = response.data.locationPriorityDetailsList;
         this.open = true;
-        this.title = "修改路径规划";
+        this.title = "修改出入库策略";
       });
     },
     /** 提交按钮 */
@@ -435,18 +435,18 @@ export default {
     /** 删除按钮操作 */
     handleDelete(row) {
       const ids = row.id || this.ids;
-      this.$modal.confirm('是否确认删除路径规划编号为"' + ids + '"的数据项?').then(function() {
+      this.$modal.confirm('是否确认删除出入库策略编号为"' + ids + '"的数据项?').then(function() {
         return delLocationPriority(ids);
       }).then(() => {
         this.getList();
         this.$modal.msgSuccess("删除成功");
       }).catch(() => {});
     },
-	/** 路径规划序号 */
+	/** 出入库策略序号 */
     rowLocationPriorityDetailsIndex({ row, rowIndex }) {
       row.index = rowIndex + 1;
     },
-    /** 路径规划添加按钮操作 */
+    /** 出入库策略添加按钮操作 */
     handleAddLocationPriorityDetails() {
       let obj = {};
       obj.lotattId = "";
@@ -454,10 +454,10 @@ export default {
       obj.remark = "";
       this.locationPriorityDetailsList.push(obj);
     },
-    /** 路径规划删除按钮操作 */
+    /** 出入库策略删除按钮操作 */
     handleDeleteLocationPriorityDetails() {
       if (this.checkedLocationPriorityDetails.length == 0) {
-        this.$modal.msgError("请先选择要删除的路径规划数据");
+        this.$modal.msgError("请先选择要删除的出入库策略数据");
       } else {
         const locationPriorityDetailsList = this.locationPriorityDetailsList;
         const checkedLocationPriorityDetails = this.checkedLocationPriorityDetails;

+ 27 - 0
warewms-ams/src/main/java/com/ruoyi/ams/config/domain/dto/InWarehouseDTO.java

@@ -9,9 +9,12 @@ public class InWarehouseDTO {
     private Double qty;
     private Double weight;
     private String supplier;
+    private String locationZoneFrom;
     private String locationFrom;
+    private String locationZoneTo;
     private String locationTo;
     private LotattDTO lotattDTO;
+    private Long warehouseId;
 
     public String getSku() {
         return sku;
@@ -68,4 +71,28 @@ public class InWarehouseDTO {
     public void setLotattDTO(LotattDTO lotattDTO) {
         this.lotattDTO = lotattDTO;
     }
+
+    public Long getWarehouseId() {
+        return warehouseId;
+    }
+
+    public void setWarehouseId(Long warehouseId) {
+        this.warehouseId = warehouseId;
+    }
+
+    public String getLocationZoneFrom() {
+        return locationZoneFrom;
+    }
+
+    public void setLocationZoneFrom(String locationZoneFrom) {
+        this.locationZoneFrom = locationZoneFrom;
+    }
+
+    public String getLocationZoneTo() {
+        return locationZoneTo;
+    }
+
+    public void setLocationZoneTo(String locationZoneTo) {
+        this.locationZoneTo = locationZoneTo;
+    }
 }

+ 1 - 0
warewms-ams/src/main/java/com/ruoyi/ams/config/service/IBusinessService.java

@@ -35,4 +35,5 @@ public interface IBusinessService {
      * @return
      */
     BaseLocationInfo OutInvAllocation(OutWarehouseDTO outWarehouseDTO);
+
 }

+ 33 - 3
warewms-ams/src/main/java/com/ruoyi/ams/config/service/impl/BusinessServiceImpl.java

@@ -1,9 +1,12 @@
 package com.ruoyi.ams.config.service.impl;
 
+import com.ruoyi.ams.config.domain.LocationPriorityHeader;
 import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
 import com.ruoyi.ams.config.domain.dto.InWarehouseDTO;
 import com.ruoyi.ams.config.domain.dto.OutWarehouseDTO;
+import com.ruoyi.ams.config.domain.vo.LocationPriorityHeaderVO;
 import com.ruoyi.ams.config.service.IBusinessService;
+import com.ruoyi.ams.config.service.ILocationPriorityHeaderService;
 import com.ruoyi.base.domain.BaseLocationInfo;
 import com.ruoyi.base.service.IBaseLocationInfoService;
 import com.ruoyi.common.core.domain.AjaxResult;
@@ -21,6 +24,8 @@ public class BusinessServiceImpl implements IBusinessService {
     private IBusinessService businessService;
     @Autowired
     private IBaseLocationInfoService baseLocationInfoService;
+    @Autowired
+    private ILocationPriorityHeaderService locationPriorityHeaderService;
 
     @Transactional
     @Override
@@ -28,7 +33,7 @@ public class BusinessServiceImpl implements IBusinessService {
         for (AgvCallDTO agvCallDTO : agvCallDTOList) {
             if (!StringUtils.isEmpty(agvCallDTO.getLocationFrom()) && StringUtils.isEmpty(agvCallDTO.getLocationTo())) {
                 //如果起始库位不为空、目标库位为空则表示为入库
-                
+
             } else if (StringUtils.isEmpty(agvCallDTO.getLocationFrom()) && !StringUtils.isEmpty(agvCallDTO.getLocationTo())) {
                 //如果起始库位为空、目标库位不为空则表示为出库
             } else if (!StringUtils.isEmpty(agvCallDTO.getLocationFrom()) && !StringUtils.isEmpty(agvCallDTO.getLocationTo())) {
@@ -44,10 +49,35 @@ public class BusinessServiceImpl implements IBusinessService {
          * 根据sku查询可以存放的zone
          * 根据每个zone的配置去分配可以存放的库位
          */
-        if (!StringUtils.isEmpty(inWarehouseDTO.getLocationTo())) {
+        if (!StringUtils.isEmpty(inWarehouseDTO.getLocationTo())) { //指定库位则直接返回库位
+            BaseLocationInfo baseLocationInfo = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(inWarehouseDTO.getLocationTo(), inWarehouseDTO.getWarehouseId());
+            return baseLocationInfo;
+        } else {
+            Long zoneId = null;
+            if (StringUtils.isEmpty(inWarehouseDTO.getLocationZoneTo()) && StringUtils.isEmpty(inWarehouseDTO.getLocationTo())) { //不指定目标库位和区域
+                // TODO 没有指定目标的根据sku进行匹配并进行分配
+            } else {
+                // 指定区域的
+                zoneId = Long.parseLong(inWarehouseDTO.getLocationZoneTo());
+            }
 
+            LocationPriorityHeader query = new LocationPriorityHeader();
+            query.setLocationZone(zoneId.toString());
+            List<LocationPriorityHeaderVO> list = locationPriorityHeaderService.selectLocationPriorityHeaderList(query);
+            if (list != null && list.size() > 0) {
+                //根据策略进行库位分配
+                //sku 批次属性 库存
+                
+                LocationPriorityHeaderVO locationPriorityHeaderVO = list.get(0);
+
+                return null;
+            } else {
+                // 如果指定区域没有配置策略则随意分配一个可用的空库位
+                List<BaseLocationInfo> locationInfoList = baseLocationInfoService.selectSortedLocatinListByZoneId(zoneId, inWarehouseDTO.getWarehouseId());
+                BaseLocationInfo locationInfo = baseLocationInfoService.filterLockLocation(locationInfoList);
+                return locationInfo;
+            }
         }
-        return null;
     }
 
     @Override

+ 8 - 0
warewms-base/src/main/java/com/ruoyi/base/mapper/BaseLocationInfoMapper.java

@@ -58,4 +58,12 @@ public interface BaseLocationInfoMapper
      * @return 结果
      */
      int deleteBaseLocationInfoByIds(Long[] ids);
+
+    /**
+     * 根据zoneId查询库位信息
+     * 返回结果会根据排列层进行排序
+     * @param baseLocationInfo
+     * @return
+     */
+     List<BaseLocationInfo> selectSortedLocationListByZoneId(BaseLocationInfo baseLocationInfo);
 }

+ 16 - 0
warewms-base/src/main/java/com/ruoyi/base/service/IBaseLocationInfoService.java

@@ -92,4 +92,20 @@ public interface IBaseLocationInfoService
      * @return
      */
      boolean checkIsLocation(String idOrNo, Long warehouseId);
+
+    /**
+     * 根据zoneId查询库位信息
+     * 返回结果会根据排列层进行排序
+     * @param zoneId
+     * @param warehouseId
+     * @return
+     */
+    List<BaseLocationInfo> selectSortedLocatinListByZoneId(Long zoneId,Long warehouseId);
+
+    /**
+     * 过滤锁定库位
+     * @param baseLocationInfos
+     * @return
+     */
+    BaseLocationInfo filterLockLocation(List<BaseLocationInfo> baseLocationInfos);
 }

+ 51 - 0
warewms-base/src/main/java/com/ruoyi/base/service/impl/BaseLocationInfoServiceImpl.java

@@ -1,7 +1,9 @@
 package com.ruoyi.base.service.impl;
 
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 import com.ruoyi.base.domain.BaseLocationZone;
@@ -23,6 +25,7 @@ import com.ruoyi.base.service.IBaseLocationInfoService;
  */
 @Service
 public class BaseLocationInfoServiceImpl implements IBaseLocationInfoService {
+
     @Autowired
     private BaseLocationInfoMapper baseLocationInfoMapper;
     @Autowired
@@ -162,4 +165,52 @@ public class BaseLocationInfoServiceImpl implements IBaseLocationInfoService {
             return true;
         }
     }
+
+    @Override
+    public List<BaseLocationInfo> selectSortedLocatinListByZoneId(Long zoneId, Long warehouseId) {
+        BaseLocationInfo query = new BaseLocationInfo();
+        query.setWarehouseId(warehouseId);
+        query.setZoneId(zoneId);
+        return baseLocationInfoMapper.selectSortedLocationListByZoneId(query);
+    }
+
+    @Override
+    public BaseLocationInfo filterLockLocation(List<BaseLocationInfo> baseLocationInfos) {
+        //将同一列的库位排序好
+        LinkedHashMap<String, List<BaseLocationInfo>> map = new LinkedHashMap<>();
+        for (BaseLocationInfo info : baseLocationInfos) {
+            List<BaseLocationInfo> infoList;
+            if (map.containsKey(info.getColNo())) {
+                infoList = map.get(info.getColNo());
+            } else {
+                infoList = new ArrayList<>();
+            }
+            infoList.add(info);
+            map.put(info.getColNo(), infoList);
+        }
+
+        //过滤出每列可以用的库位并进行分配
+        BaseLocationInfo currentLocation = null;
+        for (Map.Entry<String, List<BaseLocationInfo>> entry : map.entrySet()) {
+            List<BaseLocationInfo> locationInfoList = entry.getValue();
+            for (BaseLocationInfo b : locationInfoList) {
+                if (currentLocation == null) {
+                    if (b.getIsEmpty().equals("Y") && b.getStockStatus().equals("00")) {
+                        currentLocation = b;
+                    }
+                } else {
+                    //如果前面的库位已阻挡则之前的库位不可用
+                    if (!b.getIsEmpty().equals("Y") || !b.getStockStatus().equals("00")) {
+                        currentLocation = null;
+                    } else {
+                        continue;
+                    }
+                }
+            }
+            if (currentLocation != null) {
+                break;
+            }
+        }
+        return currentLocation;
+    }
 }

+ 7 - 1
warewms-base/src/main/resources/mapper/base/BaseLocationInfoMapper.xml

@@ -61,7 +61,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectBaseLocationInfoVo"/>
         where id = #{id}
     </select>
-        
+
     <insert id="insertBaseLocationInfo" parameterType="BaseLocationInfo" useGeneratedKeys="true" keyProperty="id">
         insert into base_location_info
         <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -186,4 +186,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{id}
         </foreach>
     </delete>
+
+    <select id="selectSortedLocationListByZoneId" parameterType="BaseLocationInfo" resultMap="BaseLocationInfoResult">
+        <include refid="selectBaseLocationInfoVo"/>
+        where warehouse_id = #{warehouseId} and zone_id = #{zoneId}
+        order by lpad(row_no, 11, '0'),row_index,lpad(shift_no, 11, '0'),shift_index,lpad(col_no, 11, '0'),col_index
+    </select>
 </mapper>