|
|
|
@ -33,12 +33,14 @@ import com.dsic.gj_erp.service.jhgk.DmZrcjhService;
|
|
|
|
|
import com.google.common.collect.ImmutableMap;
|
|
|
|
|
import com.google.common.util.concurrent.AtomicDouble;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import lombok.val;
|
|
|
|
|
|
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
|
import java.io.OutputStream;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.concurrent.CountDownLatch;
|
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
import static com.dsic.gj_erp.pc.Manager.排产;
|
|
|
|
@ -141,6 +143,105 @@ public class DataFactory {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void 排产4(){
|
|
|
|
|
装载中日程数据();
|
|
|
|
|
套料图所占工序的资源.clear();
|
|
|
|
|
Manager.排产结果=new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
List<钢料需求> list=读取钢料需求1();
|
|
|
|
|
List<钢料需求> 按批次合并 = 合并批次(list);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
均衡预占(按批次合并);
|
|
|
|
|
}catch (Exception e){
|
|
|
|
|
// e.printStackTrace();
|
|
|
|
|
throw e;
|
|
|
|
|
}finally {
|
|
|
|
|
清理冗余数据(list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void 均衡预占(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));
|
|
|
|
|
|
|
|
|
|
for (钢料需求 item:list){
|
|
|
|
|
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<>();
|
|
|
|
|
Map<String, AtomicDouble> 切割各设备需求量 = item.get切割各设备需求量();
|
|
|
|
|
资源 _资源=null;
|
|
|
|
|
Integer cd = 工序CDMap.get(依据工序).getCd();
|
|
|
|
|
do {
|
|
|
|
|
//因为第一次计算时候就是当前批量小组需求日期,所以再次循环到的时候不需要再次计算
|
|
|
|
|
if (times==0){
|
|
|
|
|
times+=1;
|
|
|
|
|
item.set均衡需求日期(DateUtil.offsetDay(DateUtil.parse(item.getXzglxq(),"yyyy/MM/dd"),times));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (times>3){
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DateTime xzglxq = item.get均衡需求日期().offset(DateField.DAY_OF_YEAR,cd);
|
|
|
|
|
|
|
|
|
|
if (xzglxq.isBefore(DateUtil.date())){
|
|
|
|
|
//break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_资源 = 提取资源(xzglxq);
|
|
|
|
|
if (_资源.get_date().isBefore(DateUtil.date())){
|
|
|
|
|
//break;
|
|
|
|
|
}
|
|
|
|
|
//记录6次计算的全部资源
|
|
|
|
|
tmpList.add(_资源);
|
|
|
|
|
if (_资源.判断切割设备是否可以被占用(切割各设备需求量)){
|
|
|
|
|
if (item.getDcCh().equals("G175K-5")&&item.getDcPl().equals("003")){
|
|
|
|
|
System.out.println(111);
|
|
|
|
|
}
|
|
|
|
|
执行排产(item.getBomList(),item.get均衡需求日期(),工序CDMap);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
//需求日期可利用范围是±3天,排产是需要根据产能进行调整
|
|
|
|
|
item.set均衡需求日期(DateUtil.offsetDay(DateUtil.parse(item.getXzglxq(),"yyyy/MM/dd"),times));
|
|
|
|
|
times+=1;
|
|
|
|
|
}while (true);
|
|
|
|
|
|
|
|
|
|
//若在需求期±3天内无法正常排产时,查找最大可用空闲资源进行占用
|
|
|
|
|
AtomicReference<String> date=new AtomicReference<>();
|
|
|
|
|
if (times>3){
|
|
|
|
|
//查找最小可用资源,进行占用
|
|
|
|
|
tmpList.sort(Comparator.comparingDouble((tmp)->tmp.get工序产能MAP().get(Constant.工序.切割).get占用()));
|
|
|
|
|
tmpList.stream().findFirst().ifPresent(tmp->{
|
|
|
|
|
//由于资源日为切割日期,这里需要还原一下,修正传递的参照需求日期
|
|
|
|
|
DateTime offset = tmp.get_date().offset(DateField.DAY_OF_MONTH, -工序CDMap.get(依据工序).getCd());
|
|
|
|
|
if (item.getDcCh().equals("G175K-5")&&item.getDcPl().equals("003")){
|
|
|
|
|
System.out.println(offset.toDateStr());
|
|
|
|
|
}
|
|
|
|
|
执行排产(item.getBomList(),offset,工序CDMap);
|
|
|
|
|
date.set(tmp.getDate());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (_资源!=null){
|
|
|
|
|
date.set(_资源.getDate());
|
|
|
|
|
}else {
|
|
|
|
|
log.info("船号:{},批次:{},早于当前日期无需排产",item.getDcCh(),item.getDcPl());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
log.info("船号:{},批次:{},占用资源成功,切割日期:{}",item.getDcCh(),item.getDcPl(),date.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void 均衡预占(Collection<按批次合并的钢料需求> _按批次合并的钢料需求){
|
|
|
|
|
工序CD接口 _工序CD接口 = getBean(工序CD接口.class);
|
|
|
|
|
List<工序CD> 工序CDS = _工序CD接口.get();
|
|
|
|
@ -186,6 +287,9 @@ public class DataFactory {
|
|
|
|
|
// 上料.占用资源(Constant.工序.上料,bom,item.get产能需求().get(Constant.工序.上料).get());
|
|
|
|
|
// _资源.占用资源(Constant.工序.切割,bom,1);
|
|
|
|
|
// }
|
|
|
|
|
if (item.getDcCh().equals("G175K-4")&&item.getDcPl().equals("020")){
|
|
|
|
|
System.out.println(111);
|
|
|
|
|
}
|
|
|
|
|
执行排产(item.getBomList(),item.get均衡需求日期(),工序CDMap);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -195,6 +299,7 @@ public class DataFactory {
|
|
|
|
|
}while (true);
|
|
|
|
|
|
|
|
|
|
//若在需求期±3天内无法正常排产时,查找最大可用空闲资源进行占用
|
|
|
|
|
AtomicReference<String> date=new AtomicReference<>();
|
|
|
|
|
if (times>3){
|
|
|
|
|
//查找最小可用资源,进行占用
|
|
|
|
|
tmpList.sort(Comparator.comparingDouble((tmp)->tmp.get工序产能MAP().get(Constant.工序.切割).get占用()));
|
|
|
|
@ -206,17 +311,22 @@ public class DataFactory {
|
|
|
|
|
// tmp.占用资源(Constant.工序.切割,bom,1);
|
|
|
|
|
// }
|
|
|
|
|
//由于资源日为切割日期,这里需要还原一下,修正传递的参照需求日期
|
|
|
|
|
if (item.getDcCh().equals("G175K-4")&&item.getDcPl().equals("020")){
|
|
|
|
|
System.out.println(111);
|
|
|
|
|
}
|
|
|
|
|
执行排产(item.getBomList(),tmp.get_date().offset(DateField.DAY_OF_YEAR,-工序CDMap.get(依据工序).getCd()),工序CDMap);
|
|
|
|
|
date.set(tmp.getDate());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (_资源!=null){
|
|
|
|
|
log.info("船号:{},批次:{},占用资源成功,切割日期:{}",item.getDcCh(),item.getDcPl(),_资源.getDate());
|
|
|
|
|
date.set(_资源.getDate());
|
|
|
|
|
log.info("船号:{},批次:{},占用资源成功,切割日期:{}",item.getDcCh(),item.getDcPl(),date.get());
|
|
|
|
|
}else {
|
|
|
|
|
log.info("船号:{},批次:{},早于当前日期无需排产",item.getDcCh(),item.getDcPl());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void 执行排产(List<Bom> list,DateTime 参照需求日期,Map<Constant.工序,工序CD> 工序CDMap){
|
|
|
|
|
CountDownLatch latch = new CountDownLatch(list.size());
|
|
|
|
|
for (Bom bom:list){
|
|
|
|
@ -224,6 +334,7 @@ public class DataFactory {
|
|
|
|
|
|
|
|
|
|
if (_套料图工序==null){
|
|
|
|
|
latch.countDown();
|
|
|
|
|
log.info("船号:{},批次:{},图纸编号:{},无法找到对应套料图",bom.getDcch(),bom.getPl(),bom.getTzbh());
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -252,20 +363,39 @@ public class DataFactory {
|
|
|
|
|
_按批次合并的钢料需求.forEach(按批次合并的钢料需求::计算各工序产能需求);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static List<钢料需求> 合并批次(List<钢料需求> list){
|
|
|
|
|
Map<String,钢料需求> map=new HashMap<>();
|
|
|
|
|
list.forEach(item->{
|
|
|
|
|
String key=item.getDcCh() + item.getDcPl();
|
|
|
|
|
钢料需求 _钢料需求 = map.get(key);
|
|
|
|
|
if (_钢料需求==null){
|
|
|
|
|
map.put(key,item);
|
|
|
|
|
}else{
|
|
|
|
|
_钢料需求.addBomList(item.getBomList());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return new ArrayList<>(map.values());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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,_按批次合并的钢料需求);
|
|
|
|
|
}
|
|
|
|
|
按批次合并的钢料需求 _按批次合并的钢料需求 = map.computeIfAbsent(key, k -> new 按批次合并的钢料需求());
|
|
|
|
|
_按批次合并的钢料需求.of(item);
|
|
|
|
|
});
|
|
|
|
|
return map.values();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static List<钢料需求> 读取钢料需求1(){
|
|
|
|
|
List<DmSygdxq> 按需求日期排序的钢料需求 = getBean(DmSygdxqService.class).getXqWithBom(from, to);
|
|
|
|
|
return 按需求日期排序的钢料需求.stream().map(item->{
|
|
|
|
|
钢料需求 _钢料需求 = 钢料需求.of(item);
|
|
|
|
|
_钢料需求.计算各设备切割需求量();
|
|
|
|
|
return _钢料需求;
|
|
|
|
|
}).collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static List<钢料需求> 读取钢料需求(){
|
|
|
|
|
List<DmSygdxq> 按需求日期排序的钢料需求 = getBean(DmSygdxqService.class).getXqWithBom(from, to);
|
|
|
|
|
return 按需求日期排序的钢料需求.stream().map(钢料需求::of).collect(Collectors.toList());
|
|
|
|
@ -417,7 +547,13 @@ public class DataFactory {
|
|
|
|
|
|
|
|
|
|
public static void 创建产能资源池(){
|
|
|
|
|
资源池.clear();
|
|
|
|
|
DateTime _from = DateUtil.parse(from, "yyyy/MM/dd").offset(DateField.DAY_OF_YEAR,-30);
|
|
|
|
|
DateTime _to = DateUtil.parse(to, "yyyy/MM/dd");
|
|
|
|
|
工厂日历.stream().filter(item -> "1".equals(item.getXxr()))
|
|
|
|
|
.filter(item->{
|
|
|
|
|
DateTime gl = DateUtil.parse(item.getGl(), "yyyy/MM/dd");
|
|
|
|
|
return gl.isAfterOrEquals(_from)&&gl.isBeforeOrEquals(_to);
|
|
|
|
|
})
|
|
|
|
|
.forEach(item -> {
|
|
|
|
|
Map<Constant.工序, 工序产能> map = 计算日产能();
|
|
|
|
|
资源池.put(item.getGl(), 资源.of(item.getGl(), map));
|
|
|
|
|