demand: 修改规则增加循环校验

committer: heyu
This commit is contained in:
aike 2025-06-30 10:28:07 +08:00
parent 2d5da6200d
commit 33e3d850ff
3 changed files with 40 additions and 294 deletions

View File

@ -4205,28 +4205,31 @@ public class EmisBaseService {
cyclePath.add(source.getId());
// 构建详细的错误信息
StringBuilder errorMsg = new StringBuilder();
errorMsg.append("检测到循环引用!循环路径:");
for (int i = 0; i < cyclePath.size(); i++) {
if (i > 0) {
errorMsg.append(" -> ");
}
Long id = cyclePath.get(i);
EmisTransPlanRule node = findNodeById(id);
if (node != null) {
errorMsg.append(node.getLineName()).append("-")
.append(node.getProductTypeName()).append("-")
.append(node.getStartSiteName()).append("-")
.append(node.getNextSiteName()).append("-")
.append(node.getSupplierName());
} else {
errorMsg.append("节点ID:").append(id);
}
}
errorMsg.append("\n循环引用发生在节点,详细信息见上");
throw new RuntimeException(errorMsg.toString());
}
}
StringBuilder errorMsg = new StringBuilder();
errorMsg.append("检测到循环引用!循环路径:");
for (int i = 0; i < cyclePath.size(); i++) {
if (i > 0) {
errorMsg.append(" -> ");
}
Long id = cyclePath.get(i);
if (id == null) {
continue;
}
EmisTransPlanRule node = findNodeById(id);
if (node != null) {
errorMsg.append(node.getLineName()).append("-")
.append(node.getProductTypeName()).append("-")
.append(node.getStartSiteName()).append("-")
.append(node.getNextSiteName()).append("-")
.append(node.getSupplierName());
} else {
errorMsg.append("节点ID:").append(id);
}
}
// errorMsg.append("\n循环引用发生在节点,详细信息见上");
throw new RuntimeException(errorMsg.toString());
}
}
// 添加到已访问集合和路径中
visitedIds.add(source.getId());

View File

@ -98,7 +98,18 @@ public class EmisTransPlanRuleServiceImpl extends EmisBaseService implements IEm
* @return 结果
*/
@Override
public int updateEmisTransPlanRule(EmisTransPlanRule emisTransPlanRule) {
public int updateEmisTransPlanRule(EmisTransPlanRule emisTransPlanRule) throws EmisBizError {
// 校验非空
checkCode(emisTransPlanRule);
checkDate(emisTransPlanRule);
// 检查重复
checkDuplicate(emisTransPlanRule);
// 校验循环引用
EmisTransPlanRule checkRule = new EmisTransPlanRule();
checkRule.setProductType(emisTransPlanRule.getProductType());
List<EmisTransPlanRule> allRules = emisTransPlanRuleMapper.selectEmisTransPlanRuleListWithoutName(checkRule);
allRules.add(emisTransPlanRule);
buildTree(allRules, emisTransPlanRule);
return emisTransPlanRuleMapper.updateEmisTransPlanRule(emisTransPlanRule);
}
@ -362,276 +373,7 @@ public class EmisTransPlanRuleServiceImpl extends EmisBaseService implements IEm
}
}
// public List<EmisTransPlanRule> buildTree(List<EmisTransPlanRule> allRules,
// EmisTransPlanRule emisTransPlanRule) {
// // 按lineCode分组
// Map<String, List<EmisTransPlanRule>> groupByLine = allRules.stream()
// .collect(Collectors.groupingBy(EmisTransPlanRule::getLineCode));
//
// List<EmisTransPlanRule> result = new ArrayList<>();
//
// // 处理每个lineCode分组
// for (Map.Entry<String, List<EmisTransPlanRule>> lineEntry :
// groupByLine.entrySet()) {
// List<EmisTransPlanRule> lineRules = lineEntry.getValue();
// if (lineRules.isEmpty()) {
// continue;
// }
//
// //
// 按productType分组(支持productType和productTypeName为逗号分隔的多个类型,且一一对应,且每个rule只保留一个type和typeName)
// Map<String, List<EmisTransPlanRule>> groupByProductType = new HashMap<>();
// for (EmisTransPlanRule rule : lineRules) {
// if (rule.getProductType() != null) {
// String[] types = rule.getProductType().split(",");
// String[] typeNames = rule.getProductTypeName() != null ?
// rule.getProductTypeName().split(",")
// : new String[0];
// for (int i = 0; i < types.length; i++) {
// String type = types[i].trim();
// if (!type.isEmpty()) {
// EmisTransPlanRule newRule = new EmisTransPlanRule();
// BeanUtils.copyProperties(rule, newRule);
// newRule.setProductType(type);
// if (i < typeNames.length) {
// newRule.setProductTypeName(typeNames[i].trim());
// } else {
// newRule.setProductTypeName(null);
// }
// groupByProductType.computeIfAbsent(type, k -> new
// ArrayList<>()).add(newRule);
// }
// }
// }
// }
// //
// 分组内去重(lineCode、productType、startSiteCode、nextSiteCode、supplierCode、startDate、endDate都相同只保留一条)
// for (Map.Entry<String, List<EmisTransPlanRule>> entry :
// groupByProductType.entrySet()) {
// List<EmisTransPlanRule> rules = entry.getValue();
// Set<String> uniqueKeys = new HashSet<>();
// List<EmisTransPlanRule> deduped = new ArrayList<>();
// for (EmisTransPlanRule rule : rules) {
// String key = (rule.getLineCode() == null ? "" : rule.getLineCode()) + "|"
// + (rule.getProductType() == null ? "" : rule.getProductType()) + "|"
// + (rule.getStartSiteCode() == null ? "" : rule.getStartSiteCode()) + "|"
// + (rule.getNextSiteCode() == null ? "" : rule.getNextSiteCode()) + "|"
// + (rule.getSupplierCode() == null ? "" : rule.getSupplierCode()) + "|"
// + (rule.getStartDate() == null ? "" : rule.getStartDate().toString()) + "|"
// + (rule.getEndDate() == null ? "" : rule.getEndDate().toString());
// if (uniqueKeys.add(key)) {
// deduped.add(rule);
// }
// }
// entry.setValue(deduped);
// }
//
// Map<String, List<EmisTransPlanRule>> tempMap = new HashMap<>();
// if (StringUtil.isNotBlank(emisTransPlanRule.getProductType())) {
// Iterator<Map.Entry<String, List<EmisTransPlanRule>>> iterator =
// groupByProductType.entrySet()
// .iterator();
// while (iterator.hasNext()) {
// Map.Entry<String, List<EmisTransPlanRule>> entry = iterator.next();
// if (emisTransPlanRule.getProductType().equals(entry.getKey())) {
// tempMap.put(entry.getKey(), entry.getValue());
// groupByProductType = tempMap;
// break;
// }
// }
// }
//
// // 处理每个productType分组
// for (Map.Entry<String, List<EmisTransPlanRule>> productEntry :
// groupByProductType.entrySet()) {
// List<EmisTransPlanRule> productRules = productEntry.getValue();
//
// // 构建站点关系树
// Map<String, List<EmisTransPlanRule>> nodeMap = new HashMap<>();
// for (EmisTransPlanRule rule : productRules) {
// String key = rule.getNextSiteCode() != null ? rule.getNextSiteCode() :
// rule.getStartSiteCode();
// if (key != null) {
// nodeMap.computeIfAbsent(key, k -> new ArrayList<>()).add(rule);
// }
// }
//
// // 按startSiteCode分组,找出所有可能的父节点
// Map<String, List<EmisTransPlanRule>> parentGroups = productRules.stream()
// .filter(rule -> rule.getStartSiteCode() != null)
// .collect(Collectors.groupingBy(EmisTransPlanRule::getStartSiteCode));
//
// // 设置父子关系
// for (Map.Entry<String, List<EmisTransPlanRule>> parentGroup :
// parentGroups.entrySet()) {
// String startSiteCode = parentGroup.getKey();
// List<EmisTransPlanRule> children = parentGroup.getValue();
//
// // 获取所有可能的父节点
// List<EmisTransPlanRule> parents = nodeMap.get(startSiteCode);
// if (parents != null) {
// for (EmisTransPlanRule parent : parents) {
// if (parent.getChildren() == null) {
// parent.setChildren(new ArrayList<>());
// }
//
// // 添加所有子节点到父节点的children列表中
// for (EmisTransPlanRule child : children) {
// if (!parent.getChildren().contains(child)) {
// parent.getChildren().add(child);
// }
// }
// }
// }
// }
//
// // 找出顶级节点(没有父节点的节点)
// List<EmisTransPlanRule> topLevelNodes = productRules.stream()
// .filter(rule -> {
// // 检查该节点是否作为其他节点的子节点
// boolean isChild = productRules.stream()
// .anyMatch(potential -> potential.getChildren() != null
// && potential.getChildren().contains(rule));
// return !isChild;
// })
// .collect(Collectors.toList());
//
// // 将顶级节点直接添加到结果中(进行深度复制)
// for (EmisTransPlanRule node : topLevelNodes) {
// result.add(deepCopyNode(node));
// }
// }
// }
//
// // 递归设置父ID和祖先节点ID(以treeId为准)
// for (EmisTransPlanRule root : result) {
// setParentAndAncestors(root, null, "");
// }
//
// return result;
// }
//
// /**
// * 递归设置父ID和祖先节点ID
// *
// * @param node 当前节点
// * @param parentId 父节点ID
// * @param ancestors 祖先节点ID字符串
// */
// private void setParentAndAncestors(EmisTransPlanRule node, String parentId,
// String ancestors) {
// if (node == null) {
// return;
// }
// // 设置父ID
// node.setParentId(parentId);
//
// // 设置祖先节点ID
// node.setAncestors(ancestors);
// // 处理子节点,子节点的祖先包含当前节点和当前节点的所有祖先
// if (node.getChildren() != null && !node.getChildren().isEmpty()) {
// String childAncestors = ancestors.isEmpty() ? node.getTreeId() : ancestors +
// "," + node.getTreeId();
// for (EmisTransPlanRule child : node.getChildren()) {
// setParentAndAncestors(child, node.getTreeId(), childAncestors);
// }
// }
// }
//
// /**
// * 深度复制节点及其子节点
// *
// * @param source 源节点
// * @return 复制后的新节点
// */
// private EmisTransPlanRule deepCopyNode(EmisTransPlanRule source) {
// return deepCopyNode(source, new HashSet<>(), new ArrayList<>());
// }
//
// /**
// * 深度复制节点及其子节点(带循环引用检测)
// *
// * @param source 源节点
// * @param visitedIds 已访问的节点ID集合
// * @param visitPath 访问路径,用于记录循环引用的路径
// * @return 复制后的新节点
// */
// private EmisTransPlanRule deepCopyNode(EmisTransPlanRule source, Set<Long>
// visitedIds, List<Long> visitPath) {
// if (source == null) {
// return null;
// }
//
// // 检查循环引用
// if (visitedIds.contains(source.getId())) {
// // 找到循环引用的起始位置
// int cycleStartIndex = visitPath.indexOf(source.getId());
// if (cycleStartIndex != -1) {
// // 构建循环路径
// List<Long> cyclePath = visitPath.subList(cycleStartIndex, visitPath.size());
// cyclePath.add(source.getId());
//
// // 构建详细的错误信息
// StringBuilder errorMsg = new StringBuilder();
// errorMsg.append("检测到循环引用!循环路径:");
// for (int i = 0; i < cyclePath.size(); i++) {
// if (i > 0) {
// errorMsg.append(" -> ");
// }
// Long id = cyclePath.get(i);
// EmisTransPlanRule node = findNodeById(id);
// if (node != null) {
// errorMsg.append(node.getLineName()).append("-")
// .append(node.getProductTypeName()).append("-")
// .append(node.getStartSiteName()).append("-")
// .append(node.getNextSiteName()).append("-")
// .append(node.getSupplierName());
// } else {
// errorMsg.append("节点ID:").append(id);
// }
// }
// errorMsg.append("\n循环引用发生在节点,详细信息见上");
// throw new RuntimeException(errorMsg.toString());
// }
// }
//
// // 添加到已访问集合和路径中
// visitedIds.add(source.getId());
// visitPath.add(source.getId());
//
// EmisTransPlanRule copy = new EmisTransPlanRule();
// BeanUtils.copyProperties(source, copy);
//
// // 为每个新节点生成唯一treeId
// copy.setTreeId(com.xdadan.erp.common.utils.idgen.UUID.fastUUID().toString());
//
// // 递归复制子节点
// if (source.getChildren() != null) {
// List<EmisTransPlanRule> copiedChildren = new ArrayList<>();
// for (EmisTransPlanRule child : source.getChildren()) {
// copiedChildren.add(deepCopyNode(child, visitedIds, visitPath));
// }
// copy.setChildren(copiedChildren);
// }
//
// // 从路径中移除当前节点(回溯)
// visitPath.remove(visitPath.size() - 1);
//
// return copy;
// }
//
// // 新增方法:根据ID查找节点
// private EmisTransPlanRule findNodeById(Long id) {
// // 由于deepCopyNode递归时无法直接访问所有节点,这里可通过全量查询实现,实际生产建议优化
// List<EmisTransPlanRule> allRules =
// emisTransPlanRuleMapper.selectEmisTransPlanRuleList(new EmisTransPlanRule());
// for (EmisTransPlanRule rule : allRules) {
// if (rule.getId() != null && rule.getId().equals(id)) {
// return rule;
// }
// }
// return null;
// }
@Override
public List<String> checkTree(EmisTransPlanRule emisTransPlanRule) {

View File

@ -145,7 +145,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="checkDuplicate" parameterType="EmisTransPlanRule" resultMap="EmisTransPlanRuleResult">
<include refid="selectEmisTransPlanRuleVo"/>
select r.*
from emis_trans_plan_rule r
<where>
r.del_flag = '0'
<if test="lineCode != null and lineCode != ''">and r.line_code = #{lineCode}</if>