Commit d1745f27 authored by Tong Li's avatar Tong Li

MP

parent ea3cc142
......@@ -33,6 +33,8 @@ public class Material {
*/
private double CurrentStock;
private Long categoryId=1l;
/**
* 库存详情
*/
......
......@@ -4,6 +4,8 @@ import com.aps.ApsApplication;
import com.aps.macroplanner.data.DataValidator;
import com.aps.macroplanner.data.MacroPlannerDataConverter;
import com.aps.macroplanner.data.TestDataBuilder;
import com.aps.macroplanner.output.ResultWriter;
import com.aps.macroplanner.output.dto.OptimizationResult;
import com.google.ortools.Loader;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
......@@ -77,6 +79,10 @@ public class MacroPlannerDataConverterRunner {
optimizer.buildModel();
optimizer.solve();
ResultWriter writer = new ResultWriter(optimizer.getModel(), optimizer.getData(), 1);
OptimizationResult result = writer.buildResult("Default");
boolean jsonPath = writer.saveResultToFile("Default", result);
System.out.println("===== MACROPLANNER DATA CONVERTER RUNNER END =====");
} finally {
SpringApplication.exit(ctx);
......
......@@ -56,38 +56,41 @@ public class MultiLevelBomTestRunner {
// 通过 Spring 容器获取 service 实例 (static main 中 @Autowired 不会生效)
ApplicationContext ctx = SpringApplication.run(ApsApplication.class, args);
try {
// MultiLevelBomTestDataBuilder data=new MultiLevelBomTestDataBuilder();
// data.init();
//
// MacroPlannerOptimizer optimizer = new MacroPlannerOptimizer(data);
// optimizer.buildModel();
// optimizer.solve("bom");
MpPispipResultPersistenceService service =
ctx.getBean(MpPispipResultPersistenceService.class);
int scale = 100;
BenchmarkDataBuilder data = BenchmarkDataBuilder.forScale(scale);
writeLog("===== TEST RUNNER START " + scale + "=====");
long startTime = System.currentTimeMillis();
MultiLevelBomTestDataBuilder data=new MultiLevelBomTestDataBuilder();
data.init();
writeLog("Data loaded: " + data.getProducts().size() + " products, "
+ data.getOperations().size() + " operations");
long startTime = System.currentTimeMillis();
MacroPlannerOptimizer optimizer = new MacroPlannerOptimizer(data);
optimizer.buildModel();
optimizer.solve(String.valueOf(scale));
// 构建结果并调用 save 入库
optimizer.solve("bom");
ResultWriter writer = new ResultWriter(optimizer.getModel(), optimizer.getData(), startTime);
OptimizationResult result = writer.buildResult(String.valueOf(scale));
boolean jsonPath = writer.saveResultToFile(String.valueOf(scale), result);
OptimizationResult result = writer.buildResult("bom");
boolean jsonPath = writer.saveResultToFile("bom", result);
writeLog("PISPIP result saved: ");
int saved = service.save(String.valueOf(scale), result);
writeLog("PISPIP result saved: " + saved);
// MpPispipResultPersistenceService service =
// ctx.getBean(MpPispipResultPersistenceService.class);
//
// int scale = 2000;
// BenchmarkDataBuilder data = BenchmarkDataBuilder.forScale(scale);
// writeLog("===== TEST RUNNER START " + scale + "=====");
//
// data.init();
// writeLog("Data loaded: " + data.getProducts().size() + " products, "
// + data.getOperations().size() + " operations");
//
// long startTime = System.currentTimeMillis();
// MacroPlannerOptimizer optimizer = new MacroPlannerOptimizer(data);
// optimizer.buildModel();
// optimizer.solve(String.valueOf(scale));
//
// // 构建结果并调用 save 入库
// ResultWriter writer = new ResultWriter(optimizer.getModel(), optimizer.getData(), startTime);
// OptimizationResult result = writer.buildResult(String.valueOf(scale));
// boolean jsonPath = writer.saveResultToFile(String.valueOf(scale), result);
//
// writeLog("PISPIP result saved: ");
// int saved = service.save(String.valueOf(scale), result);
// writeLog("PISPIP result saved: " + saved);
writeLog("===== TEST RUNNER END =====");
} catch (Exception e) {
......
......@@ -24,6 +24,7 @@ import com.aps.mapper.StockMapper;
import com.aps.service.ApsTimeConfigService;
import com.aps.service.LanuchService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -47,6 +48,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
......@@ -429,7 +431,7 @@ public class MacroPlannerDataConverter {
material.setName(m.getName());
material.setMaxProduction(m.getMaxProduction());
material.setMinProduction(m.getMinProduction());
material.setCategoryId(m.getCategoryId());
// 库存
List<Stock> materialStocks = stocksByMaterialId.getOrDefault(m.getId(), Collections.emptyList());
if (!materialStocks.isEmpty()) {
......@@ -700,6 +702,7 @@ public class MacroPlannerDataConverter {
for (Material m : ctx.materialByMaterialId.values()) {
String name = pickName(m.getName(), m.getCode(), m.getId());
Product p = new Product(m.getCode(), name, m.getCode());
p.setCategoryId(m.getCategoryId());
products.add(p);
ctx.productByMaterialId.put(m.getId(), p);
}
......@@ -842,6 +845,10 @@ public class MacroPlannerDataConverter {
int hid = rd.getRoutingHeaderId().intValue();
detailsByHeader.computeIfAbsent(hid, k -> new ArrayList<>()).add(rd);
}
Map<Integer, PlanResource> prMap = ctx.planResources.stream()
.collect(Collectors.toMap(PlanResource::getId, Function.identity()));
Map<Integer, Equipinfo> equipMap = ctx.equipinfos.stream()
.collect(Collectors.toMap(Equipinfo::getId, Function.identity()));
detailsByHeader.values().forEach(list ->
list.sort(Comparator.comparing(rd ->
rd.getTaskSeq() == null ? Long.MAX_VALUE : rd.getTaskSeq())));
......@@ -887,13 +894,23 @@ public class MacroPlannerDataConverter {
unitOps = equips.stream()
.filter(e -> e.getEquipId() != null)
.map(e -> {
PlanResource res= prMap.get(e.getEquipId().intValue());
Integer shopid=0;
if(res!=null)
{
Equipinfo equip = equipMap.get(res.getReferenceId());
if(equip!=null) {
shopid=equip.getShopId();
}
}
String unitId = "EQUIP_" + e.getEquipId();
String unitName = e.getName();
double capCoeff = (e.getDuration() != null) ? e.getDuration().doubleValue()/3600/e.getOutputQuantity().doubleValue() : 1.0;
boolean lotSize = e.getOneBatchQuantity() != null
&& e.getOneBatchQuantity().compareTo(BigDecimal.ZERO) > 0;
double lotSizeVal = lotSize ? e.getOneBatchQuantity().doubleValue() : 0.0;
return new UnitOperation(unitId,unitName, capCoeff, lotSize, lotSizeVal, 1.0);
return new UnitOperation(unitId,unitName, capCoeff, lotSize, lotSizeVal, 1.0,shopid);
})
.collect(Collectors.toList());
} else {
......@@ -902,7 +919,7 @@ public class MacroPlannerDataConverter {
String unitName = (rd.getEquipTypeId() != null ? rd.getEquipType() : "DEFAULT");
double capCoeff = (rd.getRuntime() != null) ? rd.getRuntime().doubleValue() : 1.0;
unitOps = Arrays.asList(new UnitOperation(unitId,unitName, capCoeff, false, 0.0, 1.0));
unitOps = Arrays.asList(new UnitOperation(unitId,unitName, capCoeff, false, 0.0, 1.0,0));
}
Operation op = new Operation(
......@@ -1014,7 +1031,7 @@ public class MacroPlannerDataConverter {
"采购-" + pickName(m.getName(), m.getId())
+ (mp.getSupplyName() != null ? "-" + mp.getSupplyName() : ""),
Collections.singletonList(
new UnitOperation(unitId,unitName, 0.5, false, 0.0, 1.0)),
new UnitOperation(unitId,unitName, 0.5, false, 0.0, 1.0,0)),
new OperationOutput(p, sp),
1.0, leadTimeDays);
operations.add(procureOp);
......@@ -1029,7 +1046,7 @@ public class MacroPlannerDataConverter {
"OP_PROCURE_" + m.getId(),
"采购-" + pickName(m.getName(), m.getId()),
Collections.singletonList(
new UnitOperation(unitId,"通用供应商", 0.5, false, 0.0, 1.0)),
new UnitOperation(unitId,"通用供应商", 0.5, false, 0.0, 1.0,0)),
new OperationOutput(p, sp),
1.0, 0);
operations.add(procureOp);
......@@ -1143,9 +1160,12 @@ public class MacroPlannerDataConverter {
// 收集所有 unitId (遍历每个 Operation 的每个 UnitOperation)
Map<String,String> unitIds = new HashMap<>() ;
Map<String,Integer> unitShipIds = new HashMap<>() ;
for (Operation op : operations) {
for (UnitOperation uo : op.getUnitOperations()) {
unitIds.put(uo.getUnitId(),uo.getUnitName());
unitShipIds.put(uo.getUnitId(),uo.getShopId());
}
}
......@@ -1187,7 +1207,9 @@ public class MacroPlannerDataConverter {
int workDays = calculateWorkDays(periodStart, periodEnd);
periodMaxCapacity = DEFAULT_DAILY_HOURS * Math.max(1, workDays);
}
unitPeriods.add(new UnitPeriod(unitId,unitName, p, 0.0, periodMaxCapacity, false));
Integer shopid= unitShipIds.get(unitId);
unitPeriods.add(new UnitPeriod(unitId,unitName, p, 0.0,
periodMaxCapacity, false,shopid));
}
}
log.info("构建 Period: {} (dimension={}, horizonEnd={}), UnitPeriod: {}",
......@@ -1288,7 +1310,7 @@ public class MacroPlannerDataConverter {
} else {
// 无时间信息, 放入最后一个周期
salesDemands.add(new SalesDemand(p, sp, lastPeriod, qty, priority,
ado.getId(), ado.getCode(), pickName(ado.getMmcode(), p.getId()),ado.getEndtime()==null?ado.getDeliverytime().toLocalDate():ado.getEndtime().toLocalDate()));
ado.getId(), ado.getCode(), pickName(ado.getMmcode(), p.getId()),ado.getEndtime()==null?ado.getDeliverytime().toLocalDate():ado.getEndtime().toLocalDate(),p.getCategoryId()));
continue;
}
......@@ -1310,7 +1332,7 @@ public class MacroPlannerDataConverter {
if (overlapPeriods.isEmpty()) {
salesDemands.add(new SalesDemand(p, sp, lastPeriod, qty, priority,
ado.getId(), ado.getCode(), pickName(ado.getMmcode(), p.getId()),ado.getEndtime()==null?ado.getDeliverytime().toLocalDate():ado.getEndtime().toLocalDate()));
ado.getId(), ado.getCode(), pickName(ado.getMmcode(), p.getId()),ado.getEndtime()==null?ado.getDeliverytime().toLocalDate():ado.getEndtime().toLocalDate(),p.getCategoryId()));
} else {
// 按重叠天数比例拆分需求量: 每期四舍五入取整, 最后一期补差保证总和等于总数
int totalQty = (int) Math.round(qty);
......@@ -1327,7 +1349,7 @@ public class MacroPlannerDataConverter {
allocated += periodQty;
}
salesDemands.add(new SalesDemand(p, sp, per, periodQty, priority,
ado.getId(), ado.getCode(), pickName(ado.getMmcode(), p.getId()),ado.getEndtime()==null?ado.getDeliverytime().toLocalDate():ado.getEndtime().toLocalDate()));
ado.getId(), ado.getCode(), pickName(ado.getMmcode(), p.getId()),ado.getEndtime()==null?ado.getDeliverytime().toLocalDate():ado.getEndtime().toLocalDate(),p.getCategoryId()));
}
}
}
......
......@@ -47,10 +47,14 @@ public class MultiLevelBomTestDataBuilder extends TestDataBuilder {
// === 产品: 成品 P1, P2 + 半成品 S1 + 原材料 R1, R2 ===
Product prodP1 = new Product("P1", "成品P1");
prodP1.setCategoryId(1l);
// Product prodP2 = new Product("P2", "成品P2");
Product prodS1 = new Product("S1", "半成品S1");
prodS1.setCategoryId(12l);
Product prodR1 = new Product("R1", "原材料R1");
prodR1.setCategoryId(3l);
Product prodR2 = new Product("R2", "原材料R2");
prodR2.setCategoryId(4l);
products.addAll(Arrays.asList(prodP1, prodS1, prodR1, prodR2));
// === 库存点: 每种产品一个库存点 ===
......@@ -117,7 +121,7 @@ public class MultiLevelBomTestDataBuilder extends TestDataBuilder {
// === 初始库存: 全部从 0 开始 ===
initialInventories.add(new InitialInventory(prodP1, spP1, 0.0));
// initialInventories.add(new InitialInventory(prodP2, spP2, 0.0));
initialInventories.add(new InitialInventory(prodS1, spSemi, 0.0));
initialInventories.add(new InitialInventory(prodS1, spSemi, 40.0));
initialInventories.add(new InitialInventory(prodR1, spR1, 0.0));
initialInventories.add(new InitialInventory(prodR2, spR2, 0.0));
......
......@@ -69,7 +69,7 @@ public class Operation {
boolean hasLotSize, double lotSize, double qtpfactor,
int leadTimeDays) {
this(id, name,
Arrays.asList(new UnitOperation(unitId,"", capacityCoeff, hasLotSize, lotSize, qtpfactor)),
Arrays.asList(new UnitOperation(unitId,"", capacityCoeff, hasLotSize, lotSize, qtpfactor,0)),
output, relativeDuration, leadTimeDays);
}
......
......@@ -18,9 +18,16 @@ public class OperationOutput {
private final Product product; // 产出产品
private final StockingPoint stockingPoint; // 产出到哪个库存点
public final double factor;
public OperationOutput(Product product, StockingPoint stockingPoint) {
this(product,stockingPoint,1);
}
public OperationOutput(Product product, StockingPoint stockingPoint,double factor) {
this.product = product;
this.stockingPoint = stockingPoint;
this.factor=factor;
}
public Product getProduct() { return product; }
......@@ -28,9 +35,14 @@ public class OperationOutput {
/** 便捷方法: 产品 ID */
public String getProductId() { return product.getId(); }
public String getProductCode() { return product.getCode(); }
/** 便捷方法: 库存点 ID */
public String getSpId() { return stockingPoint.getId(); }
public String getSpName() { return stockingPoint.getName(); }
@Override
public String toString() {
return product.getId() + "@" + stockingPoint.getId();
......
......@@ -8,6 +8,8 @@ public class Product {
private final String name;
private final String code;
private Long categoryId;
public Product(String id, String name) {
this(id, name, id);
}
......@@ -22,6 +24,10 @@ public class Product {
public String getName() { return name; }
public String getCode() { return code; }
public Long getCategoryId() { return categoryId; }
public void setCategoryId(Long val) { categoryId=val; }
@Override
public String toString() {
return name + "1(" + id + ")";
......
......@@ -18,6 +18,8 @@ public class SalesDemand {
private final LocalDate demandOrderDate;
private final Long categoryId;
public SalesDemand(Product product, StockingPoint stockingPoint, Period period,
double quantity, double priority) {
this(product, stockingPoint, period, quantity, priority, null,null);
......@@ -25,12 +27,13 @@ public class SalesDemand {
public SalesDemand(Product product, StockingPoint stockingPoint, Period period,
double quantity, double priority, String demandOrderId,LocalDate demandOrderDate) {
this(product, stockingPoint, period, quantity, priority, demandOrderId, null, null,demandOrderDate);
this(product, stockingPoint, period, quantity, priority, demandOrderId, null, null,demandOrderDate,0l);
}
public SalesDemand(Product product, StockingPoint stockingPoint, Period period,
double quantity, double priority, String demandOrderId,
String orderCode, String productCode,LocalDate demandOrderDate) {
String orderCode, String productCode,LocalDate demandOrderDate,Long categoryId) {
this.product = product;
this.stockingPoint = stockingPoint;
this.period = period;
......@@ -40,6 +43,7 @@ public class SalesDemand {
this.orderCode = orderCode;
this.productCode = productCode;
this.demandOrderDate=demandOrderDate;
this.categoryId= categoryId;
}
public Product getProduct() { return product; }
......@@ -50,7 +54,7 @@ public class SalesDemand {
public String getDemandOrderId() { return demandOrderId; }
public String getOrderCode() { return orderCode; }
public String getProductCode() { return productCode; }
public Long getCategoryId() { return categoryId; }
public LocalDate getDemandOrderDate() { return demandOrderDate; }
public String getKey() {
......
......@@ -17,14 +17,21 @@ public class UnitOperation {
private final double lotSize; // 批次大小
private final double qtpfactor; // QuantityToProcessFactor
private final Integer shopId;
public UnitOperation(String unitId,String unitName, double capacityCoeff,
boolean hasLotSize, double lotSize, double qtpfactor) {
this( unitId, unitName, capacityCoeff,
hasLotSize, lotSize, qtpfactor,0);
}
public UnitOperation(String unitId,String unitName, double capacityCoeff,
boolean hasLotSize, double lotSize, double qtpfactor, Integer shopId) {
this.unitId = unitId;
this.unitName=unitName;
this.capacityCoeff = capacityCoeff;
this.hasLotSize = hasLotSize;
this.lotSize = lotSize;
this.qtpfactor = qtpfactor;
this.shopId=shopId;
}
public String getUnitId() { return unitId; }
......@@ -35,6 +42,8 @@ public class UnitOperation {
public double getLotSize() { return lotSize; }
public double getQtpfactor() { return qtpfactor; }
public Integer getShopId() { return shopId; }
@Override
public String toString() {
return unitId + "(产能" + capacityCoeff + "h/件" +
......
......@@ -15,9 +15,11 @@ public class UnitPeriod {
private final boolean hasMinCapacity; // 是否有最小产能约束
private final boolean unlimited; // 产能是否无上限 (如原材料供应商)
private final Integer shopId;
/** 完整构造器 */
public UnitPeriod(String unitId,String unitName, Period period, double minCapacity, double maxCapacity,
boolean hasMinCapacity, boolean unlimited) {
boolean hasMinCapacity, boolean unlimited,Integer shopId) {
this.unitId = unitId;
this.unitName=unitName;
this.period = period;
......@@ -25,16 +27,19 @@ public class UnitPeriod {
this.maxCapacity = unlimited ? Double.MAX_VALUE : maxCapacity;
this.hasMinCapacity = hasMinCapacity;
this.unlimited = unlimited;
this.shopId=shopId;
}
/** 有限产能构造器 (向后兼容) */
public UnitPeriod(String unitId,String unitName, Period period, double minCapacity, double maxCapacity, boolean hasMinCapacity) {
this(unitId,unitName, period, minCapacity, maxCapacity, hasMinCapacity, false);
this(unitId,unitName, period, minCapacity, maxCapacity, hasMinCapacity, false,0);
}
/** 有限产能构造器 (向后兼容) */
public UnitPeriod(String unitId,String unitName, Period period, double minCapacity, double maxCapacity, boolean hasMinCapacity,Integer shopId) {
this(unitId,unitName, period, minCapacity, maxCapacity, hasMinCapacity, false,shopId);
}
/** 无限产能便捷构造器 */
public static UnitPeriod unlimited(String unitId,String unitName, Period period) {
return new UnitPeriod(unitId,unitName, period, 0, 0, false, true);
return new UnitPeriod(unitId,unitName, period, 0, 0, false, true,0);
}
public String getUnitId() { return unitId; }
......@@ -47,6 +52,8 @@ public class UnitPeriod {
public boolean hasMinCapacity() { return hasMinCapacity; }
public boolean isUnlimited() { return unlimited; }
public Integer getShopId() { return shopId; }
public String getKey() {
return unitId + "_" + period.getIndex();
}
......
......@@ -27,9 +27,17 @@ public class OptimizationResult {
// ==================== 业务结果 ====================
private final List<PeriodTaskResult> periodTasks = new ArrayList<>();
private final List<PeriodTaskResult.OutputInfo> periodTaskOutputs = new ArrayList<>();
private final List<SalesDemandResult> salesDemands = new ArrayList<>();
private List<SalesDemandResult> saleDemandSummaries = new ArrayList<>();
private final List<PispipResult> pispips = new ArrayList<>();
private final List<PispipResult.PispipSummarieResult> pispipSummaries = new ArrayList<>();
// ==================== 产品生产网络 ====================
private ProductNetworkResult productNetwork;
......@@ -38,6 +46,8 @@ public class OptimizationResult {
private List<UnitCapacityResult> unitCapacities;
private List<UnitCapacityResult.UnitPeriodDetail> unitPeriodDetails;
// ==================== 需求满足汇总 ====================
private List<DemandSummaryResult> demandSummary;
......@@ -59,15 +69,30 @@ public class OptimizationResult {
public void setVersion(String v) { this.version = v; }
public List<PeriodTaskResult> getPeriodTasks() { return periodTasks; }
public List<PeriodTaskResult.OutputInfo> getPeriodTaskOutputs() { return periodTaskOutputs; }
public List<SalesDemandResult> getSalesDemands() { return salesDemands; }
public List<SalesDemandResult> getSaleSummarieDemands() { return saleDemandSummaries; }
public void setSaleSummarieDemands(List<SalesDemandResult> v) { saleDemandSummaries=v; }
public List<PispipResult> getPispips() { return pispips; }
public List<PispipResult.PispipSummarieResult> getPispipSummaries() { return pispipSummaries; }
public ProductNetworkResult getProductNetwork() { return productNetwork; }
public void setProductNetwork(ProductNetworkResult v) { this.productNetwork = v; }
public List<UnitCapacityResult> getUnitCapacities() { return unitCapacities; }
public List<UnitCapacityResult.UnitPeriodDetail> getUnitPeriodDetails() { return unitPeriodDetails; }
public void setUnitCapacities(List<UnitCapacityResult> v) { this.unitCapacities = v; }
public void setUnitPeriodDetails(List<UnitCapacityResult.UnitPeriodDetail> v) { this.unitPeriodDetails = v; }
public List<DemandSummaryResult> getDemandSummary() { return demandSummary; }
public void setDemandSummary(List<DemandSummaryResult> v) { this.demandSummary = v; }
......
......@@ -17,6 +17,7 @@ public class PeriodTaskResult {
private String operationId;
private String operationName;
private String unitId;
private String unitName;
private int periodIndex;
private String periodStartDate;
......@@ -40,11 +41,21 @@ public class PeriodTaskResult {
// ==================== 内嵌类 ====================
/** 产出信息 */
// public static class OutputInfo {
// public String productId;
// public String spId;
// public double factor;
// }
@Data
public static class OutputInfo {
public String productId;
public String productCode;
public String spId;
public String spName;
public double factor;
private String dataKey;
private int periodIndex;
private String periodStartDate;
/** PTQty — 生产量 */
private double productionQty;
}
}
\ No newline at end of file
......@@ -16,7 +16,7 @@ public class PispipResult {
private String productId;
private String productCode;
private String spId;
private Long categoryId;
private String spName;
private int periodIndex;
private String periodStartDate;
......@@ -83,6 +83,36 @@ public class PispipResult {
/** 每个工序的产出明细 */
private final List<ProductionDetail> productionDetails = new ArrayList<>();
public static class PispipSummarieResult {
private String key;
private String productId;
private String productCode;
private String spId;
private String spName;
private Long categoryId;
public String getKey() { return key; }
public void setKey(String v) { this.key = v; }
public String getProductId() { return productId; }
public void setProductId(String v) { this.productId = v; }
public String getProductCode() { return productCode; }
public void setProductCode(String v) { this.productCode = v; }
public String getSpId() { return spId; }
public void setSpId(String v) { this.spId = v; }
public String getSpName() { return spName; }
public void setSpName(String v) { this.spName = v; }
public Long getCategoryId() { return categoryId; }
public void setCategoryId(Long v) { this.categoryId = v; }
}
// ==================== 内嵌类 ====================
/** 工序产出明细 */
......
package com.aps.macroplanner.output.dto;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
......@@ -8,6 +10,7 @@ import java.util.List;
*
* <p>每个销售需求在每个周期的满足量、缺口、优先级等。</p>
*/
@Data
public class SalesDemandResult {
private String salesDemandId;
......@@ -33,6 +36,8 @@ public class SalesDemandResult {
/** 优先级 */
private double priority;
private Long categoryId;
/** 未完成原因分析 (仅当 unmetQty > 0 时有内容) */
private final List<String> unmetReasons = new ArrayList<>();
/** 风险分析 (即使满足也可能存在的供应链风险) */
......
......@@ -19,6 +19,9 @@ public class SupplyChainNode {
/** 产品 ID */
private String productId;
public String productCode;
/** 库存点 ID */
private String spId;
......@@ -148,6 +151,10 @@ public class SupplyChainNode {
public String getProductId() { return productId; }
public void setProductId(String v) { this.productId = v; }
public String getProductCode() { return productCode; }
public void setProductCode(String v) { this.productCode = v; }
public String getSpId() { return spId; }
public void setSpId(String v) { this.spId = v; }
......
package com.aps.macroplanner.output.dto;
import lombok.Data;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
......@@ -20,6 +22,7 @@ import java.util.Map;
* <tr><td>periodTasks</td><td>该设备的生产任务明细 (PeriodTaskResult[])</td></tr>
* </table>
*/
@Data
public class UnitCapacityResult {
/** 设备ID */
......@@ -27,6 +30,8 @@ public class UnitCapacityResult {
private String unitName;
private Integer shopId;
/** 使用该设备的工序ID列表 */
private List<String> operationIds;
/** 全部周期最大可用产能合计 */
......@@ -44,13 +49,19 @@ public class UnitCapacityResult {
private double overallUtilization;
/** 各周期明细 */
private final List<UnitPeriodDetail> periodDetails = new ArrayList<>();
// private final List<UnitPeriodDetail> periodDetails = new ArrayList<>();
// ==================== 内嵌类 ====================
/** 单周期产能明细 */
public static class UnitPeriodDetail {
/** 设备ID */
public String unitId;
public String unitName;
/** 周期索引 */
public int periodIndex;
/** 周期起始日期 */
......@@ -69,7 +80,7 @@ public class UnitCapacityResult {
public double production;
/** 该周期内在该设备上执行的工序明细 */
public final List<UnitTaskInfo> tasks = new ArrayList<>();
// public final List<UnitTaskInfo> tasks = new ArrayList<>();
}
/** 设备上的工序级生产明细 */
public static class UnitTaskInfo {
......@@ -107,7 +118,7 @@ public class UnitCapacityResult {
public double getTotalProduction() { return totalProduction; }
public void setTotalProduction(double v) { this.totalProduction = v; }
public List<UnitPeriodDetail> getPeriodDetails() { return periodDetails; }
//public List<UnitPeriodDetail> getPeriodDetails() { return periodDetails; }
public double getTotalOverloaded() { return totalOverloaded; }
public void setTotalOverloaded(double v) { this.totalOverloaded = v; }
......
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