From d3a5c4420a7daf89bc9832f22ca8ed9d7e1adaf9 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期五, 27 三月 2026 17:34:32 +0800
Subject: [PATCH] yys 1.完善销售下单,生成生产订单
---
src/main/java/com/ruoyi/common/utils/OrderUtils.java | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 305 insertions(+), 3 deletions(-)
diff --git a/src/main/java/com/ruoyi/common/utils/OrderUtils.java b/src/main/java/com/ruoyi/common/utils/OrderUtils.java
index 52df76b..22915df 100644
--- a/src/main/java/com/ruoyi/common/utils/OrderUtils.java
+++ b/src/main/java/com/ruoyi/common/utils/OrderUtils.java
@@ -2,6 +2,9 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.ruoyi.basic.dto.ProductModelExcelDto;
+import com.ruoyi.basic.dto.ProductModelExcelItemDto;
import com.ruoyi.common.utils.uuid.UUID;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.stereotype.Component;
@@ -11,9 +14,8 @@
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
/**
* @author :yys
@@ -54,4 +56,304 @@
// 鎷兼帴璁㈠崟缂栧彿 preFix + 鏃堕棿锛坹yyyMMdd锛� + 璁㈠崟鏁伴噺(001)
return preFix + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE).replaceAll("-", "") + String.format("%03d", (aLong + 1)) + "-" + new Date().getTime();
}
+
+ /**
+ * 灏嗗钩闈㈠垪琛ㄨ浆鎹负鏍戝舰缁撴瀯锛堝惈瑙勬牸鍨嬪彿鎷嗗垎鍔熻兘锛�
+ * @param flatList 瀵煎叆鐨勫钩闈㈡暟鎹垪琛�
+ * @return 鏍戝舰缁撴瀯鐨勬牴鑺傜偣鍒楄〃
+ */
+ public static List<ProductModelExcelDto> buildTree(List<ProductModelExcelDto> flatList) {
+ // 1. 鍙傛暟鏍¢獙
+ if (CollectionUtils.isEmpty(flatList)) {
+ return new ArrayList<>();
+ }
+
+ // 2. 棰勫鐞嗭細杩囨护鏃犳晥鏁版嵁 + 瑙勬牸鍨嬪彿鎷嗗垎 + 鍒濆鍖栧瓙鑺傜偣鍒楄〃
+ List<ProductModelExcelDto> validList = preprocessData(flatList);
+ if (CollectionUtils.isEmpty(validList)) {
+ return new ArrayList<>();
+ }
+
+ // 3. 鎸夊眰绾у垎缁勶紝渚夸簬閫愬眰澶勭悊
+ Map<Integer, List<ProductModelExcelDto>> levelGroupMap = groupByLevel(validList);
+
+ // 4. 鏋勫缓鑺傜偣鏄犲皠锛堝簭鍙� -> 鑺傜偣锛夛紝鎻愰珮鏌ヨ鏁堢巼
+ Map<String, ProductModelExcelDto> nodeMap = buildNodeMap(validList);
+
+ // 5. 閫愬眰鏋勫缓鐖跺瓙鍏崇郴
+ buildParentChildRelation(levelGroupMap, nodeMap);
+
+ // 6. 鑾峰彇鏍硅妭鐐癸紙灞傜骇1锛夊苟鎺掑簭
+ List<ProductModelExcelDto> rootNodes = getRootNodes(levelGroupMap);
+ sortTreeNodes(rootNodes);
+
+ return rootNodes;
+ }
+
+ /**
+ * 鏁版嵁棰勫鐞嗭細
+ * 1. 杩囨护鏃犳晥鏁版嵁
+ * 2. 瑙勬牸鍨嬪彿鎷嗗垎骞跺~鍏呭埌items闆嗗悎
+ * 3. 鍒濆鍖栧瓙鑺傜偣鍒楄〃
+ */
+ private static List<ProductModelExcelDto> preprocessData(List<ProductModelExcelDto> flatList) {
+ return flatList.stream()
+ // 杩囨护鏍稿績瀛楁鏃犳晥鐨勮妭鐐�
+ .filter(node -> isValidNode(node))
+ // 澶勭悊瑙勬牸鍨嬪彿鎷嗗垎鍜宨tems濉厖
+ .peek(node -> {
+ // 鎷嗗垎瑙勬牸鍨嬪彿骞跺~鍏呭埌items
+ splitModelAndFillItems(node);
+ // 鍒濆鍖栧瓙鑺傜偣鍒楄〃锛堥伩鍏嶇┖鎸囬拡锛�
+ if (node.getChildren() == null) {
+ node.setChildren(new ArrayList<>());
+ }
+ })
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * 楠岃瘉鑺傜偣鏄惁鏈夋晥锛堟牳蹇冨瓧娈垫牎楠岋級
+ */
+ private static boolean isValidNode(ProductModelExcelDto node) {
+ if (node == null) {
+ return false;
+ }
+ // 搴忓彿蹇呴』鏈夋晥锛堝熀纭�鏍¢獙锛�
+ if (!isValidSequence(node.getNumber())) {
+ return false;
+ }
+ // 浜у搧鍚嶇О闈炵┖锛堜笟鍔℃牎楠岋紝鍙牴鎹疄闄呴渶姹傝皟鏁达級
+ return StringUtils.isNotBlank(node.getProductName());
+ }
+
+ /**
+ * 瑙勬牸鍨嬪彿鎷嗗垎骞跺~鍏呭埌items闆嗗悎
+ * @param node 寰呭鐞嗙殑鑺傜偣
+ */
+ private static void splitModelAndFillItems(ProductModelExcelDto node) {
+ // 1. 鑾峰彇鍘熷瑙勬牸鍨嬪彿
+ String originalModel = node.getModel();
+ List<ProductModelExcelItemDto> items = new ArrayList<>();
+
+ if (StringUtils.isNotBlank(originalModel)) {
+ // 2. 鎸�"+"鎷嗗垎瑙勬牸鍨嬪彿锛堝鏋滄湁澶氫釜锛夛紝澶勭悊姣忎釜鐗囨
+ List<String> splitModels = Arrays.stream(originalModel.split("\\+"))
+ .map(String::trim)
+ .filter(StringUtils::isNotBlank)
+ .distinct()
+ .collect(Collectors.toList());
+
+ // 3. 涓烘瘡涓鏍煎垱寤篒tem锛堝嵆浣垮彧鏈変竴涓紝涔熺敓鎴愪竴涓狪tem锛�
+ items = splitModels.stream()
+ .map(model -> createExcelItem(node, model))
+ .collect(Collectors.toList());
+ }
+
+ // 4. 濉厖鍒拌妭鐐圭殑items闆嗗悎锛堣鐩栧師鏈夋暟鎹級
+ node.setItems(items);
+ }
+
+ /**
+ * 鍒涘缓ProductModelExcelItemDto瀵硅薄锛堢户鎵垮師鑺傜偣鐨勫叕鍏卞睘鎬э級
+ * @param node 鍘熻妭鐐�
+ * @param model 鎷嗗垎鍚庣殑瑙勬牸鍨嬪彿
+ * @return 鏋勫缓濂界殑Item瀵硅薄
+ */
+ private static ProductModelExcelItemDto createExcelItem(ProductModelExcelDto node, String model) {
+ ProductModelExcelItemDto item = new ProductModelExcelItemDto();
+ // 1. 鎷嗗垎鍚庣殑瑙勬牸鍨嬪彿
+ item.setModel(model);
+ // 2. 缁ф壙鍘熻妭鐐圭殑鍗曚綅锛堢┖鍊煎鐞嗭級
+ item.setUnit(StringUtils.defaultIfBlank(node.getUnit(), ""));
+ // 3. 缁ф壙鍘熻妭鐐圭殑浜у搧绫诲瀷锛堢┖鍊煎鐞嗭紝榛樿0琛ㄧず鏈煡锛�
+ item.setProductType(Optional.ofNullable(node.getProductType()).orElse(0));
+ // 4. 缁ф壙鍘熻妭鐐圭殑鍥剧焊缂栧彿锛堢┖鍊煎鐞嗭級
+ item.setDrawingNumber(StringUtils.defaultIfBlank(node.getDrawingNumber(), ""));
+ return item;
+ }
+
+ /**
+ * 楠岃瘉搴忓彿鏍煎紡鏄惁鏈夋晥锛堟敮鎸�1銆�1.1銆�1.1.1绛夋牸寮忥級
+ */
+ private static boolean isValidSequence(String sequence) {
+ if (StringUtils.isBlank(sequence)) {
+ return false;
+ }
+ // 姝e垯琛ㄨ揪寮忥細鍖归厤鏁板瓧寮�澶达紝鍚庣画鍙窡.鍜屾暟瀛�
+ return sequence.trim().matches("^\\d+(\\.\\d+)*$");
+ }
+
+ /**
+ * 鎸夎妭鐐瑰眰绾у垎缁�
+ */
+ private static Map<Integer, List<ProductModelExcelDto>> groupByLevel(List<ProductModelExcelDto> validList) {
+ return validList.stream()
+ .collect(Collectors.groupingBy(
+ node -> getNodeLevel(node.getNumber()), // 璁$畻灞傜骇
+ TreeMap::new, // 鎸夊眰绾у崌搴忔帓搴�
+ Collectors.toList()
+ ));
+ }
+
+ /**
+ * 璁$畻鑺傜偣灞傜骇锛堝簭鍙蜂腑.鐨勬暟閲� + 1锛�
+ * 渚嬶細1 -> 1绾э紝1.1 -> 2绾э紝1.1.1 -> 3绾�
+ */
+ private static int getNodeLevel(String sequence) {
+ if (StringUtils.isBlank(sequence)) {
+ return 0;
+ }
+ String trimmedSeq = sequence.trim();
+ return trimmedSeq.split("\\.").length;
+ }
+
+ /**
+ * 鏋勫缓鑺傜偣鏄犲皠琛紙搴忓彿 -> 鑺傜偣锛�
+ */
+ private static Map<String, ProductModelExcelDto> buildNodeMap(List<ProductModelExcelDto> validList) {
+ return validList.stream()
+ .collect(Collectors.toMap(
+ node -> node.getNumber().trim(), // 閿細搴忓彿锛堝幓绌烘牸锛�
+ node -> node, // 鍊硷細鑺傜偣瀵硅薄
+ (oldVal, newVal) -> oldVal // 澶勭悊閲嶅搴忓彿锛氫繚鐣欑涓�涓�
+ ));
+ }
+
+ /**
+ * 鏋勫缓鐖跺瓙鑺傜偣鍏崇郴
+ */
+ private static void buildParentChildRelation(Map<Integer, List<ProductModelExcelDto>> levelGroupMap,
+ Map<String, ProductModelExcelDto> nodeMap) {
+ // 浠庡眰绾�2寮�濮嬪鐞嗭紙灞傜骇1鏄牴鑺傜偣锛屾棤鐖惰妭鐐癸級
+ for (Map.Entry<Integer, List<ProductModelExcelDto>> entry : levelGroupMap.entrySet()) {
+ int currentLevel = entry.getKey();
+ if (currentLevel <= 1) {
+ continue; // 璺宠繃鏍硅妭鐐瑰眰绾�
+ }
+
+ List<ProductModelExcelDto> currentLevelNodes = entry.getValue();
+ for (ProductModelExcelDto currentNode : currentLevelNodes) {
+ // 璁$畻鐖惰妭鐐瑰簭鍙�
+ String parentSequence = getParentSequence(currentNode.getNumber());
+ if (StringUtils.isBlank(parentSequence)) {
+ continue;
+ }
+
+ // 鏌ユ壘鐖惰妭鐐�
+ ProductModelExcelDto parentNode = nodeMap.get(parentSequence);
+ if (parentNode != null && parentNode.getChildren() != null) {
+ // 娣诲姞鍒扮埗鑺傜偣鐨勫瓙鑺傜偣鍒楄〃
+ parentNode.getChildren().add(currentNode);
+ }
+ }
+ }
+ }
+
+ /**
+ * 鏍规嵁褰撳墠鑺傜偣搴忓彿鑾峰彇鐖惰妭鐐瑰簭鍙�
+ * 渚嬶細1.1.2 -> 1.1锛�1.2 -> 1锛�1 -> null
+ */
+ private static String getParentSequence(String currentSequence) {
+ if (StringUtils.isBlank(currentSequence)) {
+ return null;
+ }
+
+ String trimmedSeq = currentSequence.trim();
+ String[] seqParts = trimmedSeq.split("\\.");
+ if (seqParts.length <= 1) {
+ return null; // 鏍硅妭鐐规棤鐖惰妭鐐�
+ }
+
+ // 鍘绘帀鏈�鍚庝竴閮ㄥ垎锛屾嫾鎺ョ埗鑺傜偣搴忓彿
+ String[] parentParts = Arrays.copyOfRange(seqParts, 0, seqParts.length - 1);
+ return String.join(".", parentParts);
+ }
+
+ /**
+ * 鑾峰彇鏍硅妭鐐瑰垪琛紙灞傜骇1鐨勮妭鐐癸級
+ */
+ private static List<ProductModelExcelDto> getRootNodes(Map<Integer, List<ProductModelExcelDto>> levelGroupMap) {
+ return levelGroupMap.getOrDefault(1, new ArrayList<>());
+ }
+
+ /**
+ * 閫掑綊鎺掑簭鎵�鏈夎妭鐐癸紙鎸夊簭鍙锋暟瀛楅『搴忥級
+ */
+ private static void sortTreeNodes(List<ProductModelExcelDto> nodeList) {
+ if (CollectionUtils.isEmpty(nodeList)) {
+ return;
+ }
+
+ // 鎺掑簭褰撳墠灞傜骇鑺傜偣
+ nodeList.sort(Comparator.comparing(
+ ProductModelExcelDto::getNumber,
+ new SequenceComparator() // 鑷畾涔夊簭鍙锋瘮杈冨櫒
+ ));
+
+ // 閫掑綊鎺掑簭瀛愯妭鐐�
+ for (ProductModelExcelDto node : nodeList) {
+ sortTreeNodes(node.getChildren());
+ }
+ }
+
+ /**
+ * 搴忓彿姣旇緝鍣細鎸夋暟瀛楅『搴忔帓搴忥紙鏀寔1.10鍦�1.2涔嬪悗锛�
+ */
+ private static class SequenceComparator implements Comparator<String> {
+ @Override
+ public int compare(String seq1, String seq2) {
+ if (StringUtils.isBlank(seq1) && StringUtils.isBlank(seq2)) {
+ return 0;
+ }
+ if (StringUtils.isBlank(seq1)) {
+ return -1;
+ }
+ if (StringUtils.isBlank(seq2)) {
+ return 1;
+ }
+
+ // 鍒嗗壊搴忓彿涓烘暟瀛楁暟缁�
+ String[] parts1 = seq1.trim().split("\\.");
+ String[] parts2 = seq2.trim().split("\\.");
+
+ // 閫愭姣旇緝鏁板瓧
+ int minLength = Math.min(parts1.length, parts2.length);
+ for (int i = 0; i < minLength; i++) {
+ int num1 = parseSequencePart(parts1[i]);
+ int num2 = parseSequencePart(parts2[i]);
+ if (num1 != num2) {
+ return num1 - num2;
+ }
+ }
+
+ // 闀垮害涓嶅悓鏃讹紝鐭殑鍦ㄥ墠锛堝1.1鍦�1.1.1涔嬪墠锛�
+ return parts1.length - parts2.length;
+ }
+
+ /**
+ * 瑙f瀽搴忓彿鐗囨涓烘暟瀛楋紙澶勭悊寮傚父鎯呭喌锛�
+ */
+ private int parseSequencePart(String part) {
+ try {
+ return Integer.parseInt(part.trim());
+ } catch (NumberFormatException e) {
+ return 0; // 寮傚父鎯呭喌鎸�0澶勭悊
+ }
+ }
+ }
+
+
+ /**
+ * 浜у搧绫诲瀷鏄犲皠锛�1=鐗╂枡锛�2=浜у搧锛�0=鏈煡锛�
+ */
+ private static String mapProductType(Integer productType) {
+ return Optional.ofNullable(productType)
+ .map(type -> type == 1 ? "鐗╂枡" : (type == 2 ? "浜у搧" : "鏈煡"))
+ .orElse("鏈煡");
+ }
+
+
+
+
}
--
Gitblit v1.9.3