Commit ccd683c2 authored by Tong Li's avatar Tong Li

倒排配套

parent da524907
......@@ -38,6 +38,7 @@ public class GAScheduleResult {
private int lockStartTime = 0; // 是否固定开始时间(默认-1)
private Long forcedMachineId =-1L; // 强制分配的设备ID(-1表示无强制)
private boolean IsLocked=false;
private boolean IsJit=false;
private double OneTime; // 单件工时
private double ProcessingTime; // 绝对处理时间(分钟)
private int changeOverTime;
......
......@@ -863,19 +863,49 @@ public class GeneticDecoder {
orderProcessCounter.put(groupId, orderProcessCounter.get(groupId) + 1);
orderLastEndTime.put(groupId, actualEndTime);
if (orderProcessCounter.get(groupId) >= entrysBygroupId.get(groupId).size()) {
// if (jitDeferredBomOrderIds.remove(groupId)) {
// entrysBygroupId.get(groupId).stream()
// .sorted(Comparator.comparingInt(Entry::getSequence))
// .forEach(op -> {
// GAScheduleResult result = scheduleIndexById.get(op.getId());
// if (result != null) {
// EditOperationBOMTime(op, chromosome, result.getStartTime(),
// machineTasksCache, entryIndexById,
// scheduleIndexById);
// }
// });
// }
if (isJit&& orderProcessCounter.get(groupId) >= entrysBygroupId.get(groupId).size()) {
List<Entry> orderOpsBySeq = entrysBygroupId.get(groupId).stream()
.sorted(Comparator.comparingInt(Entry::getSequence))
.collect(Collectors.toList());
boolean bomFailed = false;
int failedSeq = -1;
int failedBomTime = 0;
for (Entry op : orderOpsBySeq) {
GAScheduleResult result = scheduleIndexById.get(op.getId());
if (result == null||!result.isIsJit()) continue;
int bomTime = getOperationBOMTime(op, chromosome, result.getStartTime(), 3,_globalParam.isIsCheckMp());
if (bomTime <= result.getStartTime()) {
EditOperationBOMTime(op, chromosome, result.getStartTime(),
machineTasksCache, entryIndexById,
scheduleIndexById);
} else {
bomFailed = true;
failedSeq = op.getSequence();
failedBomTime = bomTime;
break;
}
}
if (bomFailed) {
int finalFailedSeq = failedSeq;
Set<Integer> keepOpIds = orderOpsBySeq.stream()
.filter(op -> op.getSequence() < finalFailedSeq)
.map(Entry::getId)
.collect(Collectors.toSet());
FileHelper.writeLogFile("[BomFallback] 订单" + groupId
+ "工序" + failedSeq + "物料不足(bomTime="
+ failedBomTime + " > startTime),从该工序开始正排");
List<Integer> removeOp = clearOrderSchedulingForForwardFallback(chromosome, groupId,
machineTasksCache, scheduleIndexById,entryIndexById, keepOpIds);
int forwardEndTime = scheduleOrderForwardFallback(groupId,removeOp,failedBomTime,
chromosome,entrysBygroupId, machineIdMap, machineTasksCache,
entryIndexById, scheduleIndexById, opMachineKeyMap);
forwardFallbackOrderIds.add(groupId);
orderSchedulingInfo.put(groupId,
new AbstractMap.SimpleEntry<>(false, 0));
orderLastEndTime.put(groupId, forwardEndTime);
}
if (semiFinishedOrderIds.contains(groupId)) {
Set<Integer> pendingFinishedIds = pendingReForwardMap.remove(groupId);
if (pendingFinishedIds != null && !pendingFinishedIds.isEmpty()) {
......@@ -1439,10 +1469,21 @@ public class GeneticDecoder {
private List<Integer> clearOrderSchedulingForForwardFallback(Chromosome chromosome,
int groupId,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
Map<Integer, GAScheduleResult> scheduleIndexById) {
List<GAScheduleResult> resultsToRemove = chromosome.getResult().stream()
.filter(t -> t.getGroupId() == groupId)
.collect(Collectors.toList());
Map<Integer, GAScheduleResult> scheduleIndexById,Map<Integer, Entry> entryIndexById,Set<Integer> keepOpIds) {
List<GAScheduleResult> resultsToRemove=new ArrayList<>();
if(keepOpIds!=null&&keepOpIds.size()>0)
{
resultsToRemove = chromosome.getResult().stream()
.filter(t -> t.getGroupId() == groupId)
.filter(t -> !keepOpIds.contains(t.getOperationId()))
.collect(Collectors.toList());
}else {
resultsToRemove = chromosome.getResult().stream()
.filter(t -> t.getGroupId() == groupId)
.collect(Collectors.toList());
}
List<Integer> operations=new ArrayList<>();
for (GAScheduleResult result : resultsToRemove) {
......@@ -1458,6 +1499,14 @@ public class GeneticDecoder {
if (machineTasks != null) {
machineTasks.removeIf(t -> t.getOperationId() == result.getOperationId());
}
Entry op= entryIndexById.get(result.getOperationId());
Map<String, MaterialDeduction> deductions = readOperationStockDeductions(op);
if (deductions != null && !deductions.isEmpty()) {
rollbackOperationStockDeduction(chromosome, deductions);
}
}
machineTasksCache.clear();
......@@ -1488,8 +1537,13 @@ public class GeneticDecoder {
for (GAScheduleResult result : resultsToRemove) {
Entry op= entrysBygroupId.get(result.getGroupId()).get(result.getOperationId());
Map<String, MaterialDeduction> deductions = readOperationStockDeductions(op);
if (deductions != null && !deductions.isEmpty()) {
rollbackOperationStockDeduction(chromosome, deductions);
}
Machine machine = getMachineById(chromosome, result.getMachineId());
if (machine != null) {
AddMachineAvailable(machine, result.getGeneDetails());
......@@ -1633,8 +1687,8 @@ public class GeneticDecoder {
endTime = startTime + processingTimeTotal;
}
GAScheduleResult result = CreateResult(operation, machine.getId(), startTime, endTime, processingTime, 0, preTime, teardownTime, 0, null, existingResult);
result.setCapacityTypeName(machine.getCapacityTypeName());
GAScheduleResult result = CreateResult(operation, machine.getId(), startTime, endTime, processingTime, 0, preTime, teardownTime, 0, null, existingResult,machine.getCapacityTypeName(),isJit);
if(islockMachineTime) {
chromosome.getResult().add(result);
machine.setLastGene(result);
......@@ -1849,8 +1903,8 @@ public class GeneticDecoder {
// 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间
GAScheduleResult result = CreateResult(operation, machine.getId(), startTime, endTime, processingTime, setupTime, preTime, teardownTime, bomtime, geneDetails, existingResult);
result.setCapacityTypeName(machine.getCapacityTypeName());
GAScheduleResult result = CreateResult(operation, machine.getId(), startTime, endTime, processingTime, setupTime, preTime, teardownTime, bomtime, geneDetails, existingResult,machine.getCapacityTypeName(),isJit);
// System.out.println("huanxingshijian="+result.getChangeOverTime()+"-------------------"+result.getOrderId()+"--------"+result.getExecId()+"---------"+prev.getOrderId()+"--------"+prev.getExecId());
if (islockMachineTime)
......@@ -2073,12 +2127,13 @@ public class GeneticDecoder {
private GAScheduleResult CreateResult(Entry operation,long machineId
,int startTime,int endTime,double processingTime
,int setupTime,int preTime,int teardownTime,int bomtime
,CopyOnWriteArrayList<ScheduleResultDetail> geneDetails,GAScheduleResult existingResult )
,CopyOnWriteArrayList<ScheduleResultDetail> geneDetails,GAScheduleResult existingResult,String capacityTypeName,boolean isJit )
{
GAScheduleResult result=new GAScheduleResult();
result.setGroupId(operation.getGroupId());
result.setOperationId(operation.getId());
result.setIsJit(isJit);
result.setExecId(operation.getExecId());
result.setOrderId(operation.getOrderId());
result.setOrderCode(operation.getOrderCode());
......@@ -2089,6 +2144,7 @@ public class GeneticDecoder {
? null
: new ArrayList<>(operation.getTargetFinishedOperationId()));
result.setMachineId(machineId);
result.setCapacityTypeName(capacityTypeName);
result.setStartTime(startTime);
result.setEndTime(endTime);
result.setOneTime(processingTime);
......@@ -3681,8 +3737,8 @@ if(geneDetails!=null&&geneDetails.size()>0)
if (scheduledCount == 0) {
continue;
}
List<Integer> removeOp= clearOrderSchedulingForForwardFallback(chromosome, finishedId,
machineTasksCache, scheduleIndexById);
List<Integer> removeOp = clearOrderSchedulingForForwardFallback(chromosome, finishedId,
machineTasksCache, scheduleIndexById,entryIndexById,null);
int forwardEndTime1 = scheduleOrderForwardFallback(finishedId,removeOp,forwardEndTime,
chromosome,entrysBygroupId, machineIdMap, machineTasksCache,
......@@ -3700,4 +3756,105 @@ if(geneDetails!=null&&geneDetails.size()>0)
reForwardFinishedOrderIds.clear();
}
/**
* 物料扣减记录:区分库存扣减(useStock)和在途扣减(useTransit)
*/
private static class MaterialDeduction {
double useStock; // 占用库存(回滚时还原到 materialStocks)
double useTransit; // 占用在途(回滚时还原到 InTransit)
}
// 读工序扣减的库存记录:materialId → 扣减明细(含库存 + 在途 + 替换料)
private Map<String, MaterialDeduction> readOperationStockDeductions(Entry op) {
Map<String, MaterialDeduction> result = new HashMap<>();
List<OrderMaterialRequirement> requirements = op.getMaterialRequirements();
if (requirements != null) {
for (OrderMaterialRequirement req : requirements) {
// 替换料
double replaceStock=0;
double replaceTransit=0;
List<OrderMaterialRequirement> replaceMaterials = req.getReplaceMaterial();
if (replaceMaterials != null) {
for (OrderMaterialRequirement rep : replaceMaterials) {
replaceStock+=rep.getUseStock();
replaceTransit+=rep.getUseTransit();
mergeRequirementIntoDeduction(result, rep,0,0);
}
}
mergeRequirementIntoDeduction(result, req,replaceStock,replaceTransit);
}
}
return result;
}
private void mergeRequirementIntoDeduction(Map<String, MaterialDeduction> map,
OrderMaterialRequirement req,double replaceStock,double replaceTransit) {
double useStock = req.getUseStock()-replaceStock;
double useTransit = req.getUseTransit()-replaceTransit;
if (useStock <= 0 && useTransit <= 0) return;
MaterialDeduction ded = map.computeIfAbsent(req.getMaterialId(),
k -> new MaterialDeduction());
ded.useStock += useStock;
ded.useTransit += useTransit;
}
// 回滚已扣库存(含库存 + 在途)
private void rollbackOperationStockDeduction(Chromosome chromosome,
Map<String, MaterialDeduction> deductions) {
TreeMap<String, Material> materials = chromosome.getMaterials();
for (Map.Entry<String, MaterialDeduction> entry : deductions.entrySet()) {
String materialId = entry.getKey();
MaterialDeduction deduction = entry.getValue();
Material material = materials.get(materialId);
if (material == null) continue;
// 回滚库存:还原 materialStocks.usedInventory
if (deduction.useStock > 0) {
List<Stock> stocks = material.getMaterialStocks().stream()
.filter(t -> t.getUsedInventory() > 0)
.collect(Collectors.toList());
double remaining = deduction.useStock;
for (Stock s : stocks) {
double rollback1 = Math.min(remaining, s.getUsedInventory());
s.setUsedInventory(s.getUsedInventory() - rollback1);
remaining -= rollback1;
if (remaining <= 0) break;
}
if (remaining > 0) {
FileHelper.writeLogFile("[StockRollback] 物料" + material.getCode()
+ " 库存回滚不足,剩余=" + remaining);
}
}
// 回滚在途:还原 InTransit(MaterialSupply).Quantity
if (deduction.useTransit > 0) {
List<MaterialSupply> inTransit = material.getInTransit();
if (inTransit != null && !inTransit.isEmpty()) {
// 按到货时间顺序回滚(先到先回滚)
List<MaterialSupply> sorted = inTransit.stream()
.sorted(Comparator.comparing(MaterialSupply::getArrivalTime,
Comparator.nullsLast(Comparator.naturalOrder())))
.collect(Collectors.toList());
double remaining = deduction.useTransit;
for (MaterialSupply supply : sorted) {
double rollback1 = remaining;
supply.setQuantity(supply.getQuantity() + rollback1);
remaining -= rollback1;
if (remaining <= 0) break;
}
if (remaining > 0) {
FileHelper.writeLogFile("[StockRollback] 物料" + material.getCode()
+ " 在途回滚不足,剩余=" + remaining);
}
} else {
FileHelper.writeLogFile("[StockRollback] 物料" + material.getCode()
+ " 在途列表为空,无法回滚 useTransit=" + deduction.useTransit);
}
}
}
}
}
......@@ -190,7 +190,7 @@ public class PlanResultService {
try {
ScheduleParams param = InitScheduleParams();
// param.setBaseTime(LocalDateTime.of(2026, 5, 20, 0, 0, 0));
param.setBaseTime(LocalDateTime.of(2026, 5, 20, 0, 0, 0));
this.baseTime=param.getBaseTime();
// 策略读取入口:优先使用前端传入的 userId;没传时用 sceneId 查场景创建人。
Long effectiveUserId = scheduleStrategyService.resolveScheduleUserId(SceneId, userId);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment