策略优化

parent ecfe8236
...@@ -71,21 +71,43 @@ public class LanuchController { ...@@ -71,21 +71,43 @@ public class LanuchController {
*/ */
@PostMapping("/schedule") @PostMapping("/schedule")
@Operation(summary = "运算") @Operation(summary = "运算")
public R<String> schedule(@RequestBody Map<String, String> params) { public R<String> schedule(@RequestBody Map<String, Object> params) {
String sceneId = params.get("sceneId"); String sceneId = getStringParam(params, "sceneId");
if (sceneId == null || sceneId.trim().isEmpty()) { if (sceneId == null || sceneId.trim().isEmpty()) {
throw new IllegalArgumentException("场景ID不能为空"); throw new IllegalArgumentException("场景ID不能为空");
} }
// 如果需要处理时间字段,可以从params中获取并转换 // 如果需要处理时间字段,可以从params中获取并转换
// 例如:开始时间、结束时间等 // 例如:开始时间、结束时间等
String startTimeStr = params.get("startTime"); String startTimeStr = getStringParam(params, "startTime");
String endTimeStr = params.get("endTime"); String endTimeStr = getStringParam(params, "endTime");
// 在这里可以添加时间格式转换逻辑 // 在这里可以添加时间格式转换逻辑
// 根据不同格式解析时间字符串 // 根据不同格式解析时间字符串
Chromosome scheduleChromosomes = planResultService.execute2(sceneId); // 这些参数前端可以不传;不传时后端会根据 sceneId 找场景创建人,再查这个人的策略。
Long userId = getLongParam(params, "userId");
Long baseRuleId = getLongParam(params, "baseRuleId");
if (baseRuleId == null) {
baseRuleId = getLongParam(params, "referenceId");
}
String userRuleId = getStringParam(params, "userRuleId");
String id = getStringParam(params, "id");
if (id != null) {
int index = id.indexOf(":");
if (index > 0 && index < id.length() - 1) {
String source = id.substring(0, index);
String ruleId = id.substring(index + 1);
// 前端如果传的是组合 id:USER:用户策略ID 走用户策略;GLOBAL:基础策略ID 走全局策略。
if ("USER".equalsIgnoreCase(source) && userRuleId == null) {
userRuleId = ruleId;
} else if ("GLOBAL".equalsIgnoreCase(source) && baseRuleId == null) {
baseRuleId = parseLongParam("id", ruleId);
}
}
}
Chromosome scheduleChromosomes = planResultService.execute2(sceneId, userId, baseRuleId, userRuleId);
return R.ok("排产计算成功", "排产计算成功"); return R.ok("排产计算成功", "排产计算成功");
} }
...@@ -218,4 +240,28 @@ public class LanuchController { ...@@ -218,4 +240,28 @@ public class LanuchController {
return lanuchService.insertOrder(sceneId, orderCode, materialId, return lanuchService.insertOrder(sceneId, orderCode, materialId,
startDate, endDate, priority, quantity); startDate, endDate, priority, quantity);
} }
private String getStringParam(Map<String, ?> params, String key) {
if (params == null || params.get(key) == null) {
return null;
}
String value = String.valueOf(params.get(key)).trim();
return value.isEmpty() ? null : value;
}
private Long getLongParam(Map<String, ?> params, String key) {
String value = getStringParam(params, key);
return parseLongParam(key, value);
}
private Long parseLongParam(String key, String value) {
if (value == null || value.trim().isEmpty()) {
return null;
}
try {
return Long.valueOf(value.trim());
} catch (NumberFormatException e) {
throw new IllegalArgumentException(key + "必须是数字");
}
}
} }
...@@ -19,4 +19,6 @@ public interface UserStrategyRuleService extends IService<UserStrategyRule> { ...@@ -19,4 +19,6 @@ public interface UserStrategyRuleService extends IService<UserStrategyRule> {
List<Map<String, Object>> getStrategyOptions(Long userId); List<Map<String, Object>> getStrategyOptions(Long userId);
List<StrategyScheduling> getEffectiveForwardScheduling(Long userId, Long baseRuleId, String sceneId); List<StrategyScheduling> getEffectiveForwardScheduling(Long userId, Long baseRuleId, String sceneId);
List<StrategyScheduling> getEffectiveForwardScheduling(Long userId, Long baseRuleId, String sceneId, String userRuleId);
} }
...@@ -37,7 +37,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -37,7 +37,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
String source = getSource(params); String source = getSource(params);
String ruleId = getRuleId(params); String ruleId = getRuleId(params);
String userRuleId = "USER".equalsIgnoreCase(source) ? ruleId : getString(params, "userRuleId"); String userRuleId = "USER".equalsIgnoreCase(source) ? ruleId : getString(params, "userRuleId");
Long baseRuleId = "GLOBAL".equalsIgnoreCase(source) ? toLong(ruleId) : getLong(params, "baseRuleId"); Long baseRuleId = resolveBaseRuleId(params, source, ruleId);
UserStrategyRule selectedUserRule = findUserRuleById(userRuleId, userId); UserStrategyRule selectedUserRule = findUserRuleById(userRuleId, userId);
if (selectedUserRule != null) { if (selectedUserRule != null) {
...@@ -63,7 +63,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -63,7 +63,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
String source = getSource(params); String source = getSource(params);
String ruleId = getRuleId(params); String ruleId = getRuleId(params);
String userRuleId = "USER".equalsIgnoreCase(source) ? ruleId : getString(params, "userRuleId"); String userRuleId = "USER".equalsIgnoreCase(source) ? ruleId : getString(params, "userRuleId");
Long baseRuleId = "GLOBAL".equalsIgnoreCase(source) ? toLong(ruleId) : getLong(params, "baseRuleId"); Long baseRuleId = resolveBaseRuleId(params, source, ruleId);
UserStrategyRule userRule = null; UserStrategyRule userRule = null;
if (StringUtils.hasText(userRuleId)) { if (StringUtils.hasText(userRuleId)) {
...@@ -116,7 +116,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -116,7 +116,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
String source = getSource(params); String source = getSource(params);
String ruleId = getRuleId(params); String ruleId = getRuleId(params);
String userRuleId = "USER".equalsIgnoreCase(source) ? ruleId : getString(params, "userRuleId"); String userRuleId = "USER".equalsIgnoreCase(source) ? ruleId : getString(params, "userRuleId");
Long baseRuleId = "GLOBAL".equalsIgnoreCase(source) ? toLong(ruleId) : getLong(params, "baseRuleId"); Long baseRuleId = resolveBaseRuleId(params, source, ruleId);
UserStrategyRule userRule = null; UserStrategyRule userRule = null;
if (StringUtils.hasText(userRuleId)) { if (StringUtils.hasText(userRuleId)) {
...@@ -224,10 +224,23 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -224,10 +224,23 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
@Override @Override
public List<StrategyScheduling> getEffectiveForwardScheduling(Long userId, Long baseRuleId, String sceneId) { public List<StrategyScheduling> getEffectiveForwardScheduling(Long userId, Long baseRuleId, String sceneId) {
return getEffectiveForwardScheduling(userId, baseRuleId, sceneId, null);
}
@Override
public List<StrategyScheduling> getEffectiveForwardScheduling(Long userId, Long baseRuleId, String sceneId, String userRuleId) {
// 1. 如果 /lanuch/schedule 明确带了 userRuleId,就优先使用这条刚保存的用户策略。
UserStrategyRule selectedUserRule = findUserRuleByIdOptionalUser(userRuleId, userId);
if (selectedUserRule != null) {
return parseForwardScheduling(selectedUserRule.getForwardScheduling());
}
// 2. 没有明确 userRuleId 时,按 userId/baseRuleId 找当前用户可用的策略。
UserStrategyRule userRule = findUserRule(userId, baseRuleId); UserStrategyRule userRule = findUserRule(userId, baseRuleId);
if (userRule != null) { if (userRule != null) {
return parseForwardScheduling(userRule.getForwardScheduling()); return parseForwardScheduling(userRule.getForwardScheduling());
} }
// 3. 用户没有自定义策略时,回退到基础/全局策略,保证排产还能继续跑。
StrategyRule globalRule = findGlobalRule(baseRuleId); StrategyRule globalRule = findGlobalRule(baseRuleId);
return globalRule == null ? new ArrayList<StrategyScheduling>() : parseForwardScheduling(globalRule.getForwardScheduling()); return globalRule == null ? new ArrayList<StrategyScheduling>() : parseForwardScheduling(globalRule.getForwardScheduling());
} }
...@@ -238,6 +251,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -238,6 +251,7 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
return null; return null;
} }
// 同一个用户可能有多条策略:默认策略优先,其次取最近修改的一条。
rules.sort(Comparator rules.sort(Comparator
.comparing((UserStrategyRule rule) -> rule.getIsDefault() == null ? 0L : rule.getIsDefault(), Comparator.reverseOrder()) .comparing((UserStrategyRule rule) -> rule.getIsDefault() == null ? 0L : rule.getIsDefault(), Comparator.reverseOrder())
.thenComparing(rule -> rule.getLastmodificationtime() == null ? LocalDateTime.MIN : rule.getLastmodificationtime(), Comparator.reverseOrder())); .thenComparing(rule -> rule.getLastmodificationtime() == null ? LocalDateTime.MIN : rule.getLastmodificationtime(), Comparator.reverseOrder()));
...@@ -256,6 +270,22 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -256,6 +270,22 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
return rule; return rule;
} }
private UserStrategyRule findUserRuleByIdOptionalUser(String userRuleId, Long userId) {
if (!StringUtils.hasText(userRuleId)) {
return null;
}
UserStrategyRule rule = this.getById(userRuleId);
if (rule == null || isDeleted(rule.getIsdeleted())) {
return null;
}
// 如果能解析到 userId,则校验策略归属,避免误用其他用户的策略。
if (userId != null && !userId.equals(rule.getUserid())) {
return null;
}
return rule;
}
private List<UserStrategyRule> findUserRules(Long userId, Long baseRuleId) { private List<UserStrategyRule> findUserRules(Long userId, Long baseRuleId) {
if (userId == null) { if (userId == null) {
return null; return null;
...@@ -362,6 +392,15 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap ...@@ -362,6 +392,15 @@ public class UserStrategyRuleServiceImpl extends ServiceImpl<UserStrategyRuleMap
return toLong(String.valueOf(params.get(key))); return toLong(String.valueOf(params.get(key)));
} }
private Long resolveBaseRuleId(Map<String, Object> params, String source, String ruleId) {
if ("GLOBAL".equalsIgnoreCase(source)) {
return toLong(ruleId);
}
Long baseRuleId = getLong(params, "baseRuleId");
// 前端保存策略时传的是 referenceId,这里兼容成基础策略 ID。
return baseRuleId == null ? getLong(params, "referenceId") : baseRuleId;
}
private String getString(Map<String, Object> params, String key) { private String getString(Map<String, Object> params, String key) {
if (params == null || params.get(key) == null) { if (params == null || params.get(key) == null) {
return null; return null;
......
...@@ -115,7 +115,7 @@ public class PlanResultService { ...@@ -115,7 +115,7 @@ public class PlanResultService {
private RedisUtils redisUtils; private RedisUtils redisUtils;
@Autowired @Autowired
private StrategyRuleService _strategyRuleService; private ScheduleStrategyService scheduleStrategyService;
@Autowired @Autowired
private OrderSortService orderSortService; private OrderSortService orderSortService;
...@@ -166,12 +166,22 @@ public class PlanResultService { ...@@ -166,12 +166,22 @@ public class PlanResultService {
// 兼容旧调用:前端只传 sceneId 时,仍然会在内部根据场景创建人查找用户策略。
public Chromosome execute2(String SceneId) { public Chromosome execute2(String SceneId) {
return execute2(SceneId, null, null, null);
}
public Chromosome execute2(String SceneId, Long userId, Long baseRuleId, String userRuleId) {
try { try {
ScheduleParams param = InitScheduleParams(); ScheduleParams param = InitScheduleParams();
this.baseTime=param.getBaseTime(); this.baseTime=param.getBaseTime();
// 策略读取入口:优先使用前端传入的 userId;没传时用 sceneId 查场景创建人。
Long effectiveUserId = scheduleStrategyService.resolveScheduleUserId(SceneId, userId);
// 读取 /userStrategyRule/save 保存的用户策略;没有用户策略时会兜底全局策略。
List<StrategyScheduling> strategySchedulings =
scheduleStrategyService.loadEffectiveForwardScheduling(effectiveUserId, baseRuleId, SceneId, userRuleId);
// 1. 读取数据 // 1. 读取数据
// List<Machine> machines = loadData("machines.json", Machine.class); // List<Machine> machines = loadData("machines.json", Machine.class);
...@@ -195,7 +205,7 @@ public class PlanResultService { ...@@ -195,7 +205,7 @@ public class PlanResultService {
List<Order> orders=InitOrder(ProdLaunchOrders); List<Order> orders=InitOrder(ProdLaunchOrders, strategySchedulings);
List<Material> Materials= InitMaterial(); List<Material> Materials= InitMaterial();
...@@ -1166,7 +1176,7 @@ public class PlanResultService { ...@@ -1166,7 +1176,7 @@ public class PlanResultService {
} }
orderSortService.initializeFieldExtractors(); orderSortService.initializeFieldExtractors();
OrderSortRule rule = createMultiConditionRule(orders); OrderSortRule rule = scheduleStrategyService.createMultiConditionRule(orders);
orderSortService.assignPriority(orders, rule); orderSortService.assignPriority(orders, rule);
updateOrderRelatedEntries(chromosome, order); updateOrderRelatedEntries(chromosome, order);
...@@ -1184,7 +1194,7 @@ public class PlanResultService { ...@@ -1184,7 +1194,7 @@ public class PlanResultService {
List<Order> orders = chromosome.getOrders(); List<Order> orders = chromosome.getOrders();
orderSortService.initializeFieldExtractors(); orderSortService.initializeFieldExtractors();
OrderSortRule rule = createMultiConditionRule(orders); OrderSortRule rule = scheduleStrategyService.createMultiConditionRule(orders);
orderSortService.assignPriority(orders, rule); orderSortService.assignPriority(orders, rule);
updateOrderRelatedEntries(chromosome, order); updateOrderRelatedEntries(chromosome, order);
...@@ -2163,6 +2173,11 @@ if(job.getGeneDetails()!=null) ...@@ -2163,6 +2173,11 @@ if(job.getGeneDetails()!=null)
return globalParam; return globalParam;
} }
private List<Order> InitOrder(List<ProdLaunchOrder> ProdLaunchOrders) private List<Order> InitOrder(List<ProdLaunchOrder> ProdLaunchOrders)
{
return InitOrder(ProdLaunchOrders, Collections.emptyList());
}
private List<Order> InitOrder(List<ProdLaunchOrder> ProdLaunchOrders, List<StrategyScheduling> strategySchedulings)
{ {
orderSortService.initializeFieldExtractors(); orderSortService.initializeFieldExtractors();
List<Order> orders=new ArrayList<>(); List<Order> orders=new ArrayList<>();
...@@ -2184,11 +2199,11 @@ if(job.getGeneDetails()!=null) ...@@ -2184,11 +2199,11 @@ if(job.getGeneDetails()!=null)
order.setSYQuantity(lo.getQuantity()); order.setSYQuantity(lo.getQuantity());
orders.add(order); orders.add(order);
} }
OrderSortRule rule = createMultiConditionRule(orders); // 根据策略生成订单排序规则,并把排序结果写回 Order.actualPriority。
OrderSortRule rule = scheduleStrategyService.createMultiConditionRule(orders, strategySchedulings);
// 执行 // 执行
orderSortService.assignPriority(orders, rule); orderSortService.assignPriority(orders, rule);
// // 按照优先级排序 // // 按照优先级排序
// orders.sort( // orders.sort(
// Comparator.comparing(Order::getActualPriority) // Comparator.comparing(Order::getActualPriority)
...@@ -2196,151 +2211,6 @@ if(job.getGeneDetails()!=null) ...@@ -2196,151 +2211,6 @@ if(job.getGeneDetails()!=null)
return orders; return orders;
} }
private OrderSortRule createMultiConditionRule(List<Order> orders) {
try {
OrderSortRule rule = new OrderSortRule();
rule.setEnabled(true);
List<OrderSortRule.SortCondition> conditions = new ArrayList<>();
StrategyRule strategyRules = _strategyRuleService.lambdaQuery()
.eq(StrategyRule::getIsDeleted, 0)
.eq(StrategyRule::getIsGlobal, 1)
.one();
OrderSortRule.SortCondition condition3 = new OrderSortRule.SortCondition();
condition3.setSequence(1);
condition3.setFieldName("priority");
condition3.setReverse(false); // 优先级越小越越先
conditions.add(condition3);
// List<StrategyScheduling> StrategySchedulings = _strategyRuleService.getForwardSchedulingByRuleId(strategyRules.getId());
// Set<String> files = new HashSet<>();
// if (StrategySchedulings != null) {
// List<StrategyScheduling> selecteds = StrategySchedulings.stream().filter(t -> t.isValue() == true).sorted(Comparator.comparingInt(StrategyScheduling::getSort) ).collect(Collectors.toList());
// if (selecteds != null && selecteds.size() > 0) {
// int i = 1;
// for (StrategyScheduling strategy : selecteds) {
//
// int Amplitude= strategy.getAmplitude();
// if (strategy.getName().equals("customer_due_date")) {
// OrderSortRule.SortCondition condition = new OrderSortRule.SortCondition();
// condition.setSequence(i);
// if(Amplitude>0) {
// condition.setFieldName("groupDueDate");
// DateGroupUtil.calculateGroupDueDate(orders, "dueDate", "groupDueDate", strategy.getAmplitude());
//
// }else {
// condition.setFieldName("dueDate");
// }
// condition.setReverse(false); // 递增
// conditions.add(condition);
// files.add("groupDueDate");
// i++;
//
//
// } else if (strategy.getName().equals("startd_date") ) {
// OrderSortRule.SortCondition condition = new OrderSortRule.SortCondition();
// condition.setSequence(i);
// if(Amplitude>0) {
// condition.setFieldName("groupStartDate");
// DateGroupUtil.calculateGroupDueDate(orders, "startDate", "groupStartDate", strategy.getAmplitude());
//
// }else {
// condition.setFieldName("startDate");
// }
// condition.setReverse(false); // 递增
// conditions.add(condition);
// files.add("groupStartDate");
// i++;
//
// } else if (strategy.getName().equals("gathering_series")) {
// OrderSortRule.SortCondition condition = new OrderSortRule.SortCondition();
// condition.setSequence(i);
// condition.setFieldName("serie");
// condition.setReverse(false); // 递增
// conditions.add(condition);
// files.add("serie");
// i++;
// } else if (strategy.getName() .equals( "Minimum_wo_priority") && !files.contains("priority")) {
// OrderSortRule.SortCondition condition = new OrderSortRule.SortCondition();
// condition.setSequence(i);
// condition.setFieldName("priority");
// condition.setReverse(false); // 递增
// conditions.add(condition);
// files.add("priority");
// i++;
// } else if (strategy.getName() .equals( "maximum_wo_priority") && !files.contains("priority")) {
// OrderSortRule.SortCondition condition = new OrderSortRule.SortCondition();
// condition.setSequence(i);
// condition.setFieldName("priority");
// condition.setReverse(true); // 高优先级在前
// conditions.add(condition);
// files.add("priority");
// i++;
// } else if (strategy.getName() .equals( "material_rise")) {
// OrderSortRule.SortCondition condition = new OrderSortRule.SortCondition();
// condition.setSequence(i);
// condition.setFieldName("materialCode");
// condition.setReverse(true); // 递增
// conditions.add(condition);
// files.add("materialCode");
// i++;
// } else if (strategy.getName() .equals( "plan_rise") && !files.contains("orderCode")) {
// OrderSortRule.SortCondition condition = new OrderSortRule.SortCondition();
// condition.setSequence(i);
// condition.setFieldName("orderCode");
// condition.setReverse(true); // 递增
// conditions.add(condition);
// files.add("orderCode");
// i++;
// } else if (strategy.getName() .equals( "plan_drop") && !files.contains("orderCode")) {
// OrderSortRule.SortCondition condition = new OrderSortRule.SortCondition();
// condition.setSequence(i);
// condition.setFieldName("orderCode");
// condition.setReverse(false); // 递减
// conditions.add(condition);
// files.add("orderCode");
// i++;
// }else if (strategy.getName().equals("minimize_tool_changeovers")) {
// // 最小化换线策略需要特殊处理,这里只做标记
// // 实际排序逻辑将在orderSortService中处理
// OrderSortRule.SortCondition condition = new OrderSortRule.SortCondition();
// condition.setSequence(i);
// condition.setFieldName("minimize_changeover");
// condition.setReverse(false);
// conditions.add(condition);
// files.add("minimize_changeover");
// i++;
// }
//
// }
//
// } else {
// OrderSortRule.SortCondition condition3 = new OrderSortRule.SortCondition();
// condition3.setSequence(1);
// condition3.setFieldName("priority");
// condition3.setReverse(false); // 优先级越小越越先
// conditions.add(condition3);
// }
//
// } else {
// OrderSortRule.SortCondition condition3 = new OrderSortRule.SortCondition();
// condition3.setSequence(1);
// condition3.setFieldName("priority");
// condition3.setReverse(false); // 优先级越小越越先
// conditions.add(condition3);
//
// }
rule.setConditions(conditions);
return rule;
} catch (Exception e) {
// 捕获异常(字段不存在/类型错误/空值等)
e.printStackTrace();
return null;
}
}
public List<Material> InitMaterial() { public List<Material> InitMaterial() {
List<Material> materials=new ArrayList<>(); List<Material> materials=new ArrayList<>();
FileHelper.writeLogFile("初始化物料-----------开始-------"); FileHelper.writeLogFile("初始化物料-----------开始-------");
......
package com.aps.service.plan;
import com.aps.common.util.DateGroupUtil;
import com.aps.entity.Algorithm.OrderSortRule;
import com.aps.entity.ProdSceneConfig;
import com.aps.entity.StrategyScheduling;
import com.aps.entity.basic.Order;
import com.aps.service.ProdSceneConfigService;
import com.aps.service.UserStrategyRuleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 排产策略服务:负责读取当前排产要使用的策略,并把策略转换成订单排序规则。
*/
@Slf4j
@Service
public class ScheduleStrategyService {
@Autowired
private UserStrategyRuleService userStrategyRuleService;
@Autowired
private ProdSceneConfigService prodSceneConfigService;
/**
* 获取本次排产实际使用的用户。
* 前端传 userId 时直接使用;没传时从场景创建人 createUser 反查。
*/
public Long resolveScheduleUserId(String sceneId, Long userId) {
if (userId != null) {
return userId;
}
try {
ProdSceneConfig sceneConfig = prodSceneConfigService == null ? null : prodSceneConfigService.getById(sceneId);
return parseLongSafely(sceneConfig == null ? null : sceneConfig.getCreateUser());
} catch (Exception e) {
log.warn("读取场景用户失败,sceneId={}", sceneId, e);
return null;
}
}
/**
* 读取 /userStrategyRule/save 保存的用户策略;没有用户策略时由 UserStrategyRuleService 兜底全局策略。
*/
public List<StrategyScheduling> loadEffectiveForwardScheduling(Long userId, Long baseRuleId, String sceneId, String userRuleId) {
try {
List<StrategyScheduling> schedulings =
userStrategyRuleService.getEffectiveForwardScheduling(userId, baseRuleId, sceneId, userRuleId);
return schedulings == null ? Collections.emptyList() : schedulings;
} catch (Exception e) {
log.warn("读取排产策略失败,使用默认优先级排序,sceneId={}, userId={}, baseRuleId={}, userRuleId={}",
sceneId, userId, baseRuleId, userRuleId, e);
return Collections.emptyList();
}
}
public OrderSortRule createMultiConditionRule(List<Order> orders) {
return createMultiConditionRule(orders, Collections.emptyList());
}
/**
* 把 forwardScheduling 中 value=true 的策略项按 sort 顺序转换成 OrderSortRule。
* 如果用户策略和全局策略都没有可用项,则回退到原来的 priority 升序。
*/
public OrderSortRule createMultiConditionRule(List<Order> orders, List<StrategyScheduling> strategySchedulings) {
OrderSortRule rule = new OrderSortRule();
rule.setEnabled(true);
List<OrderSortRule.SortCondition> conditions = new ArrayList<>();
try {
Set<String> fields = new HashSet<>();
List<StrategyScheduling> selecteds = strategySchedulings == null
? Collections.emptyList()
: strategySchedulings.stream()
.filter(StrategyScheduling::isValue)
.sorted(Comparator.comparingInt(StrategyScheduling::getSort))
.collect(Collectors.toList());
int sequence = 1;
for (StrategyScheduling strategy : selecteds) {
OrderSortRule.SortCondition condition = buildSortConditionFromStrategy(orders, strategy, sequence, fields);
if (condition != null) {
conditions.add(condition);
fields.add(condition.getFieldName());
sequence++;
}
}
} catch (Exception e) {
log.warn("策略排序条件生成失败,使用默认优先级排序", e);
conditions.clear();
}
if (conditions.isEmpty()) {
conditions.add(createSortCondition(1, "priority", false));
}
rule.setConditions(conditions);
return rule;
}
/**
* 单个策略项到排序字段的映射。
* 例如 deliveryDate -> dueDate/groupDueDate,startDate -> startDate/groupStartDate。
*/
private OrderSortRule.SortCondition buildSortConditionFromStrategy(
List<Order> orders,
StrategyScheduling strategy,
int sequence,
Set<String> fields) throws Exception {
if (strategy == null || strategy.getName() == null) {
return null;
}
String name = normalizeStrategyName(strategy.getName());
int amplitude = strategy.getAmplitude();
switch (name) {
case "customerduedate":
case "customerdue_date":
case "customer_due_date":
case "deliverydate":
case "delivery_date":
case "duedate":
case "due_date": {
String fieldName = "dueDate";
// amplitude > 0 表示按 N 天跨度分组排序;amplitude <= 0 表示直接按真实交期排序。
if (amplitude > 0) {
DateGroupUtil.calculateGroupDueDate(orders, "dueDate", "groupDueDate", amplitude);
fieldName = "groupDueDate";
}
return createSortCondition(sequence, fieldName, false);
}
case "startddate":
case "startd_date":
case "startdate":
case "start_date": {
String fieldName = "startDate";
// 开始日期策略同样支持按 amplitude 天数分组。
if (amplitude > 0) {
DateGroupUtil.calculateGroupDueDate(orders, "startDate", "groupStartDate", amplitude);
fieldName = "groupStartDate";
}
return createSortCondition(sequence, fieldName, false);
}
case "gatheringseries":
case "gathering_series":
case "serie":
case "series":
return fields.contains("serie") ? null : createSortCondition(sequence, "serie", false);
case "minimumwopriority":
case "minimum_wo_priority":
case "min_wo_priority":
case "priority":
case "priority_asc":
return fields.contains("priority") ? null : createSortCondition(sequence, "priority", false);
case "maximumwopriority":
case "maximum_wo_priority":
case "max_wo_priority":
case "priority_desc":
return fields.contains("priority") ? null : createSortCondition(sequence, "priority", true);
case "materialrise":
case "material_rise":
case "materialcode":
case "material_code":
return fields.contains("materialCode") ? null : createSortCondition(sequence, "materialCode", false);
case "planrise":
case "plan_rise":
case "ordercode_asc":
case "order_code_asc":
return fields.contains("orderCode") ? null : createSortCondition(sequence, "orderCode", false);
case "plandrop":
case "plan_drop":
case "ordercode_desc":
case "order_code_desc":
return fields.contains("orderCode") ? null : createSortCondition(sequence, "orderCode", true);
case "minimizetoolchangeovers":
case "minimize_tool_changeovers":
case "minimizechangeover":
case "minimize_changeover":
return fields.contains("minimize_changeover") ? null : createSortCondition(sequence, "minimize_changeover", false);
default:
log.warn("跳过不支持的排产策略项: {}", strategy.getName());
return null;
}
}
private Long parseLongSafely(String value) {
if (value == null || value.trim().isEmpty()) {
return null;
}
try {
return Long.valueOf(value.trim());
} catch (NumberFormatException e) {
return null;
}
}
private String normalizeStrategyName(String name) {
return name == null ? "" : name.trim().replace("-", "_").replace(" ", "_").toLowerCase(Locale.ROOT);
}
private OrderSortRule.SortCondition createSortCondition(int sequence, String fieldName, boolean reverse) {
OrderSortRule.SortCondition condition = new OrderSortRule.SortCondition();
condition.setSequence(sequence);
condition.setFieldName(fieldName);
condition.setReverse(reverse);
return condition;
}
}
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