24 changed files with 1859 additions and 85 deletions
@ -0,0 +1,180 @@ |
|||
package org.nl.wms.basedata_manage.service.dao; |
|||
|
|||
import lombok.Data; |
|||
import org.nl.wms.warehouse_management.service.dao.GroupPlate; |
|||
|
|||
import java.math.BigDecimal; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2023/5/4 19:49 |
|||
*/ |
|||
@Data |
|||
public class StructattrVechielDto extends MdPbStoragevehicleext { |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 仓位标识 |
|||
*/ |
|||
private String id; |
|||
/** |
|||
* 载具物料id |
|||
*/ |
|||
private String vm_id; |
|||
/** |
|||
* 入库类型 |
|||
*/ |
|||
private String source_form_type; |
|||
|
|||
/** |
|||
* 仓位编码 |
|||
*/ |
|||
private String struct_code; |
|||
|
|||
/** |
|||
* 仓位名称 |
|||
*/ |
|||
private String struct_name; |
|||
|
|||
/** |
|||
* 库区标识 |
|||
*/ |
|||
private String sect_code; |
|||
|
|||
/** |
|||
* 仓库标识 |
|||
*/ |
|||
private String stor_code; |
|||
|
|||
/** |
|||
* 容量 |
|||
*/ |
|||
private Integer capacity; |
|||
|
|||
/** |
|||
* 宽度 |
|||
*/ |
|||
private Integer w; |
|||
|
|||
/** |
|||
* 高度 |
|||
*/ |
|||
private Integer h; |
|||
|
|||
/** |
|||
* 深度(长度) |
|||
*/ |
|||
private Integer l; |
|||
|
|||
/** |
|||
* 承受重量 |
|||
*/ |
|||
private Integer weight; |
|||
|
|||
/** |
|||
* 起始X坐标 |
|||
*/ |
|||
private BigDecimal xqty; |
|||
|
|||
/** |
|||
* 起始Y坐标 |
|||
*/ |
|||
private BigDecimal yqty; |
|||
|
|||
/** |
|||
* 起始Z坐标 |
|||
*/ |
|||
private BigDecimal zqty; |
|||
|
|||
/** |
|||
* 排 |
|||
*/ |
|||
private Integer row_num; |
|||
|
|||
/** |
|||
* 列 |
|||
*/ |
|||
private Integer col_num; |
|||
|
|||
/** |
|||
* 层 |
|||
*/ |
|||
private Integer layer_num; |
|||
|
|||
/** |
|||
* 块 |
|||
*/ |
|||
private Integer block_num; |
|||
|
|||
/** |
|||
* 超限货位关联的货位编号 |
|||
*/ |
|||
private String control_code; |
|||
|
|||
/** |
|||
* 创建人 |
|||
*/ |
|||
private String create_id; |
|||
|
|||
/** |
|||
* 创建人姓名 |
|||
*/ |
|||
private String create_name; |
|||
|
|||
/** |
|||
* 创建时间 |
|||
*/ |
|||
private String create_time; |
|||
|
|||
/** |
|||
* 是否临时仓位 |
|||
*/ |
|||
private Boolean is_temp; |
|||
|
|||
/** |
|||
* 是否启用 |
|||
*/ |
|||
private Boolean is_used; |
|||
|
|||
/** |
|||
* 锁定类型 |
|||
*/ |
|||
private String lock_type; |
|||
|
|||
/** |
|||
* 是否判断高度 |
|||
*/ |
|||
private String is_zdepth; |
|||
|
|||
/** |
|||
* 存储载具号 |
|||
*/ |
|||
private String vehicle_code; |
|||
|
|||
/** |
|||
* 备注 |
|||
*/ |
|||
private String remark; |
|||
|
|||
/** |
|||
* 背景图片 |
|||
*/ |
|||
private String back_ground_pic; |
|||
|
|||
/** |
|||
* 前景色 |
|||
*/ |
|||
private String front_ground_color; |
|||
|
|||
/** |
|||
* 背景色 |
|||
*/ |
|||
private String back_ground_color; |
|||
|
|||
/** |
|||
* 字体显示方向 |
|||
*/ |
|||
private String font_direction_scode; |
|||
|
|||
|
|||
} |
@ -0,0 +1,36 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="org.nl.wms.basedata_manage.service.dao.mapper.StructattrMapper"> |
|||
<select id="collectVehicle" resultType="org.nl.wms.basedata_manage.service.dao.StructattrVechielDto"> |
|||
SELECT |
|||
vm.canuse_qty, |
|||
vm.frozen_qty, |
|||
vm.update_time, |
|||
vm.material_id, |
|||
vm.pcsn, |
|||
vm.storagevehicleext_id AS vm_id, |
|||
ivt.* |
|||
FROM |
|||
st_ivt_structattr ivt |
|||
LEFT JOIN md_pb_storagevehicleext vm ON ivt.storagevehicle_code = vm.storagevehicle_code |
|||
WHERE |
|||
vm.material_id = #{material_id} |
|||
<if test="pcsn != null and pcsn != ''"> |
|||
AND vm.pcsn = #{pcsn} |
|||
</if> |
|||
AND ivt.stor_code = #{stor_code} |
|||
<if test="vehicles != null and vehicles.size() > 0"> |
|||
AND ivt.storagevehicle_code in |
|||
<foreach collection="vehicles" item="value" index="key" open="(" close=")" separator=","> |
|||
#{value} |
|||
</foreach> |
|||
</if> |
|||
<if test="is_lock != null and is_lock != ''"> |
|||
and ivt.lock_type = '00' |
|||
and vm.frozen_qty = 0 |
|||
</if> |
|||
<if test="order_by != null and order_by != ''"> |
|||
order by ${order_by} |
|||
</if> |
|||
</select> |
|||
</mapper> |
@ -0,0 +1,36 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner; |
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import org.nl.common.exception.BadRequestException; |
|||
import org.nl.config.SpringContextHolder; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.IStStrategyConfigService; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.dao.StStrategyConfig; |
|||
import org.springframework.beans.factory.InitializingBean; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.core.ResolvableType; |
|||
import java.util.List; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2024/4/6 16:13 |
|||
*/ |
|||
public abstract class Decisioner<T,P> implements InitializingBean { |
|||
|
|||
//每个策略的配置信息
|
|||
public StStrategyConfig strategyConfig; |
|||
@Autowired |
|||
private IStStrategyConfigService iStStrategyConfigService; |
|||
@Autowired |
|||
private SpringContextHolder springContextHolder; |
|||
|
|||
public abstract List<T> handler(List<T> list, P param); |
|||
|
|||
@Override |
|||
public void afterPropertiesSet(){ |
|||
String type = SpringContextHolder.getApplicationContext().getBeanNamesForType(ResolvableType.forClass(this.getClass()))[0]; |
|||
this.strategyConfig =iStStrategyConfigService.getOne(new QueryWrapper<StStrategyConfig>().eq("strategy_code",type)); |
|||
if (this.strategyConfig == null){ |
|||
throw new BadRequestException("启动失败:当前策略"+type+"没有实例信息"); |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,203 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner.impl.base; |
|||
|
|||
import com.alibaba.fastjson.JSONObject; |
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.ObjectUtils; |
|||
import org.nl.common.exception.BadRequestException; |
|||
import org.nl.common.utils.MapOf; |
|||
import org.nl.wms.basedata_manage.service.IStructattrService; |
|||
import org.nl.wms.basedata_manage.service.dao.Structattr; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.decisioner.Decisioner; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.util.CollectionUtils; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2024/4/6 16:18 |
|||
* 巷道均衡策略:XYZ: 排列层 |
|||
*/ |
|||
@Slf4j |
|||
@Service("alleyAve") |
|||
public class AlleyAveRuleHandler extends Decisioner<Structattr, JSONObject> { |
|||
|
|||
|
|||
@Autowired |
|||
private IStructattrService iStructattrService; |
|||
|
|||
|
|||
/** |
|||
* 巷道均衡策略 |
|||
* |
|||
* @param list :仓位集合 |
|||
* @param param:出入库单明细:物料相关信息、出入类型:{ ioType: 出入类型 |
|||
* materialId: 物料标识 |
|||
* ... |
|||
* } |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
@Override |
|||
public List<Structattr> handler(List<Structattr> list, JSONObject param) { |
|||
// 判断仓位是否为空
|
|||
if (CollectionUtils.isEmpty(list)) { |
|||
throw new BadRequestException("均衡策略结果:载具号:" + param.getString("vehicle_code") + "当前分配策略无可用货位"); |
|||
} |
|||
long startTime1 = System.currentTimeMillis(); |
|||
if (ObjectUtils.isNotEmpty(list)) { |
|||
//扩展库不需要均衡策略
|
|||
if ("LXBCP02".equals(list.get(0).getSect_code())) { |
|||
return list; |
|||
} |
|||
} |
|||
/** |
|||
* 根据XYZ进行均衡排序:排层列 |
|||
*/ |
|||
String configParam = this.strategyConfig.getParam(); |
|||
List<String> configList = JSONObject.parseArray(configParam, String.class); |
|||
list.sort((o1, o2) -> { |
|||
BigDecimal rowNum1 = o1.getRow_num(); |
|||
BigDecimal colNum1 = o1.getCol_num(); |
|||
BigDecimal layerNum1 = o1.getLayer_num(); |
|||
BigDecimal rowNum2 = o2.getRow_num(); |
|||
BigDecimal colNum2 = o2.getCol_num(); |
|||
BigDecimal layerNum2 = o2.getLayer_num(); |
|||
HashMap<String, Integer> of1 = MapOf.of("x", rowNum1, "y", colNum1, "z", layerNum1); |
|||
HashMap<String, Integer> of2 = MapOf.of("x", rowNum2, "y", colNum2, "z", layerNum2); |
|||
for (String sort : configList) { |
|||
if (of1.get(sort) > of2.get(sort)) { |
|||
return 1; |
|||
} |
|||
if (of1.get(sort) < of2.get(sort)) { |
|||
return -1; |
|||
} |
|||
} |
|||
return 0; |
|||
}); |
|||
List<Structattr> subList = list.subList(0, Math.min(list.size(), 10)); |
|||
Structattr result = iStructattrService.getOne( |
|||
new LambdaQueryWrapper<Structattr>() |
|||
.eq(Structattr::getStruct_code, subList.get(0).getStruct_code()) |
|||
); |
|||
if (result.getStoragevehicle_code() != null || !"00".equals(result.getLock_type())) { |
|||
log.error("均衡策略分配异常,出现流程节点完成库存延迟锁定,载具号" + param.getString("vehicle_code") + "分配异常,仓位: " + result.getStruct_code() + ",该仓位被其他任务的载具锁定或其锁类型锁住"); |
|||
subList = subList.stream().filter(r -> !r.getStruct_code().equals(result.getStruct_code())).collect(Collectors.toList()); |
|||
} |
|||
log.info("均衡策略结果:载具号:" + param.getString("vehicle_code") + "分配结果: " + subList.stream().map(Structattr::getStruct_code).collect(Collectors.toList())); |
|||
log.info("均衡策略:载具号:" + param.getString("vehicle_code") + "获取仓位耗时:{}", System.currentTimeMillis() - startTime1); |
|||
if (subList.size() == 0) { |
|||
log.error("均衡策略结果:载具号:" + param.getString("vehicle_code") + "当前分配策略货位数量为0"); |
|||
throw new BadRequestException("均衡策略结果:载具号:" + param.getString("vehicle_code") + "当前分配策略货位数量为0"); |
|||
} |
|||
return subList; |
|||
} |
|||
|
|||
// public static void main(String[] args) {
|
|||
// List<Structattr> list = new ArrayList<>();
|
|||
// for (int i =0;i<10;i++){
|
|||
// Structattr structattr = new Structattr();
|
|||
// structattr.setRow_num(new Random().nextInt(2)+1);
|
|||
// structattr.setCol_num(new Random().nextInt(10)+1);
|
|||
// structattr.setLayer_num(new Random().nextInt(2)+1);
|
|||
// list.add(structattr);
|
|||
// }
|
|||
// System.out.println(list);
|
|||
// ArrayList<String> of = ListOf.of("x", "z","y");
|
|||
// list.sort((o1, o2) -> {
|
|||
// Integer rowNum1 = o1.getRow_num();
|
|||
// Integer colNum1 = o1.getCol_num();
|
|||
// Integer layerNum1 = o1.getLayer_num();
|
|||
// Integer rowNum2 = o2.getRow_num();
|
|||
// Integer colNum2 = o2.getCol_num();
|
|||
// Integer layerNum2 = o2.getLayer_num();
|
|||
// HashMap<String,Integer> of1 = MapOf.of("x", rowNum1, "y", colNum1, "z", layerNum1);
|
|||
// HashMap<String,Integer> of2 = MapOf.of("x", rowNum2, "y", colNum2, "z", layerNum2);
|
|||
// for (String sort : of) {
|
|||
// Integer in1 = of1.get(sort);
|
|||
// Integer in2 = of2.get(sort);
|
|||
// if (in1 > in2){
|
|||
// return 1;
|
|||
// }
|
|||
// if (in1 < in2){
|
|||
// return -1;
|
|||
// }
|
|||
// }
|
|||
// return 0;
|
|||
// });
|
|||
// System.out.println(list.toString());
|
|||
// }
|
|||
|
|||
/** |
|||
* 入库策略 |
|||
* |
|||
* @param attrList :仓位集合 |
|||
* @param jsonParam:materialId :物料标识(此方法只根据物料进行匹配) |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
// private List<Structattr> inHandler(List<Structattr> attrList, PmFormData jsonParam) {
|
|||
// // in查询条件处理
|
|||
// List<Integer> blockNumIn = attrList.stream()
|
|||
// .map(Structattr::getBlock_num)
|
|||
// .distinct()
|
|||
// .collect(Collectors.toList());
|
|||
// // 查询相同巷道货位相同物料
|
|||
// List<Structattr> blockAttrList = null;
|
|||
// iStructattrService.getByQuery(new StructattrQuery());
|
|||
// // 如果为空说明这些巷道都没有相同物料的巷道,则返回所有仓位
|
|||
// if (ObjectUtil.isEmpty(blockAttrList)) {
|
|||
// return attrList;
|
|||
// }
|
|||
// // 计算每个巷道的相同物料
|
|||
// Map<Integer, List<Structattr>> collectMap = blockAttrList.stream()
|
|||
// .collect(Collectors.groupingBy(Structattr::getBlock_num));
|
|||
// // 巷道
|
|||
// int blockNum = blockAttrList.get(0).getBlock_num().intValue();
|
|||
// // 集合数量
|
|||
// int size = blockAttrList.size();
|
|||
// for (Integer num : collectMap.keySet()) {
|
|||
// int min = Math.min(size, collectMap.get(num).size());
|
|||
// if (size > min) {
|
|||
// // 返回最小的巷道
|
|||
// blockNum = num.intValue();
|
|||
// size = min;
|
|||
// }
|
|||
// }
|
|||
// // 匹配相同巷道的集合并返回
|
|||
// int finalBlockNum = blockNum;
|
|||
// return attrList.stream()
|
|||
// .filter(row -> row.getBlock_num().intValue() == finalBlockNum)
|
|||
// .collect(Collectors.toList());
|
|||
// }
|
|||
|
|||
/** |
|||
* 出库策略 - 查询物料最多的巷道 |
|||
* |
|||
* @param attrList: 仓位物料 |
|||
* @return 巷道 |
|||
*/ |
|||
// private int getMaxMaterial(List<Structattr> attrList) {
|
|||
// // 根据巷道分组
|
|||
// Map<Integer, List<Structattr>> collectMap = attrList.stream()
|
|||
// .collect(Collectors.groupingBy(Structattr::getBlock_num));
|
|||
// // 找最大物料巷道
|
|||
// // 巷道
|
|||
// int blockNum = attrList.get(0).getBlock_num().intValue();
|
|||
// // 集合数量
|
|||
// int size = 0;
|
|||
// for (Integer num : collectMap.keySet()) {
|
|||
// int max = Math.max(size, collectMap.get(num).size());
|
|||
// if (size < max) {
|
|||
// // 返回最大的巷道
|
|||
// blockNum = num.intValue();
|
|||
// size = max;
|
|||
// }
|
|||
// }
|
|||
// return blockNum;
|
|||
// }
|
|||
|
|||
} |
@ -0,0 +1,160 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner.impl.base; |
|||
|
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import org.nl.common.exception.BadRequestException; |
|||
import org.nl.wms.basedata_manage.service.IStructattrService; |
|||
import org.nl.wms.basedata_manage.service.dao.Structattr; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.decisioner.Decisioner; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2024/4/6 16:18 |
|||
* 同类型聚簇策略 |
|||
*/ |
|||
@Service("cluster") |
|||
public class ClusterRuleHandler extends Decisioner<Structattr, String> { |
|||
|
|||
/** |
|||
* 仓位服务 |
|||
*/ |
|||
@Autowired |
|||
private IStructattrService iStructattrService; |
|||
|
|||
|
|||
/** |
|||
* 同类物品集中原则 |
|||
* |
|||
* @param list :仓位集合 |
|||
* @param param:物料相关信息、出入类型:{ ioType: 出入类型 |
|||
* materialId: 物料标识 |
|||
* ... |
|||
* } |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
@Override |
|||
public List<Structattr> handler(List<Structattr> list, String param) { |
|||
// 判断仓位是否为空
|
|||
if (ObjectUtil.isEmpty(list)) { |
|||
throw new BadRequestException("仓位集合为空!"); |
|||
} |
|||
|
|||
// 判断策略类型
|
|||
JSONObject jsonParam = JSONObject.parseObject(param, JSONObject.class); |
|||
|
|||
List<Structattr> resultList = new ArrayList<>(); |
|||
|
|||
switch (jsonParam.getString("ioType")) { |
|||
case "1": |
|||
// 入库策略
|
|||
resultList = inHandler(list, jsonParam); |
|||
break; |
|||
case "2": |
|||
// 出库策略
|
|||
// resultList = outHandler(list,jsonParam);
|
|||
break; |
|||
case "3": |
|||
// 通用策略
|
|||
break; |
|||
default: |
|||
throw new BadRequestException("策略类型错误!"); |
|||
} |
|||
return resultList; |
|||
} |
|||
|
|||
/** |
|||
* 入库策略 |
|||
* |
|||
* @param attrList :仓位集合 |
|||
* @param jsonParam:materialId :物料标识(此方法只根据物料、排进行匹配) |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
private List<Structattr> inHandler(List<Structattr> attrList, JSONObject jsonParam) { |
|||
// in查询条件处理
|
|||
List<BigDecimal> rowNumIn = attrList.stream() |
|||
.map(Structattr::getRow_num) |
|||
.distinct() |
|||
.collect(Collectors.toList()); |
|||
// 查询仓位中是否有相同的物料
|
|||
List<Structattr> attrLikeList = new ArrayList<>(); |
|||
// = iStructattrService.list(
|
|||
// new QueryWrapper<Structattr>().lambda()
|
|||
// .eq(Structattr::getMaterial_id, jsonParam.getString("materialId"))
|
|||
// .in(Structattr::getRow_num, rowNumIn)
|
|||
if (ObjectUtil.isEmpty(attrLikeList)) { |
|||
return attrList; |
|||
} |
|||
// 取其中一个排进行匹配并返回
|
|||
return attrList.stream() |
|||
.filter(row -> row.getRow_num().intValue() == attrLikeList.get(0).getRow_num().intValue()) |
|||
.collect(Collectors.toList()); |
|||
} |
|||
|
|||
/** |
|||
* 出库策略 |
|||
* @param attrList :仓位物料信息 |
|||
* @param jsonParam:iostorinvdtlId : 出入库明细标识(此方法只根据明细物料匹配) |
|||
* @return List<Structattr> :需出库仓位集合 |
|||
*/ |
|||
// private List<Structattr> outHandler(List<Structattr> attrList, JSONObject jsonParam) {
|
|||
//
|
|||
// // 查询对应的出入库明细
|
|||
// StIvtIostorinvdtlIn dtlDao = iStIvtIostorinvdtlService.getById(jsonParam.getString("iostorinvdtlId"));
|
|||
//
|
|||
// // 查询传入仓位物料中的数量是否满足明细中的数量
|
|||
// List<String> vehicleCodeIn = attrList.stream()
|
|||
// .map(Structattr::getStoragevehicle_code)
|
|||
// .distinct()
|
|||
// .collect(Collectors.toList());
|
|||
//
|
|||
// List<MdPbStoragevehicleext> extList = iMdPbStoragevehicleextService.list(
|
|||
// new QueryWrapper<MdPbStoragevehicleext>().lambda()
|
|||
// .in(MdPbStoragevehicleext::getStoragevehicle_code, vehicleCodeIn)
|
|||
// );
|
|||
//
|
|||
// double attrQty = extList.stream()
|
|||
// .map(MdPbStoragevehicleext::getQty)
|
|||
// .reduce(BigDecimal.ZERO, BigDecimal::add)
|
|||
// .doubleValue();
|
|||
//
|
|||
// if (dtlDao.getUnassign_qty().doubleValue() > attrQty) {
|
|||
// // 说明不满足所需重量则全部返回
|
|||
// return attrList;
|
|||
// }
|
|||
//
|
|||
// // 需返回仓位物料集合
|
|||
// List<Structattr> resultList = new ArrayList<>();
|
|||
// // 满足所需数量: 根据巷道进行平均分配
|
|||
// double unAssingQty = dtlDao.getUnassign_qty().doubleValue();
|
|||
//
|
|||
// while (unAssingQty > 0) {
|
|||
//
|
|||
// // 添加需返回的仓位物料
|
|||
// Structattr attrDao = attrList.get(0);
|
|||
// resultList.add(attrDao);
|
|||
//
|
|||
// // 减去未分配重量
|
|||
// MdPbStoragevehicleext extDao = extList.stream()
|
|||
// .filter(row -> row.getStoragevehicle_code().equals(attrDao.getStoragevehicle_code()))
|
|||
// .findFirst().orElse(null);
|
|||
//
|
|||
// if (ObjectUtil.isEmpty(extDao)) {
|
|||
// throw new BadRequestException("未查询到载具对应的物料【"+attrDao.getStoragevehicle_code()+"】");
|
|||
// }
|
|||
//
|
|||
// unAssingQty = NumberUtil.sub(unAssingQty,extDao.getQty().doubleValue());
|
|||
//
|
|||
// // 移出此仓位物料,方便下一轮进行匹配
|
|||
// attrList.remove(attrDao);
|
|||
// }
|
|||
//
|
|||
// return resultList;
|
|||
// }
|
|||
} |
@ -0,0 +1,148 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner.impl.base; |
|||
|
|||
import com.alibaba.fastjson.JSONObject; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.ObjectUtils; |
|||
import org.nl.common.exception.BadRequestException; |
|||
import org.nl.common.utils.MapOf; |
|||
import org.nl.wms.basedata_manage.service.IStructattrService; |
|||
import org.nl.wms.basedata_manage.service.dao.StructattrVechielDto; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.decisioner.Decisioner; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.util.*; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2024/4/6 16:18 |
|||
* 先进先出策略 |
|||
*/ |
|||
@Service("fifo") |
|||
@Slf4j |
|||
public class FIFORuleHandler extends Decisioner<StructattrVechielDto, JSONObject> { |
|||
|
|||
/** |
|||
* 出入库明细服务 |
|||
*/ |
|||
@Autowired |
|||
private IStructattrService iStructattrService; |
|||
|
|||
@Override |
|||
public List<StructattrVechielDto> handler(List<StructattrVechielDto> list, JSONObject param) { |
|||
//分配数量
|
|||
int plan_qty = param.getInteger("qty"); |
|||
int finalPlan_qty = plan_qty; |
|||
//当前条件只有id,批次
|
|||
log.info("---------执行fifo出库分配规则---------"); |
|||
List<StructattrVechielDto> vechielDtos = iStructattrService.collectVechicle(MapOf.of("material_id", param.getString("material_id") |
|||
, "pcsn", param.getString("pcsn") |
|||
, "stor_code", param.getString("stor_code") |
|||
, "plan_qty", plan_qty |
|||
, "is_lock", "false" |
|||
, "order_by", "md_pb_vehicleMater.pcsn asc") |
|||
); |
|||
if (ObjectUtils.isEmpty(vechielDtos)) { |
|||
throw new BadRequestException("当前出库策略:先进先出,库存分配失败,失败原因:库存不足!"); |
|||
} |
|||
List<StructattrVechielDto> disList = new ArrayList<>(); |
|||
Map<String, List<StructattrVechielDto>> groupedMap = vechielDtos.stream() |
|||
.collect(Collectors.groupingBy( |
|||
StructattrVechielDto::getPcsn, |
|||
Collectors.collectingAndThen( |
|||
Collectors.toList(), |
|||
r -> r.stream() |
|||
.sorted(Comparator.comparing(StructattrVechielDto::getPcsn)) |
|||
.collect(Collectors.toList()) |
|||
) |
|||
)); |
|||
LinkedHashMap<String, List<StructattrVechielDto>> sortedGroupMap = groupedMap.entrySet().stream() |
|||
.sorted(Comparator.comparing(entry -> entry.getValue().get(0).getPcsn())) |
|||
.collect(Collectors.toMap( |
|||
Map.Entry::getKey, |
|||
Map.Entry::getValue, |
|||
(r, s) -> r, |
|||
LinkedHashMap::new |
|||
)); |
|||
for (Map.Entry<String, List<StructattrVechielDto>> entry : sortedGroupMap.entrySet()) { |
|||
List<StructattrVechielDto> sortedList = new ArrayList<>(entry.getValue()); |
|||
for (StructattrVechielDto structattr : sortedList) { |
|||
BigDecimal qty = structattr.getCanuse_qty() != null ? structattr.getCanuse_qty() : BigDecimal.ZERO; |
|||
BigDecimal frozen = structattr.getFrozen_qty() != null ? structattr.getFrozen_qty() : BigDecimal.ZERO; |
|||
int available = qty.subtract(frozen).intValue(); |
|||
if (available <= 0) { |
|||
continue; |
|||
} |
|||
if (finalPlan_qty <= available) { |
|||
structattr.setFrozen_qty(frozen.add(new BigDecimal(finalPlan_qty))); |
|||
disList.add(structattr); |
|||
finalPlan_qty = 0; |
|||
break; |
|||
} else { |
|||
structattr.setFrozen_qty(frozen.add(new BigDecimal(available))); |
|||
disList.add(structattr); |
|||
finalPlan_qty -= available; |
|||
} |
|||
} |
|||
if (finalPlan_qty <= 0) { |
|||
break; |
|||
} |
|||
} |
|||
return disList; |
|||
} |
|||
|
|||
/** |
|||
* 巷道均衡策略 |
|||
* |
|||
* @param list :仓位集合 |
|||
* @param param:物料相关信息、出入类型:{ ioType: 出入类型 |
|||
* materialId: 物料标识 |
|||
* ... |
|||
* } |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
// @Override
|
|||
// public List<StructattrVechielDto> handler1(List<StructattrVechielDto> list, JSONObject param) {
|
|||
// // 判断仓位是否为空
|
|||
//// if (ObjectUtil.isEmpty(list)) {
|
|||
//// throw new BadRequestException("库存分配失败:库存不足!");
|
|||
//// }
|
|||
//// List<String> need = list.stream().map(StructattrVechielDto::getStoragevehicle_code).collect(Collectors.toList());
|
|||
// //分配数量
|
|||
// int plan_qty = param.getInteger("qty");
|
|||
// //当前条件只有id,批次
|
|||
// log.info("---------执行fifo出库分配规则---------");
|
|||
// List<StructattrVechielDto> vechielDtos = iStructattrService.collectVechicle(MapOf.of("material_id", param.getString("material_id")
|
|||
// , "pcsn", param.getString("pcsn")
|
|||
// , "stor_code", param.getString("stor_code")
|
|||
// , "plan_qty", plan_qty
|
|||
// , "is_lock", "false"
|
|||
//// , "order_by","block_num asc,ABS(qty-#{plan_qty}) asc,update_time asc")
|
|||
// , "order_by","block_num asc,ABS(qty-#{plan_qty}) asc,update_time asc")
|
|||
// );
|
|||
// int finalPlan_qty = 0;
|
|||
//// vechielDtos.sort(Comparator.comparingInt(o -> (o.getQty().intValue() - finalPlan_qty)));
|
|||
// List<StructattrVechielDto> disList = new ArrayList<>();
|
|||
// for (StructattrVechielDto structattr : vechielDtos) {
|
|||
//// if (need.contains(structattr.getStoragevehicle_code()) && structattr.getFrozen_qty().intValue()==0){
|
|||
// if (structattr.getFrozen_qty().intValue()==0){
|
|||
// int cause_qty = structattr.getQty().subtract(structattr.getFrozen_qty()).intValue();
|
|||
// int sub = plan_qty - cause_qty;
|
|||
// finalPlan_qty = sub;
|
|||
// disList.add(structattr);
|
|||
// if (sub<=0){
|
|||
// structattr.setFrozen_qty(new BigDecimal(plan_qty));
|
|||
// break;
|
|||
// }
|
|||
// structattr.setFrozen_qty(new BigDecimal(cause_qty));
|
|||
// plan_qty = sub;
|
|||
// }
|
|||
// }
|
|||
// if (finalPlan_qty>0){
|
|||
// throw new BadRequestException("库存不足:物料"+param.getString("material_id")+"当前库存可用数"+(param.getInteger("qty").intValue()-finalPlan_qty));
|
|||
// }
|
|||
// return disList;
|
|||
// }
|
|||
} |
@ -0,0 +1,136 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner.impl.base; |
|||
|
|||
import com.alibaba.fastjson.JSONArray; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.nl.common.exception.BadRequestException; |
|||
import org.nl.wms.basedata_manage.service.IMdPbStoragevehicleinfoService; |
|||
import org.nl.wms.basedata_manage.service.dao.MdPbStoragevehicleinfo; |
|||
import org.nl.wms.basedata_manage.service.dao.Structattr; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.decisioner.Decisioner; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.util.CollectionUtils; |
|||
|
|||
import java.util.List; |
|||
import java.util.function.Predicate; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2024/4/6 16:18 |
|||
* 货位限位策略: 限高,限宽,限长,限重 |
|||
*/ |
|||
@Service("limitStorage") |
|||
@Slf4j |
|||
public class LimitStorageRuleHandler extends Decisioner<Structattr, JSONObject> { |
|||
|
|||
|
|||
/** |
|||
* 载具扩展属性服务服务 |
|||
*/ |
|||
@Autowired |
|||
private IMdPbStoragevehicleinfoService bmVehicleInfoService; |
|||
|
|||
/** |
|||
* 货位限位策略:根据货位的长宽高 |
|||
* |
|||
* @param list :仓位集合 |
|||
* @param param:物料相关信息、出入类型:{ ioType: 出入类型 |
|||
* materialId: 物料标识 |
|||
* ... |
|||
* } |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
@Override |
|||
public List<Structattr> handler(List<Structattr> list, JSONObject param) { |
|||
long startTime1 = System.currentTimeMillis(); |
|||
// 判断仓位是否为空
|
|||
// 判断策略类型
|
|||
String vehicleCode = param.getString("vehicle_code"); |
|||
MdPbStoragevehicleinfo vehileInfo = bmVehicleInfoService.getOne(new QueryWrapper<MdPbStoragevehicleinfo>().eq("storagevehicle_code", vehicleCode)); |
|||
if (vehileInfo == null) { |
|||
throw new BadRequestException("限位策略,当前载具信息不存在:" + vehicleCode + "!"); |
|||
} |
|||
//限位策略特殊处理
|
|||
String start_point = param.getString("start_point"); |
|||
String errorTask = param.getString("errorTask"); |
|||
log.info("限位策略:起点为" + start_point + ",载具号:" + vehicleCode + "执行策略前仓位位数为:" + list.size() + ",第一个仓位为:" + list.get(0).getStruct_code()); |
|||
if ((StringUtils.isNotBlank(start_point) || StringUtils.isNotBlank(errorTask))) { |
|||
list = list.stream().filter(struct -> struct.getCol_num().intValue() > 2).collect(Collectors.toList()); |
|||
if ("1109".equals(start_point)) { |
|||
log.info("限位策略:起点为1109,载具号:" + vehicleCode + "排除小于3排的仓位成功!"); |
|||
} |
|||
if (StringUtils.isNotBlank(errorTask)) { |
|||
log.info("限位策略:任务类型为入满或出阻挡任务,载具号:" + vehicleCode + "排除小于3排的仓位成功!"); |
|||
} |
|||
} |
|||
List<Structattr> result = inHandler(list, vehileInfo); |
|||
if (CollectionUtils.isEmpty(result)) { |
|||
log.error("限位策略:载具号:" + vehicleCode + "获取仓位失败,该高度等级对应库位数量为0!"); |
|||
throw new BadRequestException("限位策略:载具号:" + vehicleCode + "获取仓位失败,该高度等级对应库位数量为0!"); |
|||
} |
|||
log.info("限位策略:起点为" + start_point + ",载具号:" + vehicleCode + "执行策略后仓位位数为:" + result.size() + ",第一个仓位为:" + result.get(0).getStruct_code()); |
|||
log.info("限位策略:载具号:" + vehicleCode + "获取仓位耗时:{}", System.currentTimeMillis() - startTime1); |
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* 入库策略:判断货位的长宽高 |
|||
* |
|||
* @param attrList :仓位集合 |
|||
* @param vehicle :物料标识、width: 宽度、 height:高度、zdepth:深度 |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
private List<Structattr> inHandler(List<Structattr> attrList, MdPbStoragevehicleinfo vehicle) { |
|||
//限制条件:限制哪些
|
|||
List<String> limits = JSONArray.parseArray(strategyConfig.getParam(), String.class); |
|||
Predicate<Structattr> eqLimt = Structattr -> { |
|||
Boolean result = Boolean.TRUE; |
|||
if (limits.contains("h")) { |
|||
result = result && Structattr.getHeight().equals(vehicle.getVehicle_height()); |
|||
} |
|||
if (limits.contains("w")) { |
|||
result = result && Structattr.getWidth().equals(vehicle.getVehicle_width()); |
|||
} |
|||
if (limits.contains("l")) { |
|||
result = result && Structattr.getZdepth().equals(vehicle.getVehicle_long()); |
|||
} |
|||
if (limits.contains("weight")) { |
|||
result = result && Structattr.getWeight().equals(vehicle.getWeigth()); |
|||
} |
|||
return result; |
|||
}; |
|||
// 判断长宽高是否符合要求
|
|||
List<Structattr> eqLimitCollect = attrList.stream() |
|||
.filter(eqLimt) |
|||
.collect(Collectors.toList()); |
|||
if (!CollectionUtils.isEmpty(eqLimitCollect)) { |
|||
return eqLimitCollect; |
|||
} |
|||
Predicate<Structattr> ltLimt = Structattr -> { |
|||
Boolean result = Boolean.TRUE; |
|||
if (limits.contains("h")) { |
|||
result = result && Structattr.getHeight().compareTo(vehicle.getVehicle_height()) > 0; |
|||
} |
|||
if (limits.contains("w")) { |
|||
result = result && Structattr.getWidth().compareTo(vehicle.getVehicle_width()) > 0; |
|||
} |
|||
if (limits.contains("l")) { |
|||
result = result && Structattr.getZdepth().compareTo(vehicle.getVehicle_long()) > 0; |
|||
} |
|||
if (limits.contains("weight")) { |
|||
result = result && Structattr.getWeight().compareTo(vehicle.getWeigth()) > 0; |
|||
} |
|||
return result; |
|||
}; |
|||
// 判断长宽高是否符合要求
|
|||
List<Structattr> ltLimtCollect = attrList.stream() |
|||
.filter(ltLimt) |
|||
.collect(Collectors.toList()); |
|||
return ltLimtCollect; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,60 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner.impl.base; |
|||
|
|||
import com.alibaba.fastjson.JSONObject; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.nl.common.exception.BadRequestException; |
|||
import org.nl.wms.basedata_manage.service.IStructattrService; |
|||
import org.nl.wms.basedata_manage.service.dao.Structattr; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.decisioner.Decisioner; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.util.CollectionUtils; |
|||
|
|||
import java.util.Comparator; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2024/4/6 16:18 |
|||
* 就近放置策略:根据物料ABC类区分 |
|||
*/ |
|||
@Service("nearby") |
|||
@Slf4j |
|||
public class NearbyRuleHandler extends Decisioner<Structattr, JSONObject> { |
|||
//每个策略的配置信息
|
|||
/** |
|||
* 出入库明细服务 |
|||
*/ |
|||
@Autowired |
|||
private IStructattrService iStructattrService; |
|||
|
|||
/** |
|||
* 载具扩展属性服务服务 |
|||
*/ |
|||
|
|||
|
|||
/** |
|||
* 就近放置策略:根据出入库顺序进行判断 |
|||
* |
|||
* @param list :仓位集合 |
|||
* @param param:物料相关信息、出入类型:{ ioType: 出入类型 |
|||
* materialId: 物料标识 |
|||
* ... |
|||
* } |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
@Override |
|||
public List<Structattr> handler(List<Structattr> list, JSONObject param) { |
|||
if (CollectionUtils.isEmpty(list)) { |
|||
throw new BadRequestException("当前分配策略无可用货位"); |
|||
} |
|||
List<Structattr> before = list.subList(0, list.size() > 10 ? 10 : list.size()); |
|||
log.info("就近分配前:" + before.stream().map(Structattr::getStruct_code).collect(Collectors.joining(","))); |
|||
list.sort(Comparator.comparingInt(i -> i.getRow_num().add(i.getCol_num()).add(i.getLayer_num()).intValue())); |
|||
//就近分配区分出库还是入库策略
|
|||
List<Structattr> subList = list.subList(0, list.size() > 10 ? 10 : list.size()); |
|||
log.info("就近分配结果:" + subList.stream().map(Structattr::getStruct_code).collect(Collectors.joining(","))); |
|||
return subList; |
|||
} |
|||
} |
@ -0,0 +1,140 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner.impl.base; |
|||
|
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import org.nl.common.exception.BadRequestException; |
|||
import org.nl.wms.basedata_manage.service.dao.Structattr; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.decisioner.Decisioner; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.Comparator; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2024/4/6 16:18 |
|||
* 轻上重下策略 |
|||
*/ |
|||
@Service("weight") |
|||
public class WeightRuleHandler extends Decisioner<Structattr, String> { |
|||
|
|||
|
|||
/** |
|||
* 轻上重下策略:根据物品的重量 |
|||
* |
|||
* @param list :仓位集合 |
|||
* @param param:物料相关信息、出入类型:{ ioType: 出入类型 |
|||
* materialId: 物料标识 |
|||
* ... |
|||
* } |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
@Override |
|||
public List<Structattr> handler(List<Structattr> list, String param) { |
|||
// 判断仓位是否为空
|
|||
if (ObjectUtil.isEmpty(list)) { |
|||
throw new BadRequestException("仓位集合为空!"); |
|||
} |
|||
|
|||
// 判断策略类型
|
|||
JSONObject jsonParam = JSONObject.parseObject(param, JSONObject.class); |
|||
|
|||
List<Structattr> resultList = new ArrayList<>(); |
|||
|
|||
switch (jsonParam.getString("ioType")) { |
|||
case "1": |
|||
// 入库策略
|
|||
resultList = inHandler(list, jsonParam); |
|||
break; |
|||
case "2": |
|||
// 出库策略
|
|||
// resultList = outHandler(list,jsonParam);
|
|||
break; |
|||
case "3": |
|||
// 通用策略
|
|||
break; |
|||
default: |
|||
throw new BadRequestException("策略类型错误!"); |
|||
} |
|||
return resultList; |
|||
} |
|||
|
|||
/** |
|||
* 入库策略:根据重量找对应的货位 |
|||
* |
|||
* @param attrList :仓位集合 |
|||
* @param jsonParam:materialId :物料标识、weight: 重量 |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
private List<Structattr> inHandler(List<Structattr> attrList, JSONObject jsonParam) { |
|||
// 过滤对应的货位
|
|||
return attrList.stream() |
|||
.filter(row -> row.getWeight().doubleValue() <= jsonParam.getDoubleValue("weight")) |
|||
.sorted(Comparator.comparing(Structattr::getWeight)) |
|||
.collect(Collectors.toList()); |
|||
} |
|||
|
|||
/** |
|||
* 出库策略:默认出库 |
|||
* @param attrList :仓位物料信息 |
|||
* @param jsonParam:iostorinvdtlId : 出入库明细标识(此方法只根据时间匹配) |
|||
* @return List<Structattr> :需出库仓位集合 |
|||
*/ |
|||
// private List<Structattr> outHandler(List<Structattr> attrList, JSONObject jsonParam) {
|
|||
//
|
|||
// // 查询对应的出入库明细
|
|||
// StIvtIostorinvdtlIn dtlDao = iStIvtIostorinvdtlService.getById(jsonParam.getString("iostorinvdtlId"));
|
|||
//
|
|||
// // 查询传入仓位物料中的数量是否满足明细中的数量
|
|||
// List<String> vehicleCodeIn = attrList.stream()
|
|||
// .map(Structattr::getStoragevehicle_code)
|
|||
// .distinct()
|
|||
// .collect(Collectors.toList());
|
|||
//
|
|||
// // 查询对应的载具物料
|
|||
// List<MdPbStoragevehicleext> extList = iMdPbStoragevehicleextService.list(
|
|||
// new QueryWrapper<MdPbStoragevehicleext>().lambda()
|
|||
// .in(MdPbStoragevehicleext::getStoragevehicle_code, vehicleCodeIn)
|
|||
// );
|
|||
//
|
|||
// double attrQty = extList.stream()
|
|||
// .map(MdPbStoragevehicleext::getQty)
|
|||
// .reduce(BigDecimal.ZERO, BigDecimal::add)
|
|||
// .doubleValue();
|
|||
//
|
|||
// if (dtlDao.getUnassign_qty().doubleValue() > attrQty) {
|
|||
// // 说明不满足所需重量则全部返回
|
|||
// return attrList;
|
|||
// }
|
|||
//
|
|||
// // 需返回仓位物料集合
|
|||
// List<Structattr> resultList = new ArrayList<>();
|
|||
// // 满足所需数量: 根据巷道进行平均分配
|
|||
// double unAssingQty = dtlDao.getUnassign_qty().doubleValue();
|
|||
//
|
|||
// while (unAssingQty > 0) {
|
|||
//
|
|||
// // 添加需返回的仓位物料
|
|||
// Structattr attrDao = attrList.get(0);
|
|||
// resultList.add(attrDao);
|
|||
//
|
|||
// // 减去未分配重量
|
|||
// MdPbStoragevehicleext extDao = extList.stream()
|
|||
// .filter(row -> row.getStoragevehicle_code().equals(attrDao.getStoragevehicle_code()))
|
|||
// .findFirst().orElse(null);
|
|||
//
|
|||
// if (ObjectUtil.isEmpty(extDao)) {
|
|||
// throw new BadRequestException("未查询到载具对应的物料【"+attrDao.getStoragevehicle_code()+"】");
|
|||
// }
|
|||
//
|
|||
// unAssingQty = NumberUtil.sub(unAssingQty,extDao.getQty().doubleValue());
|
|||
//
|
|||
// // 移出此仓位物料,方便下一轮进行匹配
|
|||
// attrList.remove(attrDao);
|
|||
// }
|
|||
//
|
|||
// return resultList;
|
|||
// }
|
|||
} |
@ -0,0 +1,20 @@ |
|||
##货位分配原则 出入库 |
|||
|
|||
###1、上轻下重原则 |
|||
根据货物重量选择摆放位置。把重的东西放在下层,把轻放在货架上层。需要人工搬运的大型货物以腰部的高度摆放。这样提高效率、保证安全。 |
|||
###2、优先靠近出入口原则 |
|||
根据出入库频率选定位置。出入库频率高的货物应放在靠近出入口,易于作业的地方;流动性差的货物放在离出入口较远的地方;季节性物品按季节特性来选定场所摆放。 |
|||
###3、先进先出原则 |
|||
一般企业为了加快周转,先入先出一同种物料出库时,先入库的物资,需要先提取出库,以加快物料周转,从而避免因物料长期积压产生锈蚀、变形、变质及其他损坏造成的损失。因此在货位分配时要方便先进物品优先出库。 |
|||
###4、同类物品集中原则 |
|||
同一品种同一地方保管。为提高作业效率和保管效率同一物品或类似物品应在同一地方保管,提高仓储工作效率。 |
|||
###5、多巷道分布原则 |
|||
货位分配是应提高可靠性,分巷道存放一仓库有多个巷道时,同种物品分散在不同的巷道进行存放。以防止因某巷道堵塞影响某种物料的出库,造成生产中断。 |
|||
###6.超限分配原则: |
|||
对于货位超限:横向/纵向暂用多个货位.高度超限 |
|||
|
|||
##规则处理方式:责任链模式 |
|||
list->5 |
|||
1->list->2->list->3->list list.get(0) |
|||
class |
|||
List<> handler(List<货位集合>,入库物料信息) |
@ -0,0 +1,16 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner.impl.diy; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.decisioner.Decisioner; |
|||
import java.util.List; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2024/4/6 16:18 |
|||
* 自定义类处理器 |
|||
*/ |
|||
public class ClassRuleHandler extends Decisioner<String,String> { |
|||
@Override |
|||
public List<String> handler(List<String> list, String param) { |
|||
System.out.println("迭代器使用中"+this.toString()); |
|||
return null; |
|||
} |
|||
} |
@ -0,0 +1,138 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner.impl.diy; |
|||
|
|||
import com.alibaba.fastjson.JSONObject; |
|||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.collections4.CollectionUtils; |
|||
import org.nl.common.exception.BadRequestException; |
|||
import org.nl.config.SpringContextHolder; |
|||
import org.nl.wms.basedata_manage.service.IStructattrService; |
|||
import org.nl.wms.basedata_manage.service.dao.Structattr; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.decisioner.Decisioner; |
|||
import org.nl.wms.sch_manage.enums.StatusEnum; |
|||
import org.springframework.stereotype.Service; |
|||
import java.util.ArrayList; |
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
import java.util.Set; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/* |
|||
*深位优先 |
|||
* @author ZZQ |
|||
* @Date 2024/7/31 15:19 |
|||
*/ |
|||
@Service("depthPriority") |
|||
@Slf4j |
|||
public class DepthPriorityHandler extends Decisioner<Structattr, JSONObject> { |
|||
public DepthPriorityHandler() { |
|||
} |
|||
|
|||
//现场1/4排深位
|
|||
@Override |
|||
public List<Structattr> handler(List<Structattr> list, JSONObject param) { |
|||
if (CollectionUtils.isNotEmpty(list)) { |
|||
//托盘库和扩展库不需要深位判断
|
|||
if (list.get(0).getStor_code().equals(StatusEnum.STOCK_INFO.code("托盘库")) || "LXBCP02".equals(list.get(0).getSect_code())) { |
|||
return list; |
|||
} |
|||
} |
|||
long startTime1 = System.currentTimeMillis(); |
|||
List<Structattr> returnResult = new ArrayList<>(); |
|||
// 深货位
|
|||
List<Structattr> depCollect = list.stream() |
|||
.filter(a -> a.getRow_num().intValue() == 1 || a.getRow_num().intValue() == 4) |
|||
.collect(Collectors.toList()); |
|||
// 浅货位
|
|||
List<Structattr> shallowCollect = list.stream() |
|||
.filter(a -> a.getRow_num().intValue() == 2 || a.getRow_num().intValue() == 3) |
|||
.collect(Collectors.toList()); |
|||
for (Structattr r : depCollect) { |
|||
for (Structattr s : shallowCollect) { |
|||
String depCode = r.getCol_num() + "-" + r.getLayer_num(); |
|||
String shallowCode = s.getCol_num() + "-" + s.getLayer_num(); |
|||
if ((r.getRow_num().intValue() == 1 && s.getRow_num().intValue() == 2) || |
|||
(r.getRow_num().intValue() == 4 && s.getRow_num().intValue() == 3)) { |
|||
if (depCode.equals(shallowCode)) { |
|||
returnResult.add(r); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if (returnResult.size() > 0) { |
|||
if (returnResult.size() < 3) { |
|||
return getOtherStructattr(list, param, startTime1, depCollect); |
|||
} else { |
|||
log.info("深位优先策略:载具号:" + param.getString("vehicle_code") + "分配结果: 存在深位并对应浅位无货的库位,分配仓位:" + returnResult.get(0).getStruct_code()); |
|||
log.info("深位优先策略:载具号:"+param.getString("vehicle_code")+"获取深货位且浅货位无货仓位耗时:{}", System.currentTimeMillis() - startTime1); |
|||
return returnResult; |
|||
} |
|||
} else { |
|||
return getOtherStructattr(list, param, startTime1, depCollect); |
|||
} |
|||
} |
|||
|
|||
private static List<Structattr> getOtherStructattr(List<Structattr> list, JSONObject param, long startTime1, List<Structattr> depCollect) { |
|||
// if (!depCollect.isEmpty()) {
|
|||
// log.info("深位优先策略:载具号:" + param.getString("vehicle_code") + "分配结果: 存在深位无货但对应浅位有货的库位,需要移库,分配仓位:" + depCollect.get(0).getStruct_code());
|
|||
// log.info("深位优先策略:获取深货位无货且浅货位有货仓位耗时:{}", System.currentTimeMillis() - startTime1);
|
|||
// return depCollect;
|
|||
// }
|
|||
//浅货位,则需要判断对应
|
|||
IStructattrService iStructattrService = SpringContextHolder.getBean(IStructattrService.class); |
|||
if (list.get(0).getStor_code().equals(StatusEnum.STOCK_INFO.code("料箱库"))) { |
|||
List<Structattr> list1 = iStructattrService.list(new LambdaUpdateWrapper<Structattr>() |
|||
.in(Structattr::getRow_num, Arrays.asList(1, 4)) |
|||
.eq(Structattr::getStor_code, StatusEnum.STOCK_INFO.code("料箱库")) |
|||
.eq(Structattr::getIs_used, 1) |
|||
.eq(Structattr::getLock_type, StatusEnum.LOCK.code("无锁"))); |
|||
//先找2排的再找3排的
|
|||
if (!list1.isEmpty()) { |
|||
List<Structattr> combinedResult = new ArrayList<>(); |
|||
//1排
|
|||
List<Structattr> deepCollect1 = list1.stream() |
|||
.filter(a -> a.getRow_num().intValue() == 1) |
|||
.collect(Collectors.toList()); |
|||
List<Structattr> shallowCollect1 = list.stream() |
|||
.filter(a -> a.getRow_num().intValue() == 2) |
|||
.collect(Collectors.toList()); |
|||
Set<String> deepCollect1Set = deepCollect1.stream() |
|||
.map(r -> r.getCol_num() + "_" + r.getLayer_num()) |
|||
.collect(Collectors.toSet()); |
|||
List<Structattr> intersection1 = shallowCollect1.stream() |
|||
.filter(r ->deepCollect1Set.contains(r.getCol_num() + "_" + r.getLayer_num())) |
|||
.collect(Collectors.toList()); |
|||
if (!intersection1.isEmpty()) { |
|||
combinedResult.addAll(intersection1); |
|||
} else { |
|||
//4排
|
|||
List<Structattr> deepCollect2 = list1.stream() |
|||
.filter(a -> a.getRow_num().intValue() == 4) |
|||
.collect(Collectors.toList()); |
|||
List<Structattr> shallowCollect2 = list.stream() |
|||
.filter(a -> a.getRow_num().intValue() == 3) |
|||
.collect(Collectors.toList()); |
|||
Set<String> deepCollect2Set = deepCollect2.stream() |
|||
.map(r -> r.getCol_num() + "_" + r.getLayer_num()) |
|||
.collect(Collectors.toSet()); |
|||
List<Structattr> intersection2 = shallowCollect2.stream() |
|||
.filter(r -> deepCollect2Set.contains(r.getCol_num() + "_" + r.getLayer_num())) |
|||
.collect(Collectors.toList()); |
|||
combinedResult.addAll(intersection2); |
|||
} |
|||
if (CollectionUtils.isEmpty(combinedResult)) { |
|||
log.error("深位优先策略:获取深货位有货且浅货位无货仓位:载具号:" + param.getString("vehicle_code") + "获取仓位失败,该策略对应库位数量为0!"); |
|||
throw new BadRequestException("深位优先策略:获取深货位有货且浅货位无货仓位:载具号:" + param.getString("vehicle_code") + "获取仓位失败,该策略对应库位数量为0!"); |
|||
} |
|||
log.info("深位优先策略:载具号:" + param.getString("vehicle_code") + "分配结果: 深货位有货且浅货位无货仓位,无需移库,分配仓位:" + combinedResult.get(0).getStruct_code()); |
|||
log.info("深位优先策略:获取深货位有货且浅货位无货仓位耗时:{}", System.currentTimeMillis() - startTime1); |
|||
return combinedResult; |
|||
} |
|||
return list; |
|||
} else { |
|||
return list; |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,93 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner.impl.diy; |
|||
|
|||
import com.alibaba.fastjson.JSONObject; |
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.nl.common.exception.BadRequestException; |
|||
import org.nl.common.utils.MapOf; |
|||
import org.nl.wms.basedata_manage.service.IStructattrService; |
|||
import org.nl.wms.basedata_manage.service.dao.Structattr; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.decisioner.Decisioner; |
|||
import org.nl.wms.sch_manage.enums.StatusEnum; |
|||
import org.nl.wms.sch_manage.service.ISchBaseTaskService; |
|||
import org.nl.wms.sch_manage.service.dao.SchBaseTask; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.util.CollectionUtils; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.Optional; |
|||
import java.util.concurrent.CopyOnWriteArrayList; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/* |
|||
* @author ZZQ |
|||
* @Date 2024/4/6 16:18 |
|||
* 入库双叉分配测策略 |
|||
*/ |
|||
@Service("inventory") |
|||
public class InventoryRuleHandler extends Decisioner<Structattr, JSONObject> { |
|||
|
|||
|
|||
private static final Map<String, String> LINK_POINT = MapOf.of("1109", "1110", "1110", "1109"); |
|||
|
|||
//每个策略的配置信息
|
|||
/** |
|||
* 出入库明细服务 |
|||
*/ |
|||
@Autowired |
|||
private IStructattrService iStructattrService; |
|||
@Autowired |
|||
private ISchBaseTaskService taskService; |
|||
@Autowired |
|||
private IStructattrService StructattrService; |
|||
|
|||
/** |
|||
* 载具扩展属性服务服务 |
|||
*/ |
|||
|
|||
|
|||
/** |
|||
* 就近放置策略:根据出入库顺序进行判断 |
|||
* |
|||
* @param list :仓位集合 |
|||
* @param param:物料相关信息、出入类型:{ ioType: 出入类型 |
|||
* materialId: 物料标识 |
|||
* ... |
|||
* } |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
@Override |
|||
public List<Structattr> handler(List<Structattr> list, JSONObject param) { |
|||
if (CollectionUtils.isEmpty(list)) { |
|||
throw new BadRequestException("当前分配策略无可用货位"); |
|||
} |
|||
String start_point = param.getString("start_point"); |
|||
String target = LINK_POINT.get(start_point); |
|||
if (StringUtils.isNotEmpty(target)){ |
|||
LambdaQueryWrapper<SchBaseTask> lqw = new LambdaQueryWrapper<>(); |
|||
lqw.eq(SchBaseTask::getPoint_code1, target) |
|||
.lt(SchBaseTask::getTask_status, StatusEnum.FORM_STATUS.code("执行中")); |
|||
List<SchBaseTask> tasks = taskService.list(lqw); |
|||
for (SchBaseTask task : tasks) { |
|||
String point_code2 = task.getPoint_code2(); |
|||
List new_list = getInventory(list, point_code2); |
|||
if (!CollectionUtils.isEmpty(new_list)) { |
|||
return new_list; |
|||
} |
|||
} |
|||
} |
|||
return list; |
|||
} |
|||
|
|||
|
|||
private List<Structattr> getInventory(List<Structattr> list, String point_code2) { |
|||
Structattr structattr = StructattrService.getOne(new LambdaQueryWrapper<Structattr>().eq(Structattr::getStruct_code, point_code2).eq(Structattr::getIs_used, true)); |
|||
return Optional.ofNullable(list) |
|||
.orElse(new CopyOnWriteArrayList<>()) |
|||
.stream() |
|||
.filter(stru -> stru.getRow_num().equals(structattr.getRow_num()) && stru.getLayer_num().equals(structattr.getLayer_num())) |
|||
.filter(stru -> (stru.getCol_num().intValue() / 4 == structattr.getCol_num().intValue() / 4) && (((stru.getCol_num().intValue() % 4) + (structattr.getCol_num().intValue() % 4) == 2) || (stru.getCol_num().intValue() % 4) + (structattr.getCol_num().intValue() % 4) == 4)) |
|||
.collect(Collectors.toList()); |
|||
} |
|||
} |
@ -0,0 +1,69 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner.impl.diy; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.nl.wms.basedata_manage.service.dao.Structattr; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.decisioner.Decisioner; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.util.CollectionUtils; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
import java.util.stream.Stream; |
|||
|
|||
/** |
|||
* 手动过滤XYZ排信息 |
|||
* {"y":[1,2,3,104,103,102]} |
|||
*/ |
|||
@Service("passRCL") |
|||
@Slf4j |
|||
public class PassRCLHandler extends Decisioner<Structattr, JSONObject> { |
|||
//现场1/4排深位
|
|||
@Override |
|||
public List<Structattr> handler(List<Structattr> list, JSONObject param) { |
|||
String configParam = this.strategyConfig.getParam(); |
|||
JSONObject jsonP = JSONObject.parseObject(configParam); |
|||
List x = jsonP.getObject("x", List.class); |
|||
List y = jsonP.getObject("y", List.class); |
|||
List z = jsonP.getObject("z", List.class); |
|||
Stream<Structattr> stream = list.stream(); |
|||
if (!CollectionUtils.isEmpty(x)){ |
|||
stream = stream.filter(Structattr -> !x.contains(Structattr.getRow_num())); |
|||
} |
|||
if (!CollectionUtils.isEmpty(y)){ |
|||
stream = stream.filter(Structattr -> !y.contains(Structattr.getCol_num())); |
|||
} |
|||
if (!CollectionUtils.isEmpty(z)){ |
|||
stream = stream.filter(Structattr -> !z.contains(Structattr.getLayer_num())); |
|||
} |
|||
List<Structattr> collect = stream.collect(Collectors.toList()); |
|||
log.info("手动过滤XYZ排信息策略过滤数量:"+(list.size()-collect.size())); |
|||
return collect; |
|||
} |
|||
// public static void main(String[] args) {
|
|||
// List<Structattr> list = new ArrayList<>();
|
|||
// for (int i =0;i<10;i++){
|
|||
// Structattr structattr = new Structattr();
|
|||
// structattr.setRow_num(new Random().nextInt(2)+1);
|
|||
// structattr.setCol_num(new Random().nextInt(10)+1);
|
|||
// structattr.setLayer_num(new Random().nextInt(2)+1);
|
|||
// list.add(structattr);
|
|||
// }
|
|||
// System.out.println(list);
|
|||
// String configParam = "{\"z\":[2]}";
|
|||
// JSONObject jsonP = JSONObject.parseObject(configParam);
|
|||
// List x = jsonP.getObject("x", List.class);
|
|||
// List y = jsonP.getObject("y", List.class);
|
|||
// List z = jsonP.getObject("z", List.class);
|
|||
// Stream<Structattr2> stream = list.stream();
|
|||
// if (!CollectionUtils.isEmpty(x)){
|
|||
// stream = stream.filter(Structattr -> !x.contains(Structattr.getRow_num()));
|
|||
// }
|
|||
// if (!CollectionUtils.isEmpty(y)){
|
|||
// stream = stream.filter(Structattr -> !y.contains(Structattr.getCol_num()));
|
|||
// }
|
|||
// if (!CollectionUtils.isEmpty(z)){
|
|||
// stream = stream.filter(Structattr -> !z.contains(Structattr.getLayer_num()));
|
|||
// }
|
|||
// List<Structattr2> collect = stream.collect(Collectors.toList());
|
|||
// System.out.println(collect);
|
|||
// }
|
|||
} |
@ -0,0 +1,76 @@ |
|||
package org.nl.wms.decision_manage.service.strategyConfig.decisioner.impl.diy; |
|||
|
|||
import com.alibaba.fastjson.JSONObject; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.nl.common.exception.BadRequestException; |
|||
import org.nl.wms.basedata_manage.service.dao.Structattr; |
|||
import org.nl.wms.decision_manage.service.strategyConfig.decisioner.Decisioner; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.util.CollectionUtils; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.util.*; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/* |
|||
* @author GBX |
|||
* @Date 2025/2/1 16:18 |
|||
* 相同巷道,自下而上分配,左右相邻 |
|||
*/ |
|||
@Service("sameBlockNum") |
|||
@Slf4j |
|||
public class SameBlockNumRuleHandler extends Decisioner<Structattr, JSONObject> { |
|||
|
|||
|
|||
/** |
|||
* 相同巷道,自下而上分配,提高CTU放货效率 |
|||
* |
|||
* @param list :仓位集合 |
|||
* @param param:出入库单明细:物料相关信息、出入类型:{ ioType: 出入类型 |
|||
* materialId: 物料标识 |
|||
* ... |
|||
* } |
|||
* @return List<Structattr> :仓位集合 |
|||
*/ |
|||
@Override |
|||
public List<Structattr> handler(List<Structattr> list, JSONObject param) { |
|||
// 判断仓位是否为空
|
|||
if (CollectionUtils.isEmpty(list)) { |
|||
throw new BadRequestException("当前分配策略sameBlockNum无可用货位"); |
|||
} |
|||
// 1. 找出最小巷道号
|
|||
BigDecimal minBlockNum = list.stream() |
|||
.map(Structattr::getBlock_num) |
|||
.min(BigDecimal::compareTo) |
|||
.orElseThrow(() -> new BadRequestException("未找到可用的巷道")); |
|||
// 2. 筛选出这个巷道的所有结构,按列 -> 层排序
|
|||
List<Structattr> blockList = list.stream() |
|||
.filter(item -> item.getBlock_num().compareTo(minBlockNum) == 0) |
|||
.sorted(Comparator |
|||
.comparing(Structattr::getCol_num) |
|||
.thenComparing(Structattr::getLayer_num)) |
|||
.collect(Collectors.toList()); |
|||
List<Structattr> result = new ArrayList<>(); |
|||
// 3. 找出所有层号(去重 + 升序)
|
|||
Set<BigDecimal> allLayers = blockList.stream() |
|||
.map(Structattr::getLayer_num) |
|||
.collect(Collectors.toCollection(TreeSet::new)); // 自动排序
|
|||
// 4. 从小层号开始,尝试找同一列的货位
|
|||
for (BigDecimal layer : allLayers) { |
|||
List<Structattr> currentLayer = blockList.stream() |
|||
.filter(item -> item.getLayer_num().compareTo(layer) == 0) |
|||
.collect(Collectors.toList()); |
|||
if (!currentLayer.isEmpty()) { |
|||
result.addAll(currentLayer); |
|||
break; // 找到一层就跳出
|
|||
} |
|||
} |
|||
// 5. 如果没找到符合的,就用全部 blockList
|
|||
if (result.isEmpty()) { |
|||
result.addAll(blockList); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
|
|||
} |
@ -1,30 +1,246 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="org.nl.wms.pm_manage.form_data.service.dao.PmFormDataDao"> |
|||
<mapper namespace="org.nl.wms.pm_manage.form_data.service.dao.mapper.PmFormDataMapper"> |
|||
|
|||
<resultMap id="BaseResultMap" type="org.nl.wms.pm_manage.form_data.service.dao.PmFormData"> |
|||
<!-- |
|||
WARNING - This element is automatically generated by MyBatis Generator ! |
|||
Do not modify this file directly, any changes will be overwritten. |
|||
--> |
|||
<id column="id" property="id" jdbcType="BIGINT"/> |
|||
<result property="form_id" column="form_id" jdbcType="BIGINT"/> |
|||
<result property="form_type" column="form_type" jdbcType="VARCHAR"/> |
|||
<result property="status" column="status" jdbcType="VARCHAR"/> |
|||
<result property="create_name" column="create_name" jdbcType="VARCHAR"/> |
|||
<result property="create_time" column="create_time" jdbcType="TIMESTAMP"/> |
|||
<result property="material_id" column="material_id" jdbcType="BIGINT"/> |
|||
<result property="qty" column="qty" jdbcType="DECIMAL"/> |
|||
<result property="pcsn" column="pcsn" jdbcType="VARCHAR"/> |
|||
<result property="vehicle_code" column="vehicle_code" jdbcType="VARCHAR"/> |
|||
<result property="parent_id" column="parent_id" jdbcType="BIGINT"/> |
|||
<result property="form_data" column="form_data" typeHandler="org.nl.common.domain.handler.FastjsonSortTypeHandler"/> |
|||
<result property="unit_id" column="unit_id" jdbcType="BIGINT"/> |
|||
<result property="id" column="id"/> |
|||
<result property="code" column="code"/> |
|||
<result property="proc_inst_id" column="proc_inst_id"/> |
|||
<result property="source_form_type" column="source_form_type"/> |
|||
<result property="source_form_id" column="source_form_id"/> |
|||
<result property="source_form_date" column="source_form_date"/> |
|||
<result property="form_type" column="form_type"/> |
|||
<result property="status" column="status"/> |
|||
<result property="create_name" column="create_name"/> |
|||
<result property="create_time" column="create_time"/> |
|||
<result property="material_id" column="material_id"/> |
|||
<result property="qty" column="qty"/> |
|||
<result property="pcsn" column="pcsn"/> |
|||
<result property="vehicle_code" column="vehicle_code"/> |
|||
<result property="parent_id" column="parent_id"/> |
|||
<result property="form_data" column="form_data" typeHandler="org.nl.common.domain.handler.FastjsonSortTypeHandler"/> |
|||
<result property="unit_id" column="unit_id"/> |
|||
</resultMap> |
|||
<resultMap id="ResultMapWithBLOBs" type="org.nl.wms.pm_manage.form_data.service.dao.PmFormData" extends="BaseResultMap"> |
|||
<!-- |
|||
WARNING - This element is automatically generated by MyBatis Generator ! |
|||
Do not modify this file directly, any changes will be overwritten. |
|||
--> |
|||
<result property="form_data" column="form_data" typeHandler="org.nl.common.domain.handler.FastjsonSortTypeHandler"/> |
|||
|
|||
<resultMap id="dataDetail" type="org.nl.wms.pm_manage.form_data.service.dto.PmFormDataDto" > |
|||
<result property="id" column="id"/> |
|||
<result property="code" column="code"/> |
|||
<result property="proc_inst_id" column="proc_inst_id"/> |
|||
<result property="source_form_type" column="source_form_type"/> |
|||
<result property="source_form_id" column="source_form_id"/> |
|||
<result property="source_form_type" column="source_form_type"/> |
|||
<result property="form_type" column="form_type"/> |
|||
<result property="status" column="status"/> |
|||
<result property="remark" column="remark"/> |
|||
<result property="create_name" column="create_name"/> |
|||
<result property="create_time" column="create_time"/> |
|||
<result property="material_id" column="material_id"/> |
|||
<result property="qty" column="qty"/> |
|||
<result property="assign_qty" column="assign_qty"/> |
|||
<result property="plan_qty" column="plan_qty"/> |
|||
<result property="pcsn" column="pcsn"/> |
|||
<result property="material_code" column="material_code"/> |
|||
<result property="material_name" column="material_name"/> |
|||
<result property="material_spec" column="material_spec"/> |
|||
<result property="net_weight" column="net_weight"/> |
|||
<result property="vehicle_code" column="vehicle_code"/> |
|||
<result property="vehicle_id" column="vehicle_id"/> |
|||
<result property="parent_id" column="parent_id"/> |
|||
<result property="form_data" column="form_data" typeHandler="org.nl.common.domain.handler.FastjsonSortTypeHandler"/> |
|||
<result property="unit_id" column="unit_id"/> |
|||
<result property="unit_name" column="unit_name"/> |
|||
<!-- <result property="HasChildren" column="HasChildren"/>--> |
|||
</resultMap> |
|||
|
|||
<select id="query" resultMap="BaseResultMap"> |
|||
SELECT |
|||
child.* |
|||
FROM |
|||
pm_form_data child |
|||
<where> |
|||
<if test="query.form_type != null and query.form_type != ''"> |
|||
and form_type = #{query.form_type} |
|||
</if> |
|||
<if test="query.form_query != null and query.form_query.size() > 0"> |
|||
<foreach collection="query.form_query" item="value" index="key" > |
|||
<if test="value != null and value != ''"> |
|||
and JSON_CONTAINS(child.form_data, '{"${key}":"${value}"}') |
|||
</if> |
|||
</foreach> |
|||
</if> |
|||
</where> |
|||
</select> |
|||
<select id="queryTree" resultMap="dataDetail"> |
|||
SELECT |
|||
pm_form_data.*, |
|||
md_me_materialbase.material_code, |
|||
md_me_materialbase.material_name, |
|||
md_me_materialbase.material_spec, |
|||
md_me_materialbase.net_weight |
|||
FROM |
|||
pm_form_data |
|||
left join md_me_materialbase on pm_form_data.material_id = md_me_materialbase.material_id |
|||
<where> |
|||
<if test="query.form_type != null and query.form_type != ''"> |
|||
and form_type = #{query.form_type} |
|||
</if> |
|||
<if test="query.status != null and query.status != ''"> |
|||
and pm_form_data.status IN |
|||
<foreach collection="query.status" item="status" separator="," open="(" close=")"> |
|||
#{status} |
|||
</foreach> |
|||
</if> |
|||
<if test="query.parent_id != null and query.parent_id != ''"> |
|||
and parent_id = #{query.parent_id} |
|||
</if> |
|||
<if test="query.form_query != null and query.form_query.size() > 0"> |
|||
<foreach collection="query.form_query" item="value" index="key" > |
|||
<if test="value != null and value != ''"> |
|||
and JSON_CONTAINS(form_data, '{"${key}":"${value}"}') |
|||
</if> |
|||
</foreach> |
|||
</if> |
|||
</where> |
|||
ORDER BY create_time DESC |
|||
</select> |
|||
<select id="queryTree2" resultMap="dataDetail"> |
|||
SELECT |
|||
pm_form_data.*, |
|||
md_me_materialbase.material_code, |
|||
md_me_materialbase.material_name, |
|||
md_me_materialbase.material_spec, |
|||
md_me_materialbase.net_weight |
|||
FROM |
|||
pm_form_data |
|||
left join md_me_materialbase on pm_form_data.material_id = md_me_materialbase.material_id |
|||
<where> |
|||
<if test="query.search != null and query.search != ''"> |
|||
and form_data LIKE '%${query.search}%' |
|||
</if> |
|||
<if test="query.form_type != null and query.form_type != ''"> |
|||
and form_type = #{query.form_type} |
|||
</if> |
|||
<if test="query.pcsn != null and query.pcsn != ''"> |
|||
and pcsn = #{query.pcsn} |
|||
</if> |
|||
<if test="query.code != null and query.code != ''"> |
|||
and code LIKE '%${query.code}' |
|||
</if> |
|||
<if test="query.bill_code != null and query.bill_code != ''"> |
|||
and source_form_date = #{query.bill_code} |
|||
</if> |
|||
<if test="query.mater != null and query.mater != ''"> |
|||
and md_me_materialbase.material_code like '%${query.mater}%' |
|||
</if> |
|||
<if test="query.start_time != null and query.start_time != ''"> |
|||
and pm_form_data.create_time >= #{query.start_time} |
|||
</if> |
|||
<if test="query.end_time != null and query.end_time != ''"> |
|||
and #{query.end_time} >= pm_form_data.create_time |
|||
</if> |
|||
<if test="query.status != null and query.status != ''"> |
|||
and pm_form_data.status IN |
|||
<foreach collection="query.status" item="status" separator="," open="(" close=")"> |
|||
#{status} |
|||
</foreach> |
|||
</if> |
|||
<if test="query.parent_id != null and query.parent_id != ''"> |
|||
and parent_id = #{query.parent_id} |
|||
</if> |
|||
<if test="query.form_query != null and query.form_query.size() > 0"> |
|||
<foreach collection="query.form_query" item="value" index="key"> |
|||
<if test="value != null and value != ''"> |
|||
and JSON_CONTAINS(form_data, '{"${key}":"${value}"}') |
|||
</if> |
|||
</foreach> |
|||
</if> |
|||
</where> |
|||
ORDER BY create_time DESC |
|||
</select> |
|||
<select id="queryTreeCounts" resultType="java.math.BigDecimal"> |
|||
SELECT |
|||
SUM(pm_form_data.qty) as counts |
|||
FROM |
|||
pm_form_data |
|||
left join md_me_materialbase on pm_form_data.material_id = md_me_materialbase.material_id |
|||
<where> |
|||
<if test="query.search != null and query.search != ''"> |
|||
and form_data LIKE '%${query.search}%' |
|||
</if> |
|||
<if test="query.form_type != null and query.form_type != ''"> |
|||
and form_type = #{query.form_type} |
|||
</if> |
|||
<if test="query.pcsn != null and query.pcsn != ''"> |
|||
and pcsn = #{query.pcsn} |
|||
</if> |
|||
<if test="query.code != null and query.code != ''"> |
|||
and code LIKE '%${query.code}' |
|||
</if> |
|||
<if test="query.bill_code != null and query.bill_code != ''"> |
|||
and source_form_date = #{query.bill_code} |
|||
</if> |
|||
<if test="query.mater != null and query.mater != ''"> |
|||
and md_me_materialbase.material_code like '%${query.mater}%' |
|||
</if> |
|||
<if test="query.start_time != null and query.start_time != ''"> |
|||
and pm_form_data.create_time >= #{query.start_time} |
|||
</if> |
|||
<if test="query.end_time != null and query.end_time != ''"> |
|||
and #{query.end_time} >= pm_form_data.create_time |
|||
</if> |
|||
<if test="query.status != null and query.status != ''"> |
|||
and pm_form_data.status IN |
|||
<foreach collection="query.status" item="status" separator="," open="(" close=")"> |
|||
#{status} |
|||
</foreach> |
|||
</if> |
|||
<if test="query.parent_id != null and query.parent_id != ''"> |
|||
and parent_id = #{query.parent_id} |
|||
</if> |
|||
<if test="query.form_query != null and query.form_query.size() > 0"> |
|||
<foreach collection="query.form_query" item="value" index="key"> |
|||
<if test="value != null and value != ''"> |
|||
and JSON_CONTAINS(form_data, '{"${key}":"${value}"}') |
|||
</if> |
|||
</foreach> |
|||
</if> |
|||
</where> |
|||
ORDER BY create_time DESC |
|||
</select> |
|||
<select id="selectChild" resultMap="dataDetail"> |
|||
select |
|||
pm_form_data.*, |
|||
md_me_materialbase.material_code, |
|||
md_me_materialbase.material_name, |
|||
md_me_materialbase.material_spec, |
|||
md_me_materialbase.net_weight |
|||
from pm_form_data left join md_me_materialbase on pm_form_data.material_id = md_me_materialbase.material_id |
|||
where parent_id = #{id} |
|||
</select> |
|||
<select id="selectChilds" resultMap="dataDetail"> |
|||
select |
|||
pm_form_data.*, |
|||
md_me_materialbase.material_code, |
|||
md_me_materialbase.material_name, |
|||
md_me_materialbase.material_spec, |
|||
md_me_materialbase.net_weight, |
|||
md_pb_measureunit.unit_name |
|||
from pm_form_data left join md_me_materialbase on pm_form_data.material_id = md_me_materialbase.material_id |
|||
left join md_pb_measureunit on pm_form_data.unit_id = md_pb_measureunit.measure_unit_id |
|||
where parent_id in |
|||
<foreach collection="parents" open="(" close=")" item="parent_id" separator=","> |
|||
#{parent_id} |
|||
</foreach> |
|||
</select> |
|||
|
|||
<select id="existFormDataList" resultType="java.lang.String"> |
|||
SELECT id |
|||
FROM pm_form_data |
|||
WHERE form_type LIKE CONCAT('%', #{form_type}, '%') |
|||
</select> |
|||
<select id="existFormCodeDataList" resultType="java.lang.String"> |
|||
SELECT code |
|||
FROM pm_form_data |
|||
WHERE DATE(create_time) = CURDATE() |
|||
</select> |
|||
</mapper> |
|||
|
Loading…
Reference in new issue