|
|
|
@ -1,5 +1,6 @@
|
|
|
|
|
package com.dsic.gj_erp.pc;
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.date.DateField;
|
|
|
|
|
import cn.hutool.core.date.DateTime;
|
|
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
|
|
import cn.hutool.core.util.ObjUtil;
|
|
|
|
@ -13,8 +14,8 @@ import com.dsic.gj_erp.bean.jcsj.EmSbcnp;
|
|
|
|
|
import com.dsic.gj_erp.bean.jcsj.EmSbjbb;
|
|
|
|
|
import com.dsic.gj_erp.bean.jhgk.DmSygdxq;
|
|
|
|
|
import com.dsic.gj_erp.bean.jhgk.DmZrcjh;
|
|
|
|
|
import com.dsic.gj_erp.bean.pgd.PgdSljh;
|
|
|
|
|
import com.dsic.gj_erp.pc.dto.data.Bom;
|
|
|
|
|
import com.dsic.gj_erp.pc.dto.data.按批次合并的钢料需求;
|
|
|
|
|
import com.dsic.gj_erp.pc.dto.data.钢料需求;
|
|
|
|
|
import com.dsic.gj_erp.pc.dto.gx.*;
|
|
|
|
|
import com.dsic.gj_erp.pc.dto.sb.*;
|
|
|
|
@ -29,8 +30,8 @@ import com.dsic.gj_erp.service.jcsj.EmSbcnpService;
|
|
|
|
|
import com.dsic.gj_erp.service.jcsj.EmSbjbbService;
|
|
|
|
|
import com.dsic.gj_erp.service.jhgk.DmSygdxqService;
|
|
|
|
|
import com.dsic.gj_erp.service.jhgk.DmZrcjhService;
|
|
|
|
|
import com.dsic.gj_erp.service.pgd.PgdSljhService;
|
|
|
|
|
import com.google.common.collect.ImmutableMap;
|
|
|
|
|
import com.google.common.util.concurrent.AtomicDouble;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
|
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
@ -38,7 +39,6 @@ import java.io.OutputStream;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.concurrent.CountDownLatch;
|
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
import static com.dsic.gj_erp.pc.Manager.排产;
|
|
|
|
@ -49,16 +49,24 @@ public class DataFactory {
|
|
|
|
|
|
|
|
|
|
public static void 排产2() {
|
|
|
|
|
装载中日程数据();
|
|
|
|
|
|
|
|
|
|
套料图所占工序的资源.clear();
|
|
|
|
|
Manager.排产结果=new ArrayList<>();
|
|
|
|
|
List<钢料需求> list=读取钢料需求();
|
|
|
|
|
|
|
|
|
|
工序CD接口 _工序CD接口 = getBean(工序CD接口.class);
|
|
|
|
|
List<工序CD> 工序CDS = _工序CD接口.get();
|
|
|
|
|
Map<Constant.工序,工序CD> 工序CDMap=new HashMap<>();
|
|
|
|
|
工序CDS.forEach(item->工序CDMap.put(item.getGx(),item));
|
|
|
|
|
|
|
|
|
|
执行排产(list,工序CDMap);
|
|
|
|
|
|
|
|
|
|
清理冗余数据(list);
|
|
|
|
|
|
|
|
|
|
if (Manager.排产结果.size()>0){
|
|
|
|
|
log.info("排产异常--{}个未完整排产,{}",Manager.排产结果.size(),Manager.排产结果);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void 执行排产(List<钢料需求> list, Map<Constant.工序, 工序CD> 工序CDMap){
|
|
|
|
|
list.forEach(钢料需求 -> {
|
|
|
|
|
CountDownLatch latch = new CountDownLatch(钢料需求.getBomList().size());
|
|
|
|
|
String xzglxq = 钢料需求.getXzglxq();
|
|
|
|
@ -92,22 +100,6 @@ public class DataFactory {
|
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
清理冗余数据(list);
|
|
|
|
|
|
|
|
|
|
if (Manager.排产结果.size()>0){
|
|
|
|
|
log.info("排产异常--{}个未完整排产,{}",Manager.排产结果.size(),Manager.排产结果);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static List<PgdSljh> 获取完工的上料计划(Bom bom){
|
|
|
|
|
return getBean(PgdSljhService.class).已排产上料计划装载(bom.getDcch(),bom.getPl(),bom.getFd(),bom.getTzbh());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Map<String,List<订货计划>> 获取订货计划(){
|
|
|
|
|
List<订货计划> _订货计划 = getBean(订货计划滚动信息接口.class).get();
|
|
|
|
|
Map<String,List<订货计划>> map= _订货计划.stream().collect(Collectors.groupingBy(订货计划::getDcch));
|
|
|
|
|
return map;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static DmZrcjh 获取中日程(String key){
|
|
|
|
@ -131,11 +123,154 @@ public class DataFactory {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void 排产3(){
|
|
|
|
|
装载中日程数据();
|
|
|
|
|
套料图所占工序的资源.clear();
|
|
|
|
|
Manager.排产结果=new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
List<钢料需求> list=读取钢料需求();
|
|
|
|
|
Collection<按批次合并的钢料需求> 按批次合并 = 按批次合并(list);
|
|
|
|
|
计算需求产能(按批次合并);
|
|
|
|
|
try {
|
|
|
|
|
均衡预占(按批次合并);
|
|
|
|
|
}catch (Exception e){
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}finally {
|
|
|
|
|
清理冗余数据(list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void 均衡预占(Collection<按批次合并的钢料需求> _按批次合并的钢料需求){
|
|
|
|
|
工序CD接口 _工序CD接口 = getBean(工序CD接口.class);
|
|
|
|
|
List<工序CD> 工序CDS = _工序CD接口.get();
|
|
|
|
|
Map<Constant.工序,工序CD> 工序CDMap=new HashMap<>();
|
|
|
|
|
工序CDS.forEach(item->工序CDMap.put(item.getGx(),item));
|
|
|
|
|
|
|
|
|
|
for (按批次合并的钢料需求 item:_按批次合并的钢料需求){
|
|
|
|
|
if (ObjUtil.isNotEmpty(item.getBomList())){
|
|
|
|
|
均衡计算(item,工序CDMap);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void 均衡计算(按批次合并的钢料需求 item,Map<Constant.工序,工序CD> 工序CDMap){
|
|
|
|
|
Constant.工序 依据工序=Constant.工序.切割;
|
|
|
|
|
//需求日期可利用范围是±3天
|
|
|
|
|
int times=-3;
|
|
|
|
|
List<资源> tmpList=new ArrayList<>();
|
|
|
|
|
AtomicDouble atomicDouble = item.get产能需求().get(依据工序);
|
|
|
|
|
资源 _资源=null;
|
|
|
|
|
do {
|
|
|
|
|
//因为第一次计算时候就是当前批量小组需求日期,所以再次循环到的时候不需要再次计算
|
|
|
|
|
if (times==0){
|
|
|
|
|
times+=1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (times>3){
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
DateTime xzglxq = item.get均衡需求日期().offset(DateField.DAY_OF_YEAR,工序CDMap.get(依据工序).getCd());
|
|
|
|
|
_资源 = 提取资源(xzglxq);
|
|
|
|
|
tmpList.add(_资源);
|
|
|
|
|
if (_资源.判断工序是否可以被占用(依据工序,atomicDouble.get())){
|
|
|
|
|
// DateTime 上料日期 = item.get均衡需求日期().offset(DateField.DAY_OF_YEAR, -14);
|
|
|
|
|
// 资源 上料 = 提取资源(上料日期);
|
|
|
|
|
// for (Bom bom:item.getBomList()){
|
|
|
|
|
// 上料.占用资源(Constant.工序.上料,bom,item.get产能需求().get(Constant.工序.上料).get());
|
|
|
|
|
// _资源.占用资源(Constant.工序.切割,bom,1);
|
|
|
|
|
// }
|
|
|
|
|
执行排产(item.getBomList(),item.get均衡需求日期(),工序CDMap);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
//需求日期可利用范围是±3天,排产是需要根据产能进行调整
|
|
|
|
|
item.set均衡需求日期(DateUtil.offsetDay(item.get均衡需求日期(),times));
|
|
|
|
|
times+=1;
|
|
|
|
|
}while (true);
|
|
|
|
|
|
|
|
|
|
//若在需求期±3天内无法正常排产时,查找最大可用空闲资源进行占用
|
|
|
|
|
if (times>3){
|
|
|
|
|
//查找最小可用资源,进行占用
|
|
|
|
|
tmpList.sort(Comparator.comparingDouble((tmp)->tmp.get工序产能MAP().get(Constant.工序.切割).get占用()));
|
|
|
|
|
tmpList.stream().findFirst().ifPresent(tmp->{
|
|
|
|
|
// DateTime 上料日期 = item.get均衡需求日期().offset(DateField.DAY_OF_YEAR, -14);
|
|
|
|
|
// 资源 上料 = 提取资源(上料日期);
|
|
|
|
|
// for (Bom bom:item.getBomList()){
|
|
|
|
|
// 上料.占用资源(Constant.工序.上料,bom,item.get产能需求().get(Constant.工序.上料).get());
|
|
|
|
|
// tmp.占用资源(Constant.工序.切割,bom,1);
|
|
|
|
|
// }
|
|
|
|
|
//由于资源日为切割日期,这里需要还原一下,修正传递的参照需求日期
|
|
|
|
|
执行排产(item.getBomList(),tmp.get_date().offset(DateField.DAY_OF_YEAR,-工序CDMap.get(依据工序).getCd()),工序CDMap);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
log.info("船号:{},批次:{},占用资源成功,切割日期:{}",item.getDcCh(),item.getDcPl(),_资源.getDate());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void 执行排产(List<Bom> list,DateTime 参照需求日期,Map<Constant.工序,工序CD> 工序CDMap){
|
|
|
|
|
CountDownLatch latch = new CountDownLatch(list.size());
|
|
|
|
|
for (Bom bom:list){
|
|
|
|
|
套料图工序 _套料图工序 = 套料图工序工厂(bom);
|
|
|
|
|
|
|
|
|
|
if (_套料图工序==null){
|
|
|
|
|
latch.countDown();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_套料图工序.setXzglxq(bom.getXzglxq());
|
|
|
|
|
_套料图工序.setDzglxq(bom.getDzglxq());
|
|
|
|
|
_套料图工序.set工序CD(工序CDMap);
|
|
|
|
|
_套料图工序.set中日程(获取中日程(bom.getDcch() + bom.getPl() + bom.getFd()));
|
|
|
|
|
_套料图工序.set参照需求日期(参照需求日期);
|
|
|
|
|
es.execute(() -> {
|
|
|
|
|
try{
|
|
|
|
|
_套料图工序.run();
|
|
|
|
|
}finally {
|
|
|
|
|
latch.countDown();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
latch.await(30, TimeUnit.SECONDS);// 指定超时时间
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void 计算需求产能(Collection<按批次合并的钢料需求> _按批次合并的钢料需求){
|
|
|
|
|
_按批次合并的钢料需求.forEach(按批次合并的钢料需求::计算各工序产能需求);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Collection<按批次合并的钢料需求> 按批次合并(List<钢料需求> list){
|
|
|
|
|
Map<String,按批次合并的钢料需求> map=new HashMap<>();
|
|
|
|
|
list.forEach(item->{
|
|
|
|
|
String key=item.getDcCh() + item.getDcPl();
|
|
|
|
|
按批次合并的钢料需求 _按批次合并的钢料需求 = map.get(key);
|
|
|
|
|
if (_按批次合并的钢料需求==null){
|
|
|
|
|
_按批次合并的钢料需求=new 按批次合并的钢料需求();
|
|
|
|
|
map.put(key,_按批次合并的钢料需求);
|
|
|
|
|
}
|
|
|
|
|
_按批次合并的钢料需求.of(item);
|
|
|
|
|
});
|
|
|
|
|
return map.values();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static List<钢料需求> 读取钢料需求(){
|
|
|
|
|
List<DmSygdxq> 按需求日期排序的钢料需求 = getBean(DmSygdxqService.class).getXqWithBom(from, to);
|
|
|
|
|
return 按需求日期排序的钢料需求.stream().map(钢料需求::of).collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Map<String,List<订货计划>> _订货计划=new HashMap<>();
|
|
|
|
|
public static List<订货计划> 获取订货计划(String dcch){
|
|
|
|
|
List<订货计划> list=_订货计划.get(dcch);
|
|
|
|
|
if (list!=null){
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
List<订货计划> _订货计划 = getBean(订货计划滚动信息接口.class).get();
|
|
|
|
|
Map<String,List<订货计划>> map= _订货计划.stream().collect(Collectors.groupingBy(订货计划::getDcch));
|
|
|
|
|
return map.get(dcch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void 排产() {
|
|
|
|
|
套料图所占工序的资源.clear();
|
|
|
|
|
List<排产结果> list = 排产.list;
|
|
|
|
@ -256,19 +391,24 @@ public class DataFactory {
|
|
|
|
|
return 资源;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Map<Constant.工序, 工序产能> 计算日产能(){
|
|
|
|
|
Map<Constant.工序, 工序产能> map = new HashMap<>();
|
|
|
|
|
Arrays.stream(Constant.工序.values()).forEach(_item -> {
|
|
|
|
|
if (StrUtil.isNotEmpty(_item.getCode())) {
|
|
|
|
|
工序产能 工序产能 = 工序产能工厂(_item);
|
|
|
|
|
if (工序产能!=null){
|
|
|
|
|
map.put(_item, 工序产能);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return map;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void 创建产能资源池(){
|
|
|
|
|
资源池.clear();
|
|
|
|
|
工厂日历.stream().filter(item -> "1".equals(item.getXxr()))
|
|
|
|
|
.forEach(item -> {
|
|
|
|
|
Map<Constant.工序, 工序产能> map = new HashMap<>();
|
|
|
|
|
Arrays.stream(Constant.工序.values()).forEach(_item -> {
|
|
|
|
|
if (StrUtil.isNotEmpty(_item.getCode())) {
|
|
|
|
|
工序产能 工序产能 = 工序产能工厂(_item);
|
|
|
|
|
if (工序产能!=null){
|
|
|
|
|
map.put(_item, 工序产能);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
Map<Constant.工序, 工序产能> map = 计算日产能();
|
|
|
|
|
资源池.put(item.getGl(), 资源.of(item.getGl(), map));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|