fangpy 11 ماه پیش
والد
کامیت
a28eb322a2

+ 2 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/domain/EquipmentParameter.java

@@ -17,5 +17,7 @@ public class EquipmentParameter implements Serializable {
     private BigDecimal equipmentBearing;
     // 设备宽度
     private BigDecimal furnace;
+    // 最大装炉卷数
+    private Integer maxfurance;
 
 }

+ 88 - 2
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/domain/ProductionProcesses.java

@@ -91,6 +91,11 @@ public class ProductionProcesses implements Serializable {
      */
     private List<Equipment> optionalProviderEquipments;
 
+    /**
+     * 铸轧机按熔炉分组设备集合
+     */
+    private Map<String, List<Equipment>> equass;
+
     /**
      * 工步生产时的设备
      */
@@ -323,8 +328,33 @@ public class ProductionProcesses implements Serializable {
      */
     private ProductionProcesses rooprocess;
 
+    /**
+     * 是否已分卷
+     */
+    private String issubsection;
+
+    private List<String> firstNextThs;
+
+    private List<String> secondNextThs;
+
     private Map<String, String> conflictRoptions;
 
+    /**
+     * 后续相同工序连续生产总计时间
+     */
+    private Integer sameProcessTime;
+
+    /**
+     * 合并其它作业的排程顺序
+     */
+    private List<String> mergeProOrders;
+
+    /**
+     * 最大装炉卷数
+     */
+    private Integer maxheatroll;
+
+
     public String getEquipmentType() {
         return equipmentType;
     }
@@ -384,9 +414,9 @@ public class ProductionProcesses implements Serializable {
             }else if(this.processType.equals("铸轧")){
                 maxDelay = 500;
             } else if (this.processType.equals("冷轧")) {
-                maxDelay = 500;
+                maxDelay = 2000;
             } else{
-                maxDelay = 100;
+                maxDelay = 1000;
             }
         }
         return ValueRangeFactory.createIntValueRange(0, maxDelay);
@@ -865,6 +895,62 @@ public class ProductionProcesses implements Serializable {
         this.oldNextProcessesIds = oldNextProcessesIds;
     }
 
+    public List<String> getFirstNextThs() {
+        return firstNextThs;
+    }
+
+    public void setFirstNextThs(List<String> firstNextThs) {
+        this.firstNextThs = firstNextThs;
+    }
+
+    public List<String> getSecondNextThs() {
+        return secondNextThs;
+    }
+
+    public void setSecondNextThs(List<String> secondNextThs) {
+        this.secondNextThs = secondNextThs;
+    }
+
+    public String getIssubsection() {
+        return issubsection;
+    }
+
+    public void setIssubsection(String issubsection) {
+        this.issubsection = issubsection;
+    }
+
+    public Integer getSameProcessTime() {
+        return sameProcessTime;
+    }
+
+    public void setSameProcessTime(Integer sameProcessTime) {
+        this.sameProcessTime = sameProcessTime;
+    }
+
+    public List<String> getMergeProOrders() {
+        return mergeProOrders;
+    }
+
+    public void setMergeProOrders(List<String> mergeProOrders) {
+        this.mergeProOrders = mergeProOrders;
+    }
+
+    public Map<String, List<Equipment>> getEquass() {
+        return equass;
+    }
+
+    public void setEquass(Map<String, List<Equipment>> equass) {
+        this.equass = equass;
+    }
+
+    public Integer getMaxheatroll() {
+        return maxheatroll;
+    }
+
+    public void setMaxheatroll(Integer maxheatroll) {
+        this.maxheatroll = maxheatroll;
+    }
+
     public String getSeriSort(){
         String sortStr = this.getId();
         if(this.getStartTime() != null){

+ 9 - 6
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/listener/TaskStartTimeListener.java

@@ -477,9 +477,6 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
         if(process.getId().equals("23b6aee636c2461cb3102fa82be48f28")){
             int a = 0;
         }
-        if(process.getId().equals("3236a3604b334a41be97067687e4bb5a")){
-            int a = 0;
-        }
         // 获取所有规划实体对象数据
         ApsSolution workingSolution = scoreDirector.getWorkingSolution();
         // 时间设定
@@ -504,6 +501,9 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
             // 流转时间
             Integer lzTimes = 0;
             if(preProcess != null){
+                if(preProcess.getEquipment() == null){
+                    System.out.println(preProcess.getId());
+                }
                 if(preProcess.getEquipment().getWorkshopid() != null && preProcess.getEquipment().getWorkshopid().equals(process.getEquipment().getWorkshopid())){
                     lzTimes = process.getApsOverallConfig().getRoamTime().get("WORKSHOP_IN");
                 }else{
@@ -636,6 +636,9 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
             // 按照开始时间排序
             equipmentRunTimes.sort(Comparator.comparing(EquipmentRunTime::getStartRunTime));
 
+            if(process.getId().equals("edc2319424ae4bd684e8c76ff6c5042c")){
+                int a = 0;
+            }
             Integer delay = process.getDelay();
             // 有交叉的时间直接跳过,退火工序特殊处理
             if(equipmentRunTimes.size()>0){
@@ -679,7 +682,7 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
                         }
                     }
                     // 冷轧工序
-                    else if (process.getProcessType().equals("冷轧")) {
+                    /*else if (process.getProcessType().equals("冷轧")) {
                         // 首个占用时间
                         if(i == 0){
                             if(proEndTime.compareTo(equipmentRunTime.getStartRunTime())<0){
@@ -742,10 +745,10 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
                                 continue;
                             }
                         }
-                    }
+                    }*/
                     // 其它工序
                     else{
-                        if(proStartTime.compareTo(equipmentRunTime.getEndRunTime())>0 || proEndTime.compareTo(equipmentRunTime.getStartRunTime())<0){
+                        if(proStartTime.compareTo(equipmentRunTime.getEndRunTime())>=0 || proEndTime.compareTo(equipmentRunTime.getStartRunTime())<=0){
                             continue;
                         }else{
                             proStartTime = equipmentRunTime.getEndRunTime().plusMinutes(1);

+ 157 - 48
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/score/ApsConstraintProvider.java

@@ -45,10 +45,12 @@ public class ApsConstraintProvider implements ConstraintProvider {
 //                processBtNear(constraintFactory),
                 seriesZzLb(constraintFactory),
 
-                beforeThClose(constraintFactory),
+//                beforeThClose(constraintFactory),
                 // SOFT
                 processNear(constraintFactory),
                 eqTimeCrossMinTuihuoSoft(constraintFactory),
+                sameBsLzClose(constraintFactory),
+                preNextProcessSameEq(constraintFactory),
         };
     }
 
@@ -229,7 +231,7 @@ public class ApsConstraintProvider implements ConstraintProvider {
                                         bol = false;
                                         break;
                                     }
-                                    if(productionProcesses.getStartTime().compareTo(endRunTime)>0 || productionProcesses.getEndTime().compareTo(startTime)<0){
+                                    if(productionProcesses.getStartTime().compareTo(endRunTime)>=0 || productionProcesses.getEndTime().compareTo(startTime)<=0){
                                         continue;
                                     }else{
                                         bol = true;
@@ -244,6 +246,27 @@ public class ApsConstraintProvider implements ConstraintProvider {
                 .asConstraint("equipmentRunTime");
     }
 
+
+    /**
+     * 前后工序如果一样则连续生产中间不能有其它作业
+     * @param constraintFactory
+     * @return
+     */
+    private Constraint sameSeriesProcess(ConstraintFactory constraintFactory){
+        return constraintFactory.forEach(ProductionProcesses.class)
+                .filter(pro->{
+                    return !pro.getProcessType().equals("成退") && !pro.getProcessType().equals("中退")
+                            && !pro.getProcessType().equals("小卷成退") && !pro.getProcessType().equals("铸轧");
+                })
+                .filter(productionProcesses -> {
+                    boolean bol = false;
+
+                    return bol;
+                })
+                .penalize(HardMediumSoftScore.ONE_HARD,(proc1)->15)
+                .asConstraint("sameSeriesProcess");
+    }
+
     /**
      * 最大等待时间,不能小于流转时间
      * @param constraintFactory
@@ -297,14 +320,14 @@ public class ApsConstraintProvider implements ConstraintProvider {
                             return false;
                         }
                     }
-                    int washingFurnaceCount = seriesProduceWashingTimeFurnaceCount(processes);
+                    int washingFurnaceCount = seriesProduceWashingTimeFurnaceCount(processes,equipmentEquassociated);
                     if(washingFurnaceCount>0){
                         return true;
                     }
                     return false;
                 })
                 .penalize(HardMediumSoftScore.ONE_HARD,(equipmentEquassociated, processess) -> {
-                    int washingFurnaceCount = seriesProduceWashingTimeFurnaceCount(processess);
+                    int washingFurnaceCount = seriesProduceWashingTimeFurnaceCount(processess,equipmentEquassociated);
                     return washingFurnaceCount*10;
                 })
                 .asConstraint("seriesProduceWashTimeWait");
@@ -314,7 +337,7 @@ public class ApsConstraintProvider implements ConstraintProvider {
      * 铸轧连续生产洗炉评分计算
      * @param processes
      */
-    private int seriesProduceWashingTimeFurnaceCount(List<ProductionProcesses> processes){
+    private int seriesProduceWashingTimeFurnaceCount(List<ProductionProcesses> processes,String equipmentEquassociated){
         List<ProductionProcesses> hasStartTimeProcess = processes.stream().filter(v -> v.getStartTime() != null).collect(Collectors.toList());
         if(hasStartTimeProcess == null || hasStartTimeProcess.size() == 0){
             return 0;
@@ -331,6 +354,20 @@ public class ApsConstraintProvider implements ConstraintProvider {
                 }
             }
         }
+        if(processes.get(0).getEquass() != null && processes.get(0).getEquass().size()>0){
+            if(StrUtil.isNotBlank(equipmentEquassociated)){
+                List<Equipment> equs = processes.get(0).getEquass().get(equipmentEquassociated);
+                if(equs != null && equs.size()>0){
+                    for (Equipment equipment : equs) {
+                        List<Equipment> list = equipments.stream().filter(v -> v.getId().equals(equipment.getId())).collect(Collectors.toList());
+                        if(list == null || list.size() == 0){
+                            equipments.add(equipment);
+                        }
+                    }
+                }
+            }
+        }
+
         if(equipments != null && equipments.size()>0){
             for (Equipment equipment : equipments) {
                 if(equipment != null && equipment.getEquipmentRunTimes() != null && equipment.getEquipmentRunTimes().size()>0){
@@ -486,7 +523,9 @@ public class ApsConstraintProvider implements ConstraintProvider {
             pp.setLastSerialLbWeight(equipment.getLastSerialLbWeight());
             hasStartTimeProcess.add(0,pp);
         }
-
+        if(hasStartTimeProcess.get(hasStartTimeProcess.size()-1).getId() != null && equipment.getId().equals("0001be252874536843730b100051")){
+            int aa = 2;
+        }
         // 周期立板已连续生产吨数
         BigDecimal zqlb = new BigDecimal("0");
         for(int i=0;i<hasStartTimeProcess.size()-1;i++){
@@ -494,15 +533,6 @@ public class ApsConstraintProvider implements ConstraintProvider {
             ProductionProcesses nextPro = hasStartTimeProcess.get(i+1);
             Map<String, String> conflictRoptions1 = prePro.getConflictRoptions();
             Map<String, String> conflictRoptions2 = nextPro.getConflictRoptions();
-            /*if(equipment.getId().equals("0001be252874536843730b100052")){
-                int aa = 1;
-                if(processes.size() == 10){
-                    aa = 2;
-                    if(prePro.getId() != null && prePro.getId().equals("b99ce83b171948bf8728b735b1529986")){
-                        aa = 3;
-                    }
-                }
-            }*/
             if(hasStartTimeProcess.get(i).getSeriesProduceMark() != null && hasStartTimeProcess.get(i+1).getSeriesProduceMark() != null){
                 String[] serspre = hasStartTimeProcess.get(i).getSeriesProduceMark().split("\\^_\\^");
                 String[] sersafter = hasStartTimeProcess.get(i+1).getSeriesProduceMark().split("\\^_\\^");
@@ -655,6 +685,9 @@ public class ApsConstraintProvider implements ConstraintProvider {
         if(processes != null && processes.size()>0){
             equipment = processes.get(0).getEquipment();
         }
+        if(processes.size() == 7){
+            int a = 0;
+        }
         List<ProductionProcesses> hasStartTimeProcess = processes.stream().filter(v -> v.getStartTime() != null).collect(Collectors.toList());
         // 设备占用时间参与连续生产排程
         if(equipment != null && equipment.getEquipmentRunTimes() != null && equipment.getEquipmentRunTimes().size()>0){
@@ -1164,20 +1197,42 @@ public class ApsConstraintProvider implements ConstraintProvider {
                         conflictRoptions2.put("hard-eqTimeCrossTuihuo","同一坯料计划不同工序退火不能排一起");
                         b++;
                     }else{
-                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-                        String startTimeKey = prePro.getStartTime().format(formatter);
-                        if(!ppMap.containsKey(startTimeKey)){
-                            List<ProductionProcesses> pps = new ArrayList<>();
-                            ppMap.put(startTimeKey,pps);
-                        }
-                        List<ProductionProcesses> processesList = ppMap.get(startTimeKey);
-                        List<ProductionProcesses> preHas = processesList.stream().filter(v -> v.getId().equals(prePro.getId())).collect(Collectors.toList());
-                        List<ProductionProcesses> nextHas = processesList.stream().filter(v -> v.getId().equals(nextPro.getId())).collect(Collectors.toList());
-                        if(preHas == null || preHas.size() == 0){
-                            processesList.add(prePro);
+                        // 判断总装炉卷数是否超过最大装炉卷数限制
+                        boolean overmaxroll = false;
+                        if(prePro.getOpeProducePcNum() != null && prePro.getOpeProducePcNum()>0 && nextPro.getOpeProducePcNum() != null && nextPro.getOpeProducePcNum()>0){
+                            int opp = prePro.getOpeProducePcNum() + nextPro.getOpeProducePcNum();
+                            Integer maxheatrollpre = prePro.getProduceOrder().get(0).getMaxheatroll();
+                            Integer maxheatrollnext = nextPro.getProduceOrder().get(0).getMaxheatroll();
+                            if(maxheatrollpre == null || maxheatrollpre<=0){
+                                maxheatrollpre = 4;
+                            }
+                            if(maxheatrollnext == null || maxheatrollnext<=0){
+                                maxheatrollnext = 4;
+                            }
+                            if(opp > maxheatrollpre || opp > maxheatrollnext){
+                                conflictRoptions1.put("hard-eqTimeCrossTuihuo","作业加工时间有交叉");
+                                conflictRoptions2.put("hard-eqTimeCrossTuihuo","作业加工时间有交叉");
+                                b++;
+                                overmaxroll = true;
+                            }
                         }
-                        if(nextHas == null || nextHas.size() == 0){
-                            processesList.add(nextPro);
+
+                        if(!overmaxroll){
+                            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                            String startTimeKey = prePro.getStartTime().format(formatter);
+                            if(!ppMap.containsKey(startTimeKey)){
+                                List<ProductionProcesses> pps = new ArrayList<>();
+                                ppMap.put(startTimeKey,pps);
+                            }
+                            List<ProductionProcesses> processesList = ppMap.get(startTimeKey);
+                            List<ProductionProcesses> preHas = processesList.stream().filter(v -> v.getId().equals(prePro.getId())).collect(Collectors.toList());
+                            List<ProductionProcesses> nextHas = processesList.stream().filter(v -> v.getId().equals(nextPro.getId())).collect(Collectors.toList());
+                            if(preHas == null || preHas.size() == 0){
+                                processesList.add(prePro);
+                            }
+                            if(nextHas == null || nextHas.size() == 0){
+                                processesList.add(nextPro);
+                            }
                         }
                     }
                 }
@@ -1496,7 +1551,7 @@ public class ApsConstraintProvider implements ConstraintProvider {
         if(processes != null && processes.size()>0){
             equipment = processes.get(0).getEquipment();
         }
-        if(equipment.getId().equals("0001be252874536843730b100124")){
+        if(equipment.getId().equals("0001be252874536843730b100056")){
             int abc = 1;
             if(processes.get(0).getDelay() == 100){
                 int abcd = 1;
@@ -1532,7 +1587,9 @@ public class ApsConstraintProvider implements ConstraintProvider {
                 pp.setConflictRoptions(new HashMap<>());
                 hasStartTimeProcess.add(0,pp);
             }else{
-                b = b+2;
+                if(equipment.getEquipmentRunTimes() == null || equipment.getEquipmentRunTimes().size() == 0){
+                    b = b+2;
+                }
             }
             for(int i=0;i<hasStartTimeProcess.size()-1;i++){
                 if(hasStartTimeProcess.get(i).getId() == null && hasStartTimeProcess.get(i+1).getId() == null){
@@ -2036,9 +2093,9 @@ public class ApsConstraintProvider implements ConstraintProvider {
      */
     private Constraint sameEquipment(ConstraintFactory constraintFactory){
         return constraintFactory.forEach(ProductionProcesses.class)
-                /*.filter(pro->{
-                    return pro.getProcessType().equals("铸轧") || pro.getProcessType().equals("冷轧");
-                })*/
+                .filter(pro->{
+                    return !pro.getProcessType().equals("成退") && !pro.getProcessType().equals("中退") && !pro.getProcessType().equals("小卷成退");
+                })
                 .groupBy(ProductionProcesses::getUniqueBsProcessesId,ConstraintCollectors.toList())
                 .filter((equipmentEquassociated,processes) -> {
                     if(processes != null && processes.size()>0){
@@ -2060,12 +2117,60 @@ public class ApsConstraintProvider implements ConstraintProvider {
                         }
                         System.out.println("*********************************");
                     }*/
+                    int a = 0;
                     Map<String, List<ProductionProcesses>> listMap = processes.stream().collect(Collectors.groupingBy(ProductionProcesses::getEquipmentId));
-                    return listMap.size()*10;
+                    a = listMap.size()*10;
+                    return a;
                 })
                 .asConstraint("sameEquipment");
     }
 
+    /**
+     * 冷轧尽量靠近
+     * @param constraintFactory
+     * @return
+     */
+    private Constraint sameBsLzClose(ConstraintFactory constraintFactory){
+        return constraintFactory.forEach(ProductionProcesses.class)
+                .filter((processes) -> "冷轧".equals(processes.getProcessType()))
+                .groupBy(ProductionProcesses::getUniqueBsProcessesId, ConstraintCollectors.toList())
+                .filter((uniqueBsProcessesId,processes) -> {
+                    if(processes != null && processes.size()>1){
+                        return true;
+                    }else{
+                        return false;
+                    }
+                })
+                .penalize(HardMediumSoftScore.ONE_SOFT,(uniqueBsProcessesId,processes)->{
+                    int countNum = 0;
+                    LocalDateTime maxTime = null;
+                    LocalDateTime minTime = null;
+                    for (ProductionProcesses process : processes) {
+                        LocalDateTime startTime = process.getStartTime();
+                        if(maxTime == null){
+                            maxTime = startTime;
+                        }else{
+                            if(startTime.compareTo(maxTime)>0){
+                                maxTime = startTime;
+                            }
+                        }
+                        if(minTime == null){
+                            minTime = startTime;
+                        }else{
+                            if(startTime.compareTo(minTime)<0){
+                                minTime = startTime;
+                            }
+                        }
+                    }
+                    if(minTime != null && maxTime != null){
+                        countNum = (int)ChronoUnit.MINUTES.between(minTime, maxTime);
+                    }
+                    return countNum*100;
+                })
+                .asConstraint("sameBsLzClose");
+
+    }
+
     /**
      * 硬约束:小卷成退合并约束
      * @param constraintFactory
@@ -2238,28 +2343,32 @@ public class ApsConstraintProvider implements ConstraintProvider {
     }
 
     /**
-     * 硬约束:铸轧最多排2条线
+     * 前后工序可以在一个设备上的尽量在一个设备上
      * @param constraintFactory
      * @return
      */
-    private Constraint twoLineZz(ConstraintFactory constraintFactory) {
+    private Constraint preNextProcessSameEq(ConstraintFactory constraintFactory) {
         return constraintFactory.forEach(ProductionProcesses.class)
                 .filter(pro->{
-                    return pro.getProcessType().equals("铸轧");
+                    boolean a = false;
+                    if(pro.getPreviousProcesses() != null && pro.getPreviousProcesses().size()>0){
+                        a = true;
+                    }
+                    return a;
                 })
-                .groupBy(ProductionProcesses::getUniqueBsProcessesId,ConstraintCollectors.toList())
-                .filter((bsProcessesId,processes) -> {
-                    if(processes != null && processes.size()>0){
-                        Map<String, List<ProductionProcesses>> listMap = processes.stream().collect(Collectors.groupingBy(ProductionProcesses::getEquipmentId));
-                        if(listMap.size()>2){
-                            return true;
+                .penalize(HardMediumSoftScore.ONE_SOFT,(processes)->{
+                    int a = 0;
+                    Equipment equipmentthis = processes.getEquipment();
+                    Equipment equipmentpre = processes.getPreviousProcesses().get(0).getEquipment();
+                    if(!equipmentpre.getId().equals(equipmentthis.getId())){
+                        a = a + 10000;
+                    }else{
+                        if(!equipmentpre.getWorkshopid().equals(equipmentthis.getWorkshopid())){
+                            a = a + 10000;
                         }
                     }
-                    return false;
-                })
-                .penalize(HardMediumSoftScore.ONE_HARD,(bsProcessesId,processes)->{
-                    return 50;
+                    return a;
                 })
-                .asConstraint("twoLineZz");
+                .asConstraint("preNextProcessSameEq");
     }
 }

+ 5 - 1
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/service/ApsService.java

@@ -16,6 +16,10 @@ public interface ApsService {
 
     List<ProductionProcesses> thProcessMerge(ProductionScheduleVo productionScheduleVo,ApsSolution apsSolution,List<ProductionProcesses> otherThproces);
 
-    List<ProductionProcesses> zzProcessAps(ProductionScheduleVo productionScheduleVo,ApsSolution apsSolution);
+    List<ProductionProcesses> thOtherMerge(List<ProductionProcesses> mergeprocesses,List<ProductionProcesses> otherThproces);
+
+    List<ProductionProcesses> zzProcessAps(ProductionScheduleVo productionScheduleVo,ApsSolution apsSolution,List<ProductionProcesses> otherNotZzFirstProces);
+
+    List<ProductionProcesses> seriesLzBzMerge(List<ProductionProcesses> mergeprocesses,List<ProductionProcesses> otherSerProces);
 
 }

+ 874 - 4
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/service/impl/ApsServiceImpl.java

@@ -231,6 +231,11 @@ public class ApsServiceImpl implements ApsService {
                             if(maxheatroll != null && maxheatroll < a){
                                 a = maxheatroll;
                             }
+                            if(equipment.getEquipmentParameter() != null && equipment.getEquipmentParameter().getMaxfurance() != null && equipment.getEquipmentParameter().getMaxfurance()>0){
+                                if(equipment.getEquipmentParameter().getMaxfurance() < a){
+                                    a = equipment.getEquipmentParameter().getMaxfurance();
+                                }
+                            }
 
                             // 作业计划加工卷数是否大于一炉最大卷数
                             if(v.get(0).getRooprocess() != null && v.get(0).getRooprocess().getStartTime() != null){
@@ -238,6 +243,9 @@ public class ApsServiceImpl implements ApsService {
                                     return p1.getRooprocess().getStartTime().compareTo(p2.getRooprocess().getStartTime());
                                 });
                             }
+                            if(a == 0){
+                                throw new ApsException(v.get(0).getUniqueBsProcessesId()+"作业单卷重超过设备承重或最大装炉卷数设置为0");
+                            }
 
                             List<List<ProductionProcesses>> chunks = new ArrayList<>();
                             int listSize = v.size();
@@ -245,7 +253,8 @@ public class ApsServiceImpl implements ApsService {
                                 chunks.add(v.subList(i, Math.min(i + a, listSize)));
                             }
                             // 合并退火作业
-                            for (List<ProductionProcesses> thps : chunks) {
+                            for(int j = 0;j < chunks.size();j++){
+                                List<ProductionProcesses> thps = chunks.get(j);
                                 for (int i = 0; i < thps.size(); i++) {
                                     if(i>0){
                                         // 设置待合并退火的主ID
@@ -311,7 +320,7 @@ public class ApsServiceImpl implements ApsService {
                                             thps.get(0).setNextProcesses(thnexts);
                                         }
                                         // 小卷退火卷数合并
-                                        if(thps.get(i).getProcessType().equals("小卷退")){
+                                        if(thps.get(i).getProcessType().equals("小卷退")){
                                             thps.get(0).setMinThPcNum(thps.get(0).getMinThPcNum()+thps.get(i).getMinThPcNum());
                                         }
                                     }
@@ -333,6 +342,859 @@ public class ApsServiceImpl implements ApsService {
         return mergeprocesses;
     }
 
+    /**
+     * 退火外合并工序:
+     * 根据退火工序合并冷轧、箔轧工序,同一个退火炉的冷轧、箔轧
+     */
+    public List<ProductionProcesses> thOtherMerge(List<ProductionProcesses> mergeprocesses,List<ProductionProcesses> otherThproces){
+        List<ProductionProcesses> lzmergeprocesses = new ArrayList<>();
+        // 根据订单分组
+        Map<String, List<ProductionProcesses>> orderProcess = mergeprocesses.stream().collect(Collectors.groupingBy(ProductionProcesses::getOrderId));
+        orderProcess.forEach((k,processes)->{
+            // 退火工序过滤
+            List<ProductionProcesses> thpros = new ArrayList<>();
+            // 所有单卷作业集合
+            Map<String,ProductionProcesses> allProMap = new HashMap<>();
+            // 按作业分组
+            Map<String,List<ProductionProcesses>> bsProceses = new HashMap<>();
+            // 合并后的作业集合
+            List<ProductionProcesses> othermergeprocesses = new ArrayList<>();
+            // 未合并的作业集合
+            List<ProductionProcesses> notMergeProces = new ArrayList<>();
+            // 已分组合并作业
+            List<String> hasMerge = new ArrayList<>();
+            for (ProductionProcesses mergeprocess : processes) {
+                if(mergeprocess.getProcessType().equals("成退") || mergeprocess.getProcessType().equals("中退") || mergeprocess.getProcessType().equals("小卷成退")){
+                    thpros.add(mergeprocess);
+                    othermergeprocesses.add(mergeprocess);
+                } else if (mergeprocess.getProcessType().equals("铸轧")) {
+                    othermergeprocesses.add(mergeprocess);
+                } else {
+                    if("是".equals(mergeprocess.getIssubsection())){
+                        othermergeprocesses.add(mergeprocess);
+                    }else {
+                        /*if(mergeprocess.getPreviousProcessesIds() == null || mergeprocess.getPreviousProcessesIds().size() == 0){
+                            othermergeprocesses.add(mergeprocess);
+                        }*/
+                    }
+                }
+                if(bsProceses.containsKey(mergeprocess.getUniqueBsProcessesId())){
+                    bsProceses.get(mergeprocess.getUniqueBsProcessesId()).add(mergeprocess);
+                }else{
+                    List<ProductionProcesses> bsProcese = new ArrayList<>();
+                    bsProcese.add(mergeprocess);
+                    bsProceses.put(mergeprocess.getUniqueBsProcessesId(),bsProcese);
+                }
+                allProMap.put(mergeprocess.getId(),mergeprocess);
+            }
+            // 根据退火合并作业
+            if(thpros != null && thpros.size()>0){
+                for (ProductionProcesses thpro : thpros) {
+                    // 退火作业往前合并
+                    thPreProMerge(thpro,notMergeProces,othermergeprocesses,bsProceses,hasMerge,allProMap);
+                }
+                for (ProductionProcesses thpro : thpros) {
+                    // 退火作业往后合并
+                    thNextProMerge(thpro,notMergeProces,othermergeprocesses,bsProceses,hasMerge,allProMap);
+                }
+            }
+            // 没有退火作业,按照默认最多4卷合并
+            else{
+                // 获取第一道工序的后一道工序作业开始合并
+                String secondbsid = null;
+                for(String bsid : bsProceses.keySet()) {
+                    List<ProductionProcesses> bspros = bsProceses.get(bsid);
+                    if(bspros != null && bspros.size()>0 && (bspros.get(0).getPreviousProcessesIds() == null || bspros.get(0).getPreviousProcessesIds().size() == 0)){
+                        if(bspros.get(0).getProcessType().equals("铸轧")){
+                            if(bspros.get(0).getNextProcesses() != null && bspros.get(0).getNextProcesses().size()>0){
+                                secondbsid = bspros.get(0).getNextProcesses().get(0).getUniqueBsProcessesId();
+                                break;
+                            }
+                        }else{
+                            secondbsid = bspros.get(0).getUniqueBsProcessesId();
+                        }
+                    }
+                }
+                fjNextMerge(secondbsid,notMergeProces,othermergeprocesses,bsProceses,hasMerge,allProMap);
+            }
+            // 剩余作业合并
+            List<ProductionProcesses> sypros = new ArrayList<>();
+            for (ProductionProcesses process : processes) {
+                if(!hasMerge.contains(process.getId())){
+                    if(!process.getProcessType().equals("铸轧") && !process.getProcessType().equals("成退")
+                            && !process.getProcessType().equals("中退") && !process.getProcessType().equals("小卷成退") && !"是".equals(process.getIssubsection())
+                            && process.getPreviousProcessesIds() != null && process.getPreviousProcessesIds().size()>0){
+                        sypros.add(process);
+                    }
+                }
+            }
+            // 按作业分组
+            if(sypros != null && sypros.size()>0){
+                Map<String, List<ProductionProcesses>> syProsMap = sypros.stream().collect(Collectors.groupingBy(ProductionProcesses::getUniqueBsProcessesId));
+                // 剩余作业按照默认4卷合并
+                syProsMap.forEach((bsid,processesList)->{
+                    if(processesList != null && processesList.size()>0){
+                        if(!hasMerge.contains(processesList.get(0).getId())){
+                            // 分卷默认4卷合并
+                            if(processesList.size()>1){
+                                // 根据承重计算最大几卷
+                                int a = 4;
+                                // 按照第一道工序排序
+                                if(processesList.get(0).getRooprocess() != null && processesList.get(0).getRooprocess().getStartTime() != null){
+                                    Collections.sort(processesList,(p1,p2)->{
+                                        return p1.getRooprocess().getStartTime().compareTo(p2.getRooprocess().getStartTime());
+                                    });
+                                }
+
+                                List<List<ProductionProcesses>> chunks = new ArrayList<>();
+                                int listSize = processesList.size();
+                                for (int i = 0; i < listSize; i += a) {
+                                    chunks.add(processesList.subList(i, Math.min(i + a, listSize)));
+                                }
+                                // 合并退火作业
+                                for (List<ProductionProcesses> thps : chunks) {
+                                    for (int i = 0; i < thps.size(); i++) {
+                                        if(i>0){
+                                            // 设置待合并退火的主ID
+                                            thps.get(i).setMergeThMainId(thps.get(0).getId());
+                                            notMergeProces.add(thps.get(i));
+                                            // 退火前一道作业设置下一作业ID
+                                            ProductionProcesses prepro = thps.get(i).getPreviousProcesses().get(0);
+                                            // 合并后关联关系重置
+                                            if(!prepro.getNextProcessesIds().contains(thps.get(0).getId())){
+                                                int i1 = prepro.getNextProcessesIds().indexOf(thps.get(i).getId());
+                                                prepro.getNextProcessesIds().set(i1,thps.get(0).getId());
+                                            }
+                                            List<String> list = new ArrayList<>();
+                                            Set<String> set = new LinkedHashSet<>();
+                                            for (String nextProcessesId : prepro.getNextProcessesIds()) {
+                                                set.add(nextProcessesId);
+                                            }
+                                            list.addAll(set);
+                                            prepro.setNextProcessesIds(list);
+                                            List<ProductionProcesses> nextpros = new ArrayList<>();
+                                            for (String nextProcessesId : prepro.getNextProcessesIds()) {
+                                                nextpros.add(allProMap.get(nextProcessesId));
+                                            }
+                                            prepro.setNextProcesses(nextpros);
+                                            // 当前合并退火作业设置前一道作业
+                                            if(!thps.get(0).getPreviousProcessesIds().contains(prepro.getId())){
+                                                thps.get(0).getPreviousProcessesIds().add(prepro.getId());
+                                            }
+                                            List<ProductionProcesses> previousProces = new ArrayList<>();
+                                            for (String pid : thps.get(0).getPreviousProcessesIds()) {
+                                                previousProces.add(allProMap.get(pid));
+                                            }
+                                            thps.get(0).setPreviousProcesses(previousProces);
+                                            // 退火后一道作业设置上一道作业ID
+                                            if(thps.get(i).getNextProcessesIds() != null && thps.get(i).getNextProcessesIds().size()>0){
+                                                for (String nextProcessesId : thps.get(i).getNextProcessesIds()) {
+                                                    ProductionProcesses nextpro = allProMap.get(nextProcessesId);
+                                                    // 合并后关联关系重置
+                                                    List<String> preids = new ArrayList<>();
+                                                    preids.add(thps.get(0).getId());
+                                                    nextpro.setPreviousProcessesIds(preids);
+
+                                                    List<ProductionProcesses> nextprepros = new ArrayList<>();
+                                                    for (String pid : nextpro.getPreviousProcessesIds()) {
+                                                        nextprepros.add(allProMap.get(pid));
+                                                    }
+                                                    nextpro.setPreviousProcesses(nextprepros);
+                                                }
+                                                // 设置合并退火作业下一道工序
+                                                thps.get(0).getNextProcessesIds().addAll(thps.get(i).getNextProcessesIds());
+                                                List<ProductionProcesses> thnexts = new ArrayList<>();
+                                                for (String pid : thps.get(0).getNextProcessesIds()) {
+                                                    thnexts.add(allProMap.get(pid));
+                                                }
+                                                thps.get(0).setNextProcesses(thnexts);
+                                            }
+                                            // 小卷退火卷数合并
+                                            if(thps.get(i).getProcessType().equals("小卷成退")){
+                                                thps.get(0).setMinThPcNum(thps.get(0).getMinThPcNum()+thps.get(i).getMinThPcNum());
+                                            }
+                                        }
+                                    }
+                                    // 取第一个作业作为合并作业
+                                    ProductionProcesses mergePro = thps.get(0);
+                                    mergePro.setOpeProducePcNum(thps.size());
+                                    mergePro.setProduceTime(mergePro.getProduceTime()*thps.size());
+                                    othermergeprocesses.add(mergePro);
+                                }
+                            }else{
+                                othermergeprocesses.addAll(processesList);
+                            }
+                            // 记录分卷已合并作业
+                            List<String> proids = processesList.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
+                            hasMerge.addAll(proids);
+                        }
+                    }
+                });
+            }
+
+            otherThproces.addAll(notMergeProces);
+            lzmergeprocesses.addAll(othermergeprocesses);
+        });
+        return lzmergeprocesses;
+    }
+
+    /**
+     * 退火作业向后合并作业
+     * @param thps
+     * @param notMergeProces
+     * @param mergeprocesses
+     * @param bsProceses
+     * @param hasMerge
+     * @param allProMap
+     */
+    private void thNextProMerge(ProductionProcesses thps,List<ProductionProcesses> notMergeProces,List<ProductionProcesses> mergeprocesses
+            ,Map<String,List<ProductionProcesses>> bsProceses,List<String> hasMerge,Map<String,ProductionProcesses> allProMap){
+        List<ProductionProcesses> nextProcesses = thps.getNextProcesses();
+        if(nextProcesses != null && nextProcesses.size()>0){
+            if(!nextProcesses.get(0).getProcessType().equals("铸轧") && !nextProcesses.get(0).getProcessType().equals("成退")
+                    && !nextProcesses.get(0).getProcessType().equals("中退") && !nextProcesses.get(0).getProcessType().equals("小卷成退")
+//                    && nextProcesses.get(0).getPreviousProcessesIds() != null && nextProcesses.get(0).getPreviousProcessesIds().size()>0
+            ){
+                // 分卷工序
+                if("是".equals(nextProcesses.get(0).getIssubsection())){
+                    for (ProductionProcesses nextProcess : nextProcesses) {
+                        List<ProductionProcesses> pres = new ArrayList<>();
+                        List<String> preids = new ArrayList<>();
+                        pres.add(thps);
+                        preids.add(thps.getId());
+                        nextProcess.setPreviousProcesses(pres);
+                        nextProcess.setPreviousProcessesIds(preids);
+                    }
+                    List<ProductionProcesses> processesList = bsProceses.get(nextProcesses.get(0).getUniqueBsProcessesId());
+                    if(processesList != null && processesList.size()>0){
+                        // 如果未合并则合并,并记录已合并的作业
+                        if(!hasMerge.contains(processesList.get(0).getId())){
+                            // 分卷的工序从此到工序的上一道工序开始合并,默认4卷
+                            fjNextMerge(processesList.get(0).getUniqueBsProcessesId(),notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
+                            // 记录合并作业ID
+                            List<String> proids = processesList.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
+                            hasMerge.addAll(proids);
+                        }
+                    }
+                }else{
+                    List<ProductionProcesses> mergePres = new ArrayList<>();
+                    mergePres.addAll(nextProcesses);
+                    if(!hasMerge.contains(mergePres.get(0).getId())){
+                        ProductionProcesses mergePro = mergePres.get(0);
+                        Map<String,ProductionProcesses> mergeProNexts = new HashMap<>();
+                        if(mergePres.size()>1){
+                            List<String> mergeProOrders = new ArrayList<>();
+                            mergeProOrders.add(mergePro.getId());
+                            mergePro.setMergeProOrders(mergeProOrders);
+                            for (int i = 0; i < mergePres.size(); i++) {
+                                if(i>0){
+                                    // 设置待合并退火的主ID
+                                    mergePres.get(i).setMergeThMainId(mergePres.get(0).getId());
+                                    mergePro.getMergeProOrders().add(mergePres.get(i).getId());
+                                    notMergeProces.add(mergePres.get(i));
+                                    if(mergePres.get(i).getNextProcesses() != null && mergePres.get(i).getNextProcesses().size()>0){
+                                        for (ProductionProcesses nextProcess : mergePres.get(i).getNextProcesses()) {
+                                            mergeProNexts.put(nextProcess.getId(),nextProcess);
+                                        }
+                                    }
+                                }
+                            }
+                            // 取第一个作业作为合并作业
+                            mergePro.setProduceTime(mergePro.getProduceTime()*mergePres.size());
+                            mergePro.setOpeProducePcNum(mergePres.size());
+                            List<String> nextids = new ArrayList<>();
+                            List<String> preids = new ArrayList<>();
+                            List<ProductionProcesses> nextpss = new ArrayList<>();
+                            List<ProductionProcesses> prepss = new ArrayList<>();
+                            nextpss.add(thps);
+                            nextids.add(thps.getId());
+                            mergePro.setPreviousProcesses(nextpss);
+                            mergePro.setPreviousProcessesIds(nextids);
+                            preids.add(mergePro.getId());
+                            prepss.add(mergePro);
+                            thps.setNextProcessesIds(preids);
+                            thps.setNextProcesses(prepss);
+                            // 合并作业的上一道工序
+                            if(mergeProNexts.size()>0){
+                                for (String proid:mergeProNexts.keySet()){
+                                    if(!mergePro.getNextProcessesIds().contains(proid)){
+                                        ProductionProcesses propro = mergeProNexts.get(proid);
+                                        mergePro.getNextProcessesIds().add(proid);
+                                        mergePro.getNextProcesses().add(propro);
+                                    }
+                                }
+                            }
+
+                            mergeprocesses.add(mergePro);
+                        }else{
+                            mergeprocesses.addAll(mergePres);
+                        }
+                        // 记录已合并的作业
+                        if(!hasMerge.contains(mergePres.get(0).getId())){
+                            List<String> proids = mergePres.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
+                            hasMerge.addAll(proids);
+                        }
+                        // 递归按照退火合并
+                        thNextProMerge(mergePro,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 合并除退火外其它作业
+     * @param thps
+     * @param notMergeProces
+     * @param mergeprocesses
+     * @param bsProceses
+     * @param hasMerge 已参与合并的作业ID(单卷作业ID)
+     */
+    private void thPreProMerge(ProductionProcesses thps,List<ProductionProcesses> notMergeProces,List<ProductionProcesses> mergeprocesses
+            ,Map<String,List<ProductionProcesses>> bsProceses,List<String> hasMerge,Map<String,ProductionProcesses> allProMap){
+        List<ProductionProcesses> previousProcesses = thps.getPreviousProcesses();
+        if(previousProcesses != null && previousProcesses.size()>0){
+            // 铸轧、退火、和第一道工序不合并
+            if(!previousProcesses.get(0).getProcessType().equals("铸轧") && !previousProcesses.get(0).getProcessType().equals("成退")
+                    && !previousProcesses.get(0).getProcessType().equals("中退") && !previousProcesses.get(0).getProcessType().equals("小卷成退")
+//                    && previousProcesses.get(0).getPreviousProcessesIds() != null && previousProcesses.get(0).getPreviousProcessesIds().size()>0
+            ){
+                // 分卷工序
+                if("是".equals(previousProcesses.get(0).getIssubsection())){
+                    for (ProductionProcesses preProcess : previousProcesses) {
+                        List<ProductionProcesses> nexts = new ArrayList<>();
+                        if(preProcess.getNextProcesses().size()>1){
+                            List<ProductionProcesses> othernexts = preProcess.getNextProcesses().stream().filter(v -> !v.getUniqueBsProcessesId().equals(thps.getUniqueBsProcessesId())).collect(Collectors.toList());
+                            othernexts.add(thps);
+                            nexts = othernexts;
+                        }else{
+                            nexts.add(thps);
+                        }
+                        preProcess.setNextProcesses(nexts);
+                        List<String> nextids = new ArrayList<>();
+                        for (ProductionProcesses next : nexts) {
+                            nextids.add(next.getId());
+                        }
+                        preProcess.setNextProcessesIds(nextids);
+                    }
+                    List<ProductionProcesses> processesList = bsProceses.get(previousProcesses.get(0).getUniqueBsProcessesId());
+                    if(processesList != null && processesList.size()>0){
+                        // 如果未合并则合并,并记录已合并的作业
+                        if(!hasMerge.contains(processesList.get(0).getId())){
+                            // 分卷的工序从此到工序的上一道工序开始合并,默认4卷
+                            fjMerge(processesList.get(0).getUniqueBsProcessesId(),notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
+                            // 记录合并作业ID
+                            List<String> proids = processesList.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
+                            hasMerge.addAll(proids);
+                        }
+                    }
+                }else{
+                    List<ProductionProcesses> mergePres = new ArrayList<>();
+                    mergePres.addAll(previousProcesses);
+                    if(!hasMerge.contains(mergePres.get(0).getId())){
+                        ProductionProcesses mergePro = mergePres.get(0);
+                        Map<String,ProductionProcesses> mergeProPres = new HashMap<>();
+                        if(mergePres.size()>1){
+                            List<String> mergeProOrders = new ArrayList<>();
+                            mergeProOrders.add(mergePro.getId());
+                            mergePro.setMergeProOrders(mergeProOrders);
+                            for (int i = 0; i < mergePres.size(); i++) {
+                                if(i>0){
+                                    // 设置待合并退火的主ID
+                                    mergePres.get(i).setMergeThMainId(mergePres.get(0).getId());
+                                    mergePro.getMergeProOrders().add(mergePres.get(i).getId());
+                                    notMergeProces.add(mergePres.get(i));
+                                    if(mergePres.get(i).getPreviousProcesses() != null && mergePres.get(i).getPreviousProcesses().size()>0){
+                                        for (ProductionProcesses previousProcess : mergePres.get(i).getPreviousProcesses()) {
+                                            mergeProPres.put(previousProcess.getId(),previousProcess);
+                                        }
+                                    }
+                                }
+                            }
+                            // 取第一个作业作为合并作业
+                            mergePro.setProduceTime(mergePro.getProduceTime()*mergePres.size());
+                            mergePro.setOpeProducePcNum(mergePres.size());
+                            List<String> nextids = new ArrayList<>();
+                            List<String> preids = new ArrayList<>();
+                            List<ProductionProcesses> nextpss = new ArrayList<>();
+                            List<ProductionProcesses> prepss = new ArrayList<>();
+                            nextpss.add(thps);
+                            nextids.add(thps.getId());
+                            mergePro.setNextProcesses(nextpss);
+                            mergePro.setNextProcessesIds(nextids);
+                            preids.add(mergePro.getId());
+                            prepss.add(mergePro);
+                            thps.setPreviousProcessesIds(preids);
+                            thps.setPreviousProcesses(prepss);
+                            // 合并作业的上一道工序
+                            if(mergeProPres.size()>0){
+                                for (String proid:mergeProPres.keySet()){
+                                    if(!mergePro.getPreviousProcessesIds().contains(proid)){
+                                        ProductionProcesses propro = mergeProPres.get(proid);
+                                        mergePro.getPreviousProcessesIds().add(proid);
+                                        mergePro.getPreviousProcesses().add(propro);
+                                    }
+                                }
+                            }
+
+                            mergeprocesses.add(mergePro);
+                        }else{
+                            mergeprocesses.addAll(mergePres);
+                        }
+                        // 记录已合并的作业
+                        if(!hasMerge.contains(mergePres.get(0).getId())){
+                            List<String> proids = mergePres.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
+                            hasMerge.addAll(proids);
+                        }
+                        // 递归按照退火合并
+                        thPreProMerge(mergePro,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
+                    }
+                }
+            }else{
+                // 第一道工序处理
+                if(previousProcesses.get(0).getPreviousProcessesIds() == null || previousProcesses.get(0).getPreviousProcessesIds().size() == 0){
+                    List<String> nextids = new ArrayList<>();
+                    List<ProductionProcesses> nextpss = new ArrayList<>();
+                    nextpss.add(thps);
+                    nextids.add(thps.getId());
+                    for (ProductionProcesses previousProcess : previousProcesses) {
+                        previousProcess.setNextProcesses(nextpss);
+                        previousProcess.setNextProcessesIds(nextids);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 分卷前作业合并处理
+     * @param bsprocessid
+     * @param notMergeProces
+     * @param mergeprocesses
+     * @param bsProceses
+     * @param hasMerge
+     * @param allProMap
+     */
+    private void fjMerge(String bsprocessid,List<ProductionProcesses> notMergeProces,List<ProductionProcesses> mergeprocesses
+            ,Map<String,List<ProductionProcesses>> bsProceses,List<String> hasMerge,Map<String,ProductionProcesses> allProMap){
+        List<ProductionProcesses> processesList = bsProceses.get(bsprocessid);
+        // 铸轧、退火、和第一道工序不合并
+        if(!processesList.get(0).getProcessType().equals("铸轧") && !processesList.get(0).getProcessType().equals("成退")
+                && !processesList.get(0).getProcessType().equals("中退") && !processesList.get(0).getProcessType().equals("小卷成退")
+//                && processesList.get(0).getPreviousProcessesIds() != null && processesList.get(0).getPreviousProcessesIds().size()>0
+        ){
+            if("是".equals(processesList.get(0).getIssubsection())){
+                if(processesList.get(0).getPreviousProcesses() != null && processesList.get(0).getPreviousProcesses().size()>0){
+                    String uniqueBsProcessesId = processesList.get(0).getPreviousProcesses().get(0).getUniqueBsProcessesId();
+                    fjMerge(uniqueBsProcessesId,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
+                }
+            }else{
+                if(processesList != null && processesList.size()>0){
+                    List<ProductionProcesses> pres = new ArrayList<>();
+                    if(!hasMerge.contains(processesList.get(0).getId())){
+                        // 分卷默认4卷合并
+                        if(processesList.size()>1){
+                            // 根据承重计算最大几卷
+                            int a = 4;
+                            // 按照第一道工序排序
+                            if(processesList.get(0).getRooprocess() != null && processesList.get(0).getRooprocess().getStartTime() != null){
+                                Collections.sort(processesList,(p1,p2)->{
+                                    return p1.getRooprocess().getStartTime().compareTo(p2.getRooprocess().getStartTime());
+                                });
+                            }
+
+                            List<List<ProductionProcesses>> chunks = new ArrayList<>();
+                            int listSize = processesList.size();
+                            for (int i = 0; i < listSize; i += a) {
+                                chunks.add(processesList.subList(i, Math.min(i + a, listSize)));
+                            }
+                            // 合并退火作业
+                            for (List<ProductionProcesses> thps : chunks) {
+                                // 取第一个作业作为合并作业
+                                ProductionProcesses mergePro = thps.get(0);
+                                List<String> mergeProOrders = new ArrayList<>();
+                                mergeProOrders.add(mergePro.getId());
+                                mergePro.setMergeProOrders(mergeProOrders);
+                                for (int i = 0; i < thps.size(); i++) {
+                                    if(i>0){
+                                        // 设置待合并退火的主ID
+                                        thps.get(i).setMergeThMainId(thps.get(0).getId());
+                                        mergePro.getMergeProOrders().add(thps.get(i).getId());
+                                        notMergeProces.add(thps.get(i));
+                                        if(thps.get(i).getPreviousProcesses() != null && thps.get(i).getPreviousProcesses().size() > 0){
+                                            // 退火前一道作业设置下一作业ID
+                                            ProductionProcesses prepro = thps.get(i).getPreviousProcesses().get(0);
+                                            // 合并后关联关系重置
+                                            if(!prepro.getNextProcessesIds().contains(thps.get(0).getId())){
+                                                int i1 = prepro.getNextProcessesIds().indexOf(thps.get(i).getId());
+                                                prepro.getNextProcessesIds().set(i1,thps.get(0).getId());
+                                            }
+                                            List<String> list = new ArrayList<>();
+                                            Set<String> set = new LinkedHashSet<>();
+                                            for (String nextProcessesId : prepro.getNextProcessesIds()) {
+                                                set.add(nextProcessesId);
+                                            }
+                                            list.addAll(set);
+                                            prepro.setNextProcessesIds(list);
+                                            List<ProductionProcesses> nextpros = new ArrayList<>();
+                                            for (String nextProcessesId : prepro.getNextProcessesIds()) {
+                                                nextpros.add(allProMap.get(nextProcessesId));
+                                            }
+                                            prepro.setNextProcesses(nextpros);
+                                            // 当前合并退火作业设置前一道作业
+                                            if(!thps.get(0).getPreviousProcessesIds().contains(prepro.getId())){
+                                                thps.get(0).getPreviousProcessesIds().add(prepro.getId());
+                                            }
+                                            List<ProductionProcesses> previousProces = new ArrayList<>();
+                                            for (String pid : thps.get(0).getPreviousProcessesIds()) {
+                                                previousProces.add(allProMap.get(pid));
+                                            }
+                                            thps.get(0).setPreviousProcesses(previousProces);
+                                        }
+                                        // 退火后一道作业设置上一道作业ID
+                                        if(thps.get(i).getNextProcessesIds() != null && thps.get(i).getNextProcessesIds().size()>0){
+                                            for (String nextProcessesId : thps.get(i).getNextProcessesIds()) {
+                                                ProductionProcesses nextpro = allProMap.get(nextProcessesId);
+                                                // 合并后关联关系重置
+                                                List<String> preids = new ArrayList<>();
+                                                preids.add(thps.get(0).getId());
+                                                nextpro.setPreviousProcessesIds(preids);
+
+                                                List<ProductionProcesses> nextprepros = new ArrayList<>();
+                                                for (String pid : nextpro.getPreviousProcessesIds()) {
+                                                    nextprepros.add(allProMap.get(pid));
+                                                }
+                                                nextpro.setPreviousProcesses(nextprepros);
+                                            }
+                                            // 设置合并退火作业下一道工序
+                                            thps.get(0).getNextProcessesIds().addAll(thps.get(i).getNextProcessesIds());
+                                            List<ProductionProcesses> thnexts = new ArrayList<>();
+                                            for (String pid : thps.get(0).getNextProcessesIds()) {
+                                                thnexts.add(allProMap.get(pid));
+                                            }
+                                            thps.get(0).setNextProcesses(thnexts);
+                                        }
+                                        // 小卷退火卷数合并
+                                        if(thps.get(i).getProcessType().equals("小卷成退")){
+                                            thps.get(0).setMinThPcNum(thps.get(0).getMinThPcNum()+thps.get(i).getMinThPcNum());
+                                        }
+                                    }
+                                }
+                                mergePro.setOpeProducePcNum(thps.size());
+                                mergePro.setProduceTime(mergePro.getProduceTime()*thps.size());
+                                mergeprocesses.add(mergePro);
+                                pres.add(mergePro);
+                            }
+                        }else{
+                            mergeprocesses.addAll(processesList);
+                            pres.addAll(processesList);
+                        }
+                        // 记录分卷已合并作业
+                        List<String> proids = processesList.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
+                        hasMerge.addAll(proids);
+                    }
+                    // 递归合并分卷前的作业
+                    if(pres != null && pres.size()>0){
+                        for (ProductionProcesses pre : pres) {
+                            thPreProMerge(pre,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
+                        }
+                        /*String uniqueBsProcessesId = processesList.get(0).getPreviousProcesses().get(0).getUniqueBsProcessesId();
+                        fjMerge(uniqueBsProcessesId,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);*/
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 分卷后作业合并处理
+     * @param bsprocessid
+     * @param notMergeProces
+     * @param mergeprocesses
+     * @param bsProceses
+     * @param hasMerge
+     * @param allProMap
+     */
+    private void fjNextMerge(String bsprocessid,List<ProductionProcesses> notMergeProces,List<ProductionProcesses> mergeprocesses
+            ,Map<String,List<ProductionProcesses>> bsProceses,List<String> hasMerge,Map<String,ProductionProcesses> allProMap){
+        List<ProductionProcesses> processesList = bsProceses.get(bsprocessid);
+        List<String> nextbsids = new ArrayList<>();
+        if(processesList != null && processesList.size()>0){
+            for (ProductionProcesses productionProcesses : processesList) {
+                if(productionProcesses.getNextProcesses() != null && productionProcesses.getNextProcesses().size()>0){
+                    for (ProductionProcesses nextProcess : productionProcesses.getNextProcesses()) {
+                        if(!nextbsids.contains(nextProcess.getUniqueBsProcessesId())){
+                            nextbsids.add(nextProcess.getUniqueBsProcessesId());
+                        }
+                    }
+                }
+            }
+        }
+        // 铸轧、退火、和第一道工序不合并
+        if(!processesList.get(0).getProcessType().equals("铸轧") && !processesList.get(0).getProcessType().equals("成退")
+                && !processesList.get(0).getProcessType().equals("中退") && !processesList.get(0).getProcessType().equals("小卷成退")
+//                && processesList.get(0).getPreviousProcessesIds() != null && processesList.get(0).getPreviousProcessesIds().size()>0
+        ){
+            if("是".equals(processesList.get(0).getIssubsection())){
+                if(nextbsids != null && nextbsids.size()>0){
+                    for (String nextbsid : nextbsids) {
+                        fjNextMerge(nextbsid,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
+                    }
+                }
+            }else{
+                if(processesList != null && processesList.size()>0){
+                    List<ProductionProcesses> nexts = new ArrayList<>();
+                    if(!hasMerge.contains(processesList.get(0).getId())){
+                        // 分卷默认4卷合并
+                        if(processesList.size()>1){
+                            // 根据承重计算最大几卷
+                            int a = 4;
+                            // 按照第一道工序排序
+                            if(processesList.get(0).getRooprocess() != null && processesList.get(0).getRooprocess().getStartTime() != null){
+                                Collections.sort(processesList,(p1,p2)->{
+                                    return p1.getRooprocess().getStartTime().compareTo(p2.getRooprocess().getStartTime());
+                                });
+                            }
+
+                            List<List<ProductionProcesses>> chunks = new ArrayList<>();
+                            int listSize = processesList.size();
+                            for (int i = 0; i < listSize; i += a) {
+                                chunks.add(processesList.subList(i, Math.min(i + a, listSize)));
+                            }
+                            // 合并退火作业
+                            for (List<ProductionProcesses> thps : chunks) {
+                                // 取第一个作业作为合并作业
+                                ProductionProcesses mergePro = thps.get(0);
+                                List<String> mergeProOrders = new ArrayList<>();
+                                mergeProOrders.add(mergePro.getId());
+                                mergePro.setMergeProOrders(mergeProOrders);
+                                for (int i = 0; i < thps.size(); i++) {
+                                    if(i>0){
+                                        // 设置待合并退火的主ID
+                                        thps.get(i).setMergeThMainId(thps.get(0).getId());
+                                        mergePro.getMergeProOrders().add(thps.get(i).getId());
+                                        notMergeProces.add(thps.get(i));
+                                        if(thps.get(i).getPreviousProcesses() != null && thps.get(i).getPreviousProcesses().size() > 0){
+                                            // 退火前一道作业设置下一作业ID
+                                            ProductionProcesses prepro = thps.get(i).getPreviousProcesses().get(0);
+                                            // 合并后关联关系重置
+                                            if(!prepro.getNextProcessesIds().contains(thps.get(0).getId())){
+                                                int i1 = prepro.getNextProcessesIds().indexOf(thps.get(i).getId());
+                                                prepro.getNextProcessesIds().set(i1,thps.get(0).getId());
+                                            }
+                                            List<String> list = new ArrayList<>();
+                                            Set<String> set = new LinkedHashSet<>();
+                                            for (String nextProcessesId : prepro.getNextProcessesIds()) {
+                                                set.add(nextProcessesId);
+                                            }
+                                            list.addAll(set);
+                                            prepro.setNextProcessesIds(list);
+                                            List<ProductionProcesses> nextpros = new ArrayList<>();
+                                            for (String nextProcessesId : prepro.getNextProcessesIds()) {
+                                                nextpros.add(allProMap.get(nextProcessesId));
+                                            }
+                                            prepro.setNextProcesses(nextpros);
+                                            // 当前合并退火作业设置前一道作业
+                                            if(!thps.get(0).getPreviousProcessesIds().contains(prepro.getId())){
+                                                thps.get(0).getPreviousProcessesIds().add(prepro.getId());
+                                            }
+                                            List<ProductionProcesses> previousProces = new ArrayList<>();
+                                            for (String pid : thps.get(0).getPreviousProcessesIds()) {
+                                                previousProces.add(allProMap.get(pid));
+                                            }
+                                            thps.get(0).setPreviousProcesses(previousProces);
+                                        }
+                                        // 退火后一道作业设置上一道作业ID
+                                        if(thps.get(i).getNextProcessesIds() != null && thps.get(i).getNextProcessesIds().size()>0){
+                                            for (String nextProcessesId : thps.get(i).getNextProcessesIds()) {
+                                                ProductionProcesses nextpro = allProMap.get(nextProcessesId);
+                                                // 合并后关联关系重置
+                                                List<String> preids = new ArrayList<>();
+                                                preids.add(thps.get(0).getId());
+                                                nextpro.setPreviousProcessesIds(preids);
+
+                                                List<ProductionProcesses> nextprepros = new ArrayList<>();
+                                                for (String pid : nextpro.getPreviousProcessesIds()) {
+                                                    nextprepros.add(allProMap.get(pid));
+                                                }
+                                                nextpro.setPreviousProcesses(nextprepros);
+                                            }
+                                            // 设置合并退火作业下一道工序
+                                            thps.get(0).getNextProcessesIds().addAll(thps.get(i).getNextProcessesIds());
+                                            List<ProductionProcesses> thnexts = new ArrayList<>();
+                                            for (String pid : thps.get(0).getNextProcessesIds()) {
+                                                thnexts.add(allProMap.get(pid));
+                                            }
+                                            thps.get(0).setNextProcesses(thnexts);
+                                        }
+                                        // 小卷退火卷数合并
+                                        if(thps.get(i).getProcessType().equals("小卷成退")){
+                                            thps.get(0).setMinThPcNum(thps.get(0).getMinThPcNum()+thps.get(i).getMinThPcNum());
+                                        }
+                                    }
+                                }
+                                mergePro.setOpeProducePcNum(thps.size());
+                                mergePro.setProduceTime(mergePro.getProduceTime()*thps.size());
+                                mergeprocesses.add(mergePro);
+                                nexts.add(mergePro);
+                            }
+                        }else{
+                            mergeprocesses.addAll(processesList);
+                            nexts.addAll(processesList);
+                        }
+                        // 记录分卷已合并作业
+                        List<String> proids = processesList.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
+                        hasMerge.addAll(proids);
+                    }
+                    // 递归合并分卷后的作业
+                    if(nexts != null && nexts.size()>0){
+                        for (ProductionProcesses next : nexts) {
+                            thNextProMerge(next,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
+                        }
+                        /*for (String nextbsid : nextbsids) {
+                            fjNextMerge(nextbsid,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
+                        }*/
+                    }
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 连续冷轧箔轧作业合并
+     * @param mergeprocesses
+     * @param otherSerProces
+     */
+    @Override
+    public List<ProductionProcesses> seriesLzBzMerge(List<ProductionProcesses> mergeprocesses,List<ProductionProcesses> otherSerProces){
+        List<ProductionProcesses> retPros = new ArrayList<>();
+        if(mergeprocesses != null && mergeprocesses.size()>0){
+            // 获取所有根节点
+            List<ProductionProcesses> rootPros = new ArrayList<>();
+            for (ProductionProcesses mergeprocess : mergeprocesses) {
+                if(mergeprocess.getPreviousProcesses() == null || mergeprocess.getPreviousProcesses().size() == 0){
+                    rootPros.add(mergeprocess);
+                }
+            }
+            // 被合并的作业
+            List<ProductionProcesses> lzbzMergeOthers = new ArrayList<>();
+            // 根据根节点逐级查询是否可合并的作业
+            if(rootPros != null && rootPros.size()>0){
+                Map<String,List<ProductionProcesses>> lzbzMerges = new HashMap<>();
+                // 已合并处理过作业ID
+                List<String> hasMid = new ArrayList<>();
+                for (ProductionProcesses rootPro : rootPros) {
+                    getLzBzSeries(rootPro,lzbzMerges,null,null,null,hasMid);
+                }
+                if(lzbzMerges != null && lzbzMerges.size()>0){
+                    for (String k:lzbzMerges.keySet()){
+                        List<ProductionProcesses> serPros = lzbzMerges.get(k);
+                        // 连续冷轧或箔轧超过1个,则合并
+                        if(serPros != null && serPros.size()>1){
+                            ProductionProcesses fMergePro = serPros.get(0);
+                            if(fMergePro.getMergeProOrders() == null){
+                                fMergePro.setMergeProOrders(new ArrayList<>());
+                                fMergePro.getMergeProOrders().add(fMergePro.getId());
+                            }
+                            // 按顺序依次合并
+                            for (int i = 0; i < serPros.size(); i++) {
+                                if(i>0){
+                                    serPros.get(i).setMergeThMainId(fMergePro.getId());
+                                    if(serPros.get(i).getMergeProOrders() == null){
+                                        fMergePro.getMergeProOrders().add(serPros.get(i).getId());
+                                    }else{
+                                        fMergePro.getMergeProOrders().addAll(serPros.get(i).getMergeProOrders());
+                                    }
+                                    fMergePro.setProduceTime(fMergePro.getProduceTime()+serPros.get(i).getProduceTime());
+                                    // 连续生产合并作业设置下道工序,以及合并后下道作业的上道工序
+                                    if(i == serPros.size()-1){
+                                        fMergePro.setNextProcesses(serPros.get(i).getNextProcesses());
+                                        fMergePro.setNextProcessesIds(serPros.get(i).getNextProcessesIds());
+                                        if(fMergePro.getNextProcesses() != null && fMergePro.getNextProcesses().size()>0){
+                                            for (ProductionProcesses nextProcess : fMergePro.getNextProcesses()) {
+                                                List<ProductionProcesses> pres = new ArrayList<>();
+                                                List<String> preids = new ArrayList<>();
+                                                pres.add(fMergePro);
+                                                preids.add(fMergePro.getId());
+                                                nextProcess.setPreviousProcesses(pres);
+                                                nextProcess.setPreviousProcessesIds(preids);
+                                            }
+                                        }
+                                    }
+                                    lzbzMergeOthers.add(serPros.get(i));
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            // 除去被合并的作业
+            if(lzbzMergeOthers != null && lzbzMergeOthers.size()>0){
+                List<String> lzbzMergeOtherIds = lzbzMergeOthers.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
+                for (ProductionProcesses mergeprocess : mergeprocesses) {
+                    if(!lzbzMergeOtherIds.contains(mergeprocess.getId())){
+                        retPros.add(mergeprocess);
+                    }
+                }
+            }else{
+                retPros.addAll(mergeprocesses);
+            }
+        }
+        return retPros;
+    }
+
+    private void getLzBzSeries(ProductionProcesses rootPro,Map<String,List<ProductionProcesses>> lzbzMerges
+            ,String seriesKey,String protype,List<String> commonEqus,List<String> hasMid){
+        if(!hasMid.contains(rootPro.getId())){
+            hasMid.add(rootPro.getId());
+            List<ProductionProcesses> nextProcesses = rootPro.getNextProcesses();
+            if("否".equals(rootPro.getIssubsection()) && ("冷轧".equals(rootPro.getProcessType()) || "箔轧".equals(rootPro.getProcessType()))){
+                // 是否连续冷轧、箔轧
+                boolean hasSeries = false;
+                if(StrUtil.isNotBlank(seriesKey) && StrUtil.isNotBlank(protype) && protype.equals(rootPro.getProcessType())){
+                    if(commonEqus != null && commonEqus.size()>0){
+                        List<String> commonEqusNext = new ArrayList<>();
+                        for (String optionalEquipment : rootPro.getOptionalEquipments()) {
+                            if(commonEqus.contains(optionalEquipment)){
+                                commonEqusNext.add(optionalEquipment);
+                            }
+                        }
+                        if(commonEqusNext != null && commonEqusNext.size()>0){
+                            hasSeries = true;
+                            lzbzMerges.get(seriesKey).add(rootPro);
+                            commonEqus = commonEqusNext;
+                        }
+                    }
+                }
+                if(nextProcesses != null && nextProcesses.size()>0){
+                    // 不能和上一道工序连续,则作为第一道连续工序
+                    if(!hasSeries){
+                        List<ProductionProcesses> serPros = new ArrayList<>();
+                        serPros.add(rootPro);
+                        lzbzMerges.put(rootPro.getId(),serPros);
+                        // 上下道工序共用的可选设备
+                        commonEqus = new ArrayList<>();
+                        commonEqus.addAll(rootPro.getOptionalEquipments());
+                    }
+                    for (ProductionProcesses nextProcess : nextProcesses) {
+                        if(hasSeries){
+                            getLzBzSeries(nextProcess,lzbzMerges,seriesKey,rootPro.getProcessType(),commonEqus,hasMid);
+                        }else{
+                            getLzBzSeries(nextProcess,lzbzMerges,rootPro.getId(),rootPro.getProcessType(),commonEqus,hasMid);
+                        }
+                    }
+                }
+            }else{
+                if(nextProcesses != null && nextProcesses.size()>0){
+                    for (ProductionProcesses nextProcess : nextProcesses) {
+                        getLzBzSeries(nextProcess,lzbzMerges,null,null,null,hasMid);
+                    }
+                }
+            }
+        }
+    }
+
     /**
      * 多订单合并
      * @param productionScheduleVo
@@ -452,7 +1314,7 @@ public class ApsServiceImpl implements ApsService {
      * @return
      */
     @Override
-    public List<ProductionProcesses> zzProcessAps(ProductionScheduleVo productionScheduleVo, ApsSolution apsSolution) {
+    public List<ProductionProcesses> zzProcessAps(ProductionScheduleVo productionScheduleVo, ApsSolution apsSolution,List<ProductionProcesses> otherNotZzFirstProces) {
         ApsSolution apsSolutionZz = new ApsSolution();
         List<ProductionProcesses> zzprocesList = new ArrayList<>();
         for (ProductionProcesses process : apsSolution.getProcessesList()) {
@@ -460,6 +1322,14 @@ public class ApsServiceImpl implements ApsService {
                 zzprocesList.add(process);
             }
         }
+        if(zzprocesList.size() == 0){
+            for (ProductionProcesses process : apsSolution.getProcessesList()) {
+                if((process.getPreviousProcessesIds() == null || process.getPreviousProcessesIds().size() == 0) && !process.getIfLock()){
+                    zzprocesList.add(process);
+                    otherNotZzFirstProces.add(process);
+                }
+            }
+        }
         if(zzprocesList != null && zzprocesList.size()>0){
             apsSolutionZz.setStartTime(apsSolution.getStartTime());
             apsSolutionZz.setEquipmentList(apsSolution.getEquipmentList());
@@ -493,7 +1363,7 @@ public class ApsServiceImpl implements ApsService {
             log.info("**************铸轧排程评分分析***************");
 
             for (ProductionProcesses process : apsSolution.getProcessesList()) {
-                if(process.getProcessType().equals("铸轧")){
+                if(process.getProcessType().equals("铸轧") || (process.getPreviousProcessesIds() == null || process.getPreviousProcessesIds().size() == 0)){
                     List<ProductionProcesses> collect = solvedBalance1.getProcessesList().stream().filter(v -> v.getId().equals(process.getId())).collect(Collectors.toList());
                     if(collect != null && collect.size()>0){
                         process.setStartTime(collect.get(0).getStartTime());

+ 165 - 30
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/service/impl/ProductionScheduleServiceImpl.java

@@ -111,20 +111,57 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
                     }
                     System.out.println("************"+event.getNewBestScore()+"************");
                     log.info("************"+event.getNewBestScore()+"************");
+
+                    // 终止排程
+//                    solver.terminateEarly();
                 }
             }
         });
         // optaplanner 求解器数据装配
         List<ProductionProcesses> otherThproces = new ArrayList<>();
+        List<ProductionProcesses> otherNotThproces = new ArrayList<>();
         ApsSolution apsSolution = getPreApsSolution(productionScheduleVo,otherThproces);
+        //非铸轧第一道工序,提前排程
+        List<ProductionProcesses> otherNotZzFirstProces = new ArrayList<>();
         // 铸轧提前排序
-        apsService.zzProcessAps(productionScheduleVo,apsSolution);
+        apsService.zzProcessAps(productionScheduleVo,apsSolution,otherNotZzFirstProces);
+        // 全量排程数据备份
+        List<ProductionProcesses> allToApsProcess = new ArrayList<>();
+        allToApsProcess.addAll(apsSolution.getProcessesList());
+        Map<String,ProductionProcesses> allToApsProcesMaps = new HashMap<>();
+        for (ProductionProcesses toApsProcess : allToApsProcess) {
+            allToApsProcesMaps.put(toApsProcess.getId(),toApsProcess);
+        }
         /*if(1 == 1){
             return null;
         }*/
         // 退火合并
         List<ProductionProcesses> thList = apsService.thProcessMerge(productionScheduleVo,apsSolution,otherThproces);
         apsSolution.setProcessesList(thList);
+        List<ProductionProcesses> processesList = apsService.thOtherMerge(thList, otherNotThproces);
+        apsSolution.setProcessesList(processesList);
+
+        List<ProductionProcesses> otherSerProces = new ArrayList<>();
+        List<ProductionProcesses> otherSerProcesMerges = apsService.seriesLzBzMerge(processesList, otherSerProces);
+        apsSolution.setProcessesList(otherSerProcesMerges);
+        // 排程作业排序
+        sortProcess(apsSolution.getProcessesList(),1);
+        // 取消第一道工序非铸轧提前排程的锁定状态
+        if(otherNotZzFirstProces != null && otherNotZzFirstProces.size()>0){
+            for (ProductionProcesses otherSerProcesMerge : apsSolution.getProcessesList()) {
+                if(otherSerProcesMerge.getIfLock()){
+                    List<ProductionProcesses> list1 = otherNotZzFirstProces.stream().filter(v -> v.getId().equals(otherSerProcesMerge.getId())).collect(Collectors.toList());
+                    if(list1 != null && list1.size()>0){
+                        otherSerProcesMerge.setIfLock(false);
+                        otherSerProcesMerge.setStartTime(null);
+                        otherSerProcesMerge.setEndTime(null);
+                        otherSerProcesMerge.setEquipment(null);
+                        otherSerProcesMerge.setEquipmentId(null);
+                        otherSerProcesMerge.setDelay(null);
+                    }
+                }
+            }
+        }
         // 去掉锁定工序
         List<ProductionProcesses> notLocks = new ArrayList<>();
         List<ProductionProcesses> hasLocks = new ArrayList<>();
@@ -141,8 +178,6 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
             throw new ApsException("没有可排程的工序");
         }
         apsSolution.setProcessesList(notLocks);
-
-        sortProcess(apsSolution.getProcessesList());
         ApsSolution solvedBalance = solver.solve(apsSolution);
         log.info("**************排程评分分析***************");
         SolutionManager<ApsSolution, HardSoftScore> scoreManager = SolutionManager.create(solverFactory);
@@ -193,6 +228,7 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
         productionScheduleRetVo.setProcesses(solvedBalance.getProcessesList());
         // 循环引用ProductionProcesses置空
 //        solvedBalance.getProcessesList().addAll(solvedBalance1.getProcessesList());
+        // 退火合并工序排程完拆分
         if(otherThproces != null && otherThproces.size()>0){
             for (ProductionProcesses otherThproce : otherThproces) {
                 if(StrUtil.isNotBlank(otherThproce.getMergeThMainId())){
@@ -237,8 +273,57 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
                 }
             }
         }
+        // 非退火合并工序排程完拆分
+        /*if(otherNotThproces != null && otherNotThproces.size()>0){
+            for (ProductionProcesses otherNotThproce : otherNotThproces) {
+                if(StrUtil.isNotBlank(otherNotThproce.getMergeThMainId())){
+                    ProductionProcesses thpro = null;
+                    for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
+                        if(productionProcesses.getId().equals(otherNotThproce.getMergeThMainId())){
+                            thpro = productionProcesses;
+                            break;
+                        }
+                    }
+                    if(thpro != null){
+                        otherNotThproce.setStartTime(thpro.getEndTime().minusMinutes(otherNotThproce.getProduceTime()));
+                        otherNotThproce.setEndTime(thpro.getEndTime());
+                        otherNotThproce.setEquipmentId(thpro.getEquipmentId());
+                        otherNotThproce.setEquipment(thpro.getEquipment());
+                        otherNotThproce.setConflictRoptions(thpro.getConflictRoptions());
+
+                        thpro.setOpeProducePcNum(1);
+                        thpro.setProduceTime(thpro.getProduceTime()-otherNotThproce.getProduceTime());
+                        thpro.setEndTime(thpro.getEndTime().minusMinutes(otherNotThproce.getProduceTime()));
+                    }
+
+                }
+            }
+        }*/
+        // 非退火合并拆分
+        List<ProductionProcesses> sers = new ArrayList<>();
+        for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
+            if(productionProcesses.getMergeProOrders() != null && productionProcesses.getMergeProOrders().size()>0){
+                List<String> mergeProOrders = productionProcesses.getMergeProOrders();
+                for (int i = mergeProOrders.size()-1; i > 0; i--) {
+                    ProductionProcesses po = allToApsProcesMaps.get(mergeProOrders.get(i));
+                    po.setStartTime(productionProcesses.getEndTime().minusMinutes(po.getUnitProduceTime()));
+                    po.setEndTime(productionProcesses.getEndTime());
+                    po.setEquipmentId(productionProcesses.getEquipmentId());
+                    po.setEquipment(productionProcesses.getEquipment());
+//                    po.setConflictRoptions(productionProcesses.getConflictRoptions());
+
+                    productionProcesses.setOpeProducePcNum(1);
+                    productionProcesses.setProduceTime(productionProcesses.getProduceTime()-po.getUnitProduceTime());
+                    productionProcesses.setEndTime(productionProcesses.getEndTime().minusMinutes(po.getUnitProduceTime()));
+
+                    sers.add(po);
+                }
+            }
+        }
 
         solvedBalance.getProcessesList().addAll(otherThproces);
+        solvedBalance.getProcessesList().addAll(sers);
+//        solvedBalance.getProcessesList().addAll(otherNotThproces);
         for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
             productionProcesses.setPreviousProcesses(null);
             productionProcesses.setRooprocess(null);
@@ -736,6 +821,10 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
                 if(pres != null && pres.size()>0){
                     process.setPreviousProcesses(pres);
                 }
+                // 前道工序历史备份
+                List<String> oldpreids = new ArrayList<>();
+                oldpreids.addAll(process.getPreviousProcessesIds());
+                process.setOldPreviousProcessesIds(oldpreids);
             }
             // 后道工序
             if(process.getNextProcessesIds() != null && process.getNextProcessesIds().size()>0){
@@ -754,6 +843,10 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
                 if(nexts != null && nexts.size()>0){
                     process.setNextProcesses(nexts);
                 }
+                // 后道工序历史备份
+                List<String> oldnextids = new ArrayList<>();
+                oldnextids.addAll(process.getNextProcessesIds());
+                process.setOldNextProcessesIds(oldnextids);
             }
             // 默认批次为1
             if(process.getProducePcNum() == null){
@@ -781,6 +874,11 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
                 }
                 process.setOptionalProviderEquipments(providedEq);
             }
+            // 铸轧机熔炉分组
+            List<Equipment> zzrls = productionScheduleVo.getEquipmentList().stream().filter(v->StrUtil.isNotBlank(v.getEquassociated())).collect(Collectors.toList());
+            Map<String, List<Equipment>> equass = zzrls.stream().collect(Collectors.groupingBy(Equipment::getEquassociated));
+            process.setEquass(equass);
+
             // 上机时间和下机时间如果为null,设置为0
             if(process.getPrepressworkmin() == null){
                 process.setPrepressworkmin(0);
@@ -901,12 +999,12 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
         // 工序任务初始化
         unsolvedCloudBalance.setProcessesList(productionProcesses);*/
 
-        sortProcess(productionScheduleVo.getProcesses());
+        sortProcess(productionScheduleVo.getProcesses(),0);
         unsolvedCloudBalance.setProcessesList(productionScheduleVo.getProcesses());
         return unsolvedCloudBalance;
     }
 
-    private List<ProductionProcesses> sortProcess(List<ProductionProcesses> sources){
+    private List<ProductionProcesses> sortProcess(List<ProductionProcesses> sources,int sortType){
         // 排序后的列表
         List<ProductionProcesses> processes = new ArrayList<>();
         // 任务的排序
@@ -941,30 +1039,23 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
                 }
                 if(roots != null && roots.size()>0){
                     //设置下一节点的根目录
-                    for (ProductionProcesses root : roots) {
-                        setNextProRoot(root,root);
+                    if(sortType == 0){
+                        for (ProductionProcesses root : roots) {
+                            setNextProRoot(root,root);
+                        }
                     }
-                    ProductionProcesses rootPro = roots.get(0);
-                    nextProSort(sortMap,bsMap,rootPro.getUniqueBsProcessesId());
+
+                    if(sortType == 1){
+                        ProductionProcesses rootPro = roots.get(0);
+                        nextProSort(sortMap,bsMap,rootPro.getUniqueBsProcessesId());
+                    }
+
                 }
             }
         }
-
-        // 订单作业列表
-        /*Map<String,Integer> orderMap = new HashMap<>();
-        orderMap.put("orderMark",0);
-        for (ProductionProcesses root : roots) {
-            orderMap.put("orderMark",orderMap.get("orderMark")+1);
-            root.setOrderMark(orderMap.get("orderMark"));
-            setProcessSort(root,orderMap);
+        if(sortType == 1){
+            sources.sort(Comparator.comparing(ProductionProcesses::getOrderMark));
         }
-        for (ProductionProcesses source : sources) {
-            if(source.getOrderMark() == null){
-                System.out.println(source);
-            }
-        }*/
-        sources.sort(Comparator.comparing(ProductionProcesses::getOrderMark));
-
         return processes;
     }
 
@@ -983,11 +1074,7 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
     private void nextProSort(Map<String,Integer> sortMap,Map<String,List<ProductionProcesses>> bsMap,String uniqueBsProcessesId){
         List<ProductionProcesses> processesList1 = bsMap.get(uniqueBsProcessesId);
         if(processesList1 != null && processesList1.size()>0){
-            if(processesList1.get(0).getProcessType().equals("成退") || processesList1.get(0).getProcessType().equals("中退") || processesList1.get(0).getProcessType().equals("小卷成退")
-//            if(processesList1.get(0).getNextProcesses() != null && (processesList1.get(0).getNextProcesses().get(0).getProcessType().equals("成退")
-//                    || processesList1.get(0).getNextProcesses().get(0).getProcessType().equals("中退")
-//                    || processesList1.get(0).getNextProcesses().get(0).getProcessType().equals("小卷成退"))
-            ){
+            /*if(processesList1.get(0).getProcessType().equals("成退") || processesList1.get(0).getProcessType().equals("中退") || processesList1.get(0).getProcessType().equals("小卷成退")){
                 if(processesList1.get(0).getPreviousProcesses() != null && processesList1.get(0).getPreviousProcesses().size()>0){
                     for (ProductionProcesses productionProcesses : processesList1) {
                         productionProcesses.setOrderMark(productionProcesses.getPreviousProcesses().get(0).getOrderMark());
@@ -1005,7 +1092,42 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
                         productionProcesses.setOrderMark(sortMap.get("sortInt"));
                     }
                 }
+            }else if(processesList1.get(0).getProcessType().equals("冷轧")){
+                if(processesList1.get(0).getRooprocess() != null && processesList1.get(0).getRooprocess().getStartTime() != null){
+                    // 按照铸轧开始时间排序
+                    Collections.sort(processesList1,(p1,p2)->{
+                        return p2.getRooprocess().getStartTime().compareTo(p1.getRooprocess().getStartTime());
+                    });
+                    for (int i = 0;i<processesList1.size();i++) {
+                        ProductionProcesses productionProcesses = processesList1.get(i);
+                        sortMap.put("sortInt",sortMap.get("sortInt")+1);
+                        productionProcesses.setOrderMark(sortMap.get("sortInt"));
+                    }
+                }else{
+                    for (int i = 0;i<processesList1.size();i++) {
+                        ProductionProcesses productionProcesses = processesList1.get(i);
+                        sortMap.put("sortInt",sortMap.get("sortInt")+1);
+                        productionProcesses.setOrderMark(sortMap.get("sortInt"));
+                    }
+                }
+            }else{
+                for (int i = 0;i<processesList1.size();i++) {
+                    ProductionProcesses productionProcesses = processesList1.get(i);
+                    sortMap.put("sortInt",sortMap.get("sortInt")+1);
+                    productionProcesses.setOrderMark(sortMap.get("sortInt"));
+                }
+            }*/
 
+            if(processesList1.get(0).getRooprocess() != null && processesList1.get(0).getRooprocess().getStartTime() != null){
+                // 按照铸轧开始时间排序
+                Collections.sort(processesList1,(p1,p2)->{
+                    return p1.getRooprocess().getStartTime().compareTo(p2.getRooprocess().getStartTime());
+                });
+                for (int i = 0;i<processesList1.size();i++) {
+                    ProductionProcesses productionProcesses = processesList1.get(i);
+                    sortMap.put("sortInt",sortMap.get("sortInt")+1);
+                    productionProcesses.setOrderMark(sortMap.get("sortInt"));
+                }
             }else{
                 for (int i = 0;i<processesList1.size();i++) {
                     ProductionProcesses productionProcesses = processesList1.get(i);
@@ -1013,6 +1135,7 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
                     productionProcesses.setOrderMark(sortMap.get("sortInt"));
                 }
             }
+
             Set<String> uniqueBsProcessesIdSet = new HashSet<>();
             for (ProductionProcesses productionProcesses : processesList1) {
                 if(productionProcesses.getNextProcesses() != null && productionProcesses.getNextProcesses().size()>0){
@@ -1022,8 +1145,20 @@ public class ProductionScheduleServiceImpl implements ProductionScheduleService
                 }
             }
             if(uniqueBsProcessesIdSet != null && uniqueBsProcessesIdSet.size()>0){
+                List<ProductionProcesses> uniqueBsProcessesIdList = new ArrayList<>();
                 for (String psid : uniqueBsProcessesIdSet) {
-                    nextProSort(sortMap,bsMap,psid);
+                    List<ProductionProcesses> processesList = bsMap.get(psid);
+                    if(processesList != null && processesList.size()>0){
+                        uniqueBsProcessesIdList.add(processesList.get(0));
+                    }
+                }
+                // 按照宽度从大到小排序
+                Collections.sort(uniqueBsProcessesIdList,(p1,p2)->{
+                    return p2.getVolumeWidth().compareTo(p1.getVolumeWidth());
+                });
+
+                for (ProductionProcesses psid : uniqueBsProcessesIdList) {
+                    nextProSort(sortMap,bsMap,psid.getUniqueBsProcessesId());
                 }
             }
         }