Prechádzať zdrojové kódy

feat(recommend): 实现订单分组纯类 OrderGrouper(7 项 TDD 单测通过)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jintao.geng 1 mesiac pred
rodič
commit
4a41028c2a

+ 55 - 0
mango-domain/src/main/java/com/mangoo/rating/recommend/service/recommend/OrderGrouper.java

@@ -0,0 +1,55 @@
+package com.mangoo.rating.recommend.service.recommend;
+
+import com.mangoo.rating.recommend.enums.EvaluateEfficiencyEnum;
+import com.mangoo.rating.recommend.response.recommend.OrderSuggestionVO;
+import com.mangoo.rating.recommend.response.recommend.RecommendCardVO;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * 订单分组纯算法(无 Spring 依赖)。
+ * 规则:按每卡的 recommendEfficiency 精确分组,相同档位归为一个订单;
+ *      订单按档位升序输出,groupNo 从 1 递增;
+ *      组内卡列表保留输入原顺序(稳定)。
+ *
+ * @author gengjintao
+ * @date 2026/06/24
+ */
+public final class OrderGrouper {
+
+    private OrderGrouper() {
+    }
+
+    /**
+     * 将卡列表按推荐时效分组为订单建议
+     */
+    public static List<OrderSuggestionVO> group(List<RecommendCardVO> cards) {
+        List<OrderSuggestionVO> result = new ArrayList<>();
+        if (cards == null || cards.isEmpty()) {
+            return result;
+        }
+
+        // 用 TreeMap 按档位升序归并;同档列表用 ArrayList 保留输入顺序(稳定)
+        Map<Integer, List<RecommendCardVO>> bucket = new TreeMap<>();
+        for (RecommendCardVO card : cards) {
+            Integer eff = card.getRecommendEfficiency();
+            bucket.computeIfAbsent(eff, k -> new ArrayList<>()).add(card);
+        }
+
+        int groupNo = 1;
+        for (Map.Entry<Integer, List<RecommendCardVO>> entry : bucket.entrySet()) {
+            OrderSuggestionVO order = new OrderSuggestionVO();
+            order.setGroupNo(groupNo++);
+            order.setEfficiency(entry.getKey());
+            order.setEfficiencyDesc(EvaluateEfficiencyEnum.getDescByCode(entry.getKey()));
+            order.setCardCount(entry.getValue().size());
+            order.setCards(entry.getValue());
+            // unitPrice / totalAmount 由上层报价后回填,此处不设置
+            result.add(order);
+        }
+        return result;
+    }
+}