1.满足均衡排产问题

2.在满足批次完整性的同时,当产能不足时需整批量调整
master
董哲奇 10 months ago
parent 00b3471abe
commit 2a13568185

@ -1,6 +1,5 @@
package com.dsic.gj_erp.controller.jhgk;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.dsic.gj_erp.bean.ResultBean;

@ -37,14 +37,15 @@ public interface Constant {
01(.,"龙门01","",2.4,3.6,40,15.6,25.2),
01(.,"火焰01","",0.3,11.15,40.0,0,2.0),
01(.,"数控01","",1.5,3.0,0,8.5,8.5),
03(., "火焰03", "", 0.3, 11.5, 40.0, 0, 2.0),
03(., "数控03", "", 2.0, 4.2, 0, 14.0, 14.0),
03(., "龙门03", "", 1.6, 3.2, 40.0, 11.2, 18.4),
02(., "火焰02", "", 0.3, 11.5, 40.0, 0, 3.9),
02(., "数控02", "", 1.4, 3.0, 0, 18.2, 18.2),
02(., "龙门02", "", 2.0, 3.0, 40.0, 13.0, 13.0),
03(., "火焰03", "", 0.3, 11.5, 40.0, 0, 2.0),
03(., "数控03", "", 2.0, 4.2, 0, 14.0, 14.0),
03(., "龙门03", "", 1.6, 3.2, 40.0, 11.2, 18.4),
01(., "坡口01", "", 2.0, 3.0, 100.0, 13.0, 13.0),
01(., "型材01", "", 2.0, 3.0, 100.0, 13.0, 13.0),
01(., "曲加工01", "", 2.0, 3.0, 100.0, 13.0, 13.0),

@ -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.getMAP().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());
_.setCD(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));
});
}

@ -49,6 +49,39 @@ public class Bom {
return _bom;
}
public double (Constant. _){
switch (_) {
case :
return 1;
case :
return 1;
case :
return 1;
case 线:
return 1;
case :
return 1;
case :
return 1;
case :
return 1;
case :
return 1;
case :
return 1;
case :
return 1;
case :
return 1;
// case 预配盘:
// return new 工序01上料(_工序,_设备);
// case 配送:
// return new 工序01上料(_工序,_设备);
default:
return 0;
}
}
public String toString() {
return JSONObject.toJSONString(this);
}

@ -0,0 +1,78 @@
package com.dsic.gj_erp.pc.dto.data;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjUtil;
import com.dsic.gj_erp.pc.Constant;
import com.dsic.gj_erp.pc.DataFactory;
import com.dsic.gj_erp.pc.dto.;
import com.google.common.util.concurrent.AtomicDouble;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Getter
@Setter
public class {
private String dcCh;
private String dcPl;
private List<String> dcFd;
private String xzglxq;
private String dzglxq;
private DateTime ;
private List<Bom> bomList;
private String ;
private Map<Constant., AtomicDouble> ;//fixme 要求必须所有工序都不可以打乱才能用
private Map<Constant., String> ;
public void (){
=new HashMap<>();
this.bomList.forEach(item->{
_ = DataFactory.(item);
_.get().forEach(_->{
AtomicDouble aDouble = .get(_);
if (aDouble==null){
aDouble=new AtomicDouble(0);
.put(_,aDouble);
}
aDouble.addAndGet(item.(_));
});
});
}
public of( _){
if (this.dcCh==null){
this.dcCh= _.getDcCh();
}
if (this.dcPl==null){
this.dcPl=_.getDcPl();
}
if (!ObjUtil.equals(_.getDcCh(),this.dcCh)||!ObjUtil.equals(_.getDcPl(),this.dcPl)){
return this;
}
if (dcFd==null){
dcFd=new ArrayList<>();
}
this.dcFd.add(_.getDcFd());
this.xzglxq= _.getXzglxq();
this.dzglxq= _.getDzglxq();
if (this.bomList==null){
this.bomList=new ArrayList<>();
}
this.bomList.addAll(_.getBomList());
return this;
}
public DateTime get(){
if (this. ==null){
return DateUtil.parse(this.xzglxq,"yyyy/MM/dd");
}
return this.;
}
}

@ -35,6 +35,7 @@ public abstract class 套料图工序 implements 套料图工序接口 {
protected double = 1;//默认数量为1,切割处理时候按照实际切割长度计算,切割产能在设备产能中单独计算
protected String ;
protected DateTime _;
protected DateTime ;//当排产无法满足时,临时需求日期生效,±3天查找可用资源
protected DmZrcjh ;
protected List<Constant.> ;
protected Map<Constant.,CD> CD;
@ -49,13 +50,25 @@ public abstract class 套料图工序 implements 套料图工序接口 {
}
protected boolean (){
if (ObjUtil.isEmpty(this.bom)||StrUtil.isEmpty(this.bom.getTzbh())){
return false;
}
String xzxq=this.xzglxq;
if (this.!=null){
xzxq=this..toString("yyyy/MM/dd");
}
//为了批次完整性,目前无论大小组都采用小组需求期
this.set(xzxq);
if (this.zlType==ZlType.||this.zlType==ZlType.){
this.set(this.xzglxq);
this.set(xzxq);
}
if (this.zlType==ZlType.){
if (this.dzglxq==null){
this.set(this.xzglxq);
this.set(xzxq);
this.bom.使();
}else {
this.set(this.dzglxq);
@ -63,37 +76,33 @@ public abstract class 套料图工序 implements 套料图工序接口 {
}
if (this.zlType==ZlType.&&this..contains(Constant..)){
//大组需求有曲外板,需要按照大组需求期计算
// 大组需求有曲外板,需要按照大组需求期计算
if (this.dzglxq==null){
this.set(this.xzglxq);
this.bom.使();
this.set(xzxq);
}else {
this.set(this.dzglxq);
}
//曲外板批量名称设置
//曲外板批量名称设置.
this.bom.set_pl(this.bom.getPl()+"Q");
}
//当大组需求期无法满足小组需求时,以小组需求期为准
if (StrUtil.isAllNotEmpty(xzglxq,dzglxq)){
if (DateUtil.parse(xzglxq,"yyyy/MM/dd").isAfter(DateUtil.parse(dzglxq,"yyyy/MM/dd"))){
if (StrUtil.isAllNotEmpty(xzxq,dzglxq)){
if (DateUtil.parse(xzxq,"yyyy/MM/dd").isAfter(DateUtil.parse(dzglxq,"yyyy/MM/dd"))){
this.set(dzglxq);
}
}
if (ObjUtil.isEmpty(this.bom)||StrUtil.isEmpty(this.bom.getTzbh())){
return false;
}
this._ = DateUtil.parse(this., "yyyy/MM/dd");
Map<String,List<>> _=DataFactory.();
this.s = _.get(bom.getDcch());
this.s = DataFactory.(bom.getDcch());
return true;
}
public void run(AtomicBoolean atomicBoolean) {
if (!this.()){
System.out.println(String.format("船号:%s,批量:%s,未订货",this.bom.getDcch(),this.bom.getPl()));
// System.out.println(String.format("船号:%s,批量:%s,未订货",this.bom.getDcch(),this.bom.getPl()));
bom.();
}

@ -31,6 +31,17 @@ public class 资源 {
});
}
public boolean (Constant. _ ,double ){
= MAP.get(_);
AtomicBoolean atomicBoolean = new AtomicBoolean(false);
Optional.ofNullable().ifPresent(it->{
if (it.()){
atomicBoolean.set(true);
}
});
return atomicBoolean.get();
}
public boolean (Constant. , Bom bom, double ){
AtomicBoolean atomicBoolean = new AtomicBoolean(false);
= MAP.get();

@ -25,7 +25,7 @@ public class 排产 {
DataFactory.();
DataFactory.();
DataFactory.();
DataFactory.2();
DataFactory.3();
}
private static of(@NotNull String from, @NotNull String to){

Loading…
Cancel
Save