kpi修改

parent c6774944
......@@ -1023,8 +1023,8 @@ public class MacroPlannerResultController {
Map<String, String> entryMap = new LinkedHashMap<>();
entryMap.put("name", e.name);
entryMap.put("rawValue", String.format("%.2f", e.rawValue));
entryMap.put("weight", String.format("%.1f", e.weight));
entryMap.put("penalty", String.format("%.2f", e.penalty));
entryMap.put("weight", e.weight == null ? null : String.format("%.1f", e.weight));
entryMap.put("penalty", e.penalty == null ? null : String.format("%.2f", e.penalty));
kpiList.add(entryMap);
}
kpiData.put("entries", kpiList);
......
......@@ -260,7 +260,6 @@ public class MacroPlannerDataConverter {
ctx.horizonEnd = calculateHorizonEnd(ctx.periodDimension, baseDate, periodCount);
LocalDateTime horizonEndDateTime = ctx.horizonEnd.atStartOfDay();
log.info("排产周期: dimension={}, periodCount={}, baseTime={}, horizonEnd={}",
ctx.periodDimension, periodCount, ctx.baseTime, ctx.horizonEnd);log.info("排产周期: dimension={}, periodCount={}, baseTime={}, horizonEnd={}",
ctx.periodDimension, periodCount, ctx.baseTime, ctx.horizonEnd);
// 1. 需求订单 (ApsDemandOrder, 按 deliverytime 时间范围过滤)
......
......@@ -4,6 +4,7 @@ import com.aps.common.util.FileHelper;
import com.aps.common.util.FlatParquetUtil;
import com.aps.macroplanner.data.*;
import com.aps.macroplanner.model.MacroPlannerModel;
import com.aps.macroplanner.objective.KpiLib;
import com.aps.macroplanner.output.dto.*;
import com.aps.service.plan.SceneService;
import com.fasterxml.jackson.databind.DeserializationFeature;
......@@ -230,6 +231,12 @@ public class ResultWriter {
// BOM 结构持久化 (供 getProductNetwork 按需组装)
writeLog("writeBomStructure");
writeBomStructure(sceneId);
// KPI 汇总通过 summary 接口从 JSON 读取,这里同步保存完整结果。
File jsonFile = getOptimizationFile(sceneId);
objectMapper.writeValue(jsonFile, result);
writeLog("writeOptimizationResultJson: " + jsonFile.getAbsolutePath());
// 工序×物料×周期消耗量持久化
// writeLog("writeOperationDemands");
// List<OperationDemandResult> opDemands = buildOperationDemandResults();
......@@ -535,7 +542,7 @@ public class ResultWriter {
// KPI + 统计
writeLog("Kpi");
// result.setKpis(buildKpis());
result.setKpis(buildKpis());
// result.setStatistics(buildStatistics());
return result;
......@@ -1486,49 +1493,24 @@ public class ResultWriter {
private KpiResult buildKpis() {
KpiResult kr = new KpiResult();
KPIWeights w = data.getKpiWeights();
double objValue = model.getSolver().objective().value();
kr.setObjectiveValue(objValue);
kr.addEntry("需求缺口(Fulfillment)",
model.getTotalFulfillment().solutionValue(),
w.getFulfillmentWeight(), false);
kr.addEntry("需求满足数(FulfilledDemands)",
countFulfilledDemands(), 0.0, true);
kr.addEntry("批次偏差(LotSize)",
model.getTotalLotSize().solutionValue(),
w.getLotSizeWeight(), false);
kr.addEntry("超库存(MaxInventory)",
model.getTotalMaxInventoryLevel().solutionValue(),
w.getMaxInventoryLevelWeight(), false);
kr.addEntry("欠库存(MinInventory)",
model.getTotalMinInventoryLevel().solutionValue(),
w.getMinInventoryLevelWeight(), false);
kr.addEntry("目标库存偏差(TargetInv)",
model.getTotalTargetInvLevel().solutionValue(),
w.getTargetInventoryLevelWeight(), false);
kr.addEntry("产能超载(UnitCapacity)",
model.getTotalUnitCapacity().solutionValue(),
w.getUnitCapacityWeight(), false);
kr.addEntry("供应目标偏差(SupplyTarget)",
model.getTotalSupplyTarget().solutionValue(),
w.getSupplyTargetWeight(), false);
kr.addEntry("最小供应不足(MinSupply)",
model.getTotalMinSupply().solutionValue(),
w.getMinSupplyWeight(), false);
kr.addEntry("最大供应超出(MaxSupply)",
model.getTotalMaxSupply().solutionValue(),
w.getMaxSupplyWeight(), false);
kr.addEntry("销售优先级(SalesPriority)",
model.getTotalSalesDemandPriority().solutionValue(),
w.getSalesDemandPriorityWeight(), true);
kr.addEntry("推迟惩罚(Postponement)",
model.getTotalPostponementPenalty().solutionValue(),
w.getPostponementPenaltyWeight(), false);
kr.addEntry("过程最大量(ProcessMax)",
model.getTotalProcessMaxQuantity().solutionValue(),
w.getProcessMaxQuantityWeight(), false);
for (KpiLib kpi : KpiLib.values()) {
kr.addEntry(kpi.getCn(),
model.getKpi(kpi.getEn()).solutionValue(),
null,
kpi == KpiLib.SalesDemandPriority);
}
// // 这几个指标暂未纳入 KpiLib,保留原有结果字段,但不返回权重。
// kr.addEntry("需求满足数(FulfilledDemands)",
// countFulfilledDemands(), null, true);
// kr.addEntry("推迟惩罚(Postponement)",
// model.getTotalPostponementPenalty().solutionValue(), null, false);
// kr.addEntry("过程最大量(ProcessMax)",
// model.getTotalProcessMaxQuantity().solutionValue(), null, false);
return kr;
}
......@@ -1714,8 +1696,8 @@ public class ResultWriter {
jb.obj()
.key("name").val(e.name)
.key("rawValue").val(e.rawValue)
.key("weight").val(e.weight)
.key("penalty").val(e.penalty)
.key("weight").valOpt(e.weight)
.key("penalty").valOpt(e.penalty)
.key("isBenefit").val(e.isBenefit)
.endObj();
}
......
......@@ -22,10 +22,10 @@ public class KpiResult {
public String name;
/** KPI 原始值 (松弛量总和) */
public double rawValue;
/** 权重 */
public double weight;
/** 加权惩罚 = rawValue × weight */
public double penalty;
/** 权重;结果展示暂不提供权重时为 null */
public Double weight;
/** 加权惩罚;权重为空时为 null */
public Double penalty;
/** 是否为收益项 (越大越好, 正系数) */
public boolean isBenefit;
}
......@@ -37,13 +37,13 @@ public class KpiResult {
public List<KpiEntry> getEntries() { return entries; }
public void addEntry(String name, double rawValue, double weight, boolean isBenefit) {
public void addEntry(String name, double rawValue, Double weight, boolean isBenefit) {
KpiEntry e = new KpiEntry();
e.name = name;
e.rawValue = rawValue;
e.weight = weight;
e.isBenefit = isBenefit;
e.penalty = isBenefit ? -rawValue * weight : rawValue * weight;
e.penalty = weight == null ? null : (isBenefit ? -rawValue * weight : rawValue * weight);
entries.add(e);
}
}
\ No newline at end of file
}
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