Просмотр исходного кода

feat: 实现 getTeamConsumption 团队消费统计(按 referral_tree level 聚合,fulfillStatus=completed)

Sisyphus 1 неделя назад
Родитель
Сommit
48bd823e26

+ 66 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/CommissionService.java

@@ -6,8 +6,10 @@ import com.etotem.cfc.dto.CommissionSummaryDTO;
 import com.etotem.cfc.dto.ReferralSummaryDTO;
 import com.etotem.cfc.entity.CommissionRecord;
 import com.etotem.cfc.entity.Product;
+import com.etotem.cfc.entity.ProductOrder;
 import com.etotem.cfc.entity.PromotionTier;
 import com.etotem.cfc.entity.PromotionTierConfig;
+import com.etotem.cfc.entity.ReferralTree;
 import com.etotem.cfc.entity.User;
 import com.etotem.cfc.entity.WithdrawalRequest;
 import com.etotem.cfc.mapper.CommissionRecordMapper;
@@ -606,6 +608,70 @@ public class CommissionService {
         return stats;
     }
 
+    /**
+     * 团队总消费额分级汇总(按 referral_tree level 聚合)
+     * maxLevel 默认 3,可后台配置
+     */
+    public Map<String, Object> getTeamConsumption(Long userId, Integer maxLevel) {
+        if (maxLevel == null || maxLevel <= 0) maxLevel = 3;
+        if (maxLevel > 10) maxLevel = 10; // 安全上限
+
+        Map<String, Object> result = new LinkedHashMap<>();
+        List<Map<String, Object>> levelBreakdown = new ArrayList<>();
+
+        // 1. 查 referral_tree: parentId = userId 且 level <= maxLevel
+        List<ReferralTree> treeNodes = referralTreeMapper.selectList(
+                new LambdaQueryWrapper<ReferralTree>()
+                        .eq(ReferralTree::getParentId, userId)
+                        .le(ReferralTree::getLevel, maxLevel)
+                        .orderByAsc(ReferralTree::getLevel)
+        );
+
+        if (treeNodes.isEmpty()) {
+            result.put("totalConsumption", 0);
+            result.put("levelBreakdown", levelBreakdown);
+            result.put("totalMembers", 0);
+            result.put("maxLevel", maxLevel);
+            return result;
+        }
+
+        // 2. 按 level 分组收集 childId
+        Map<Integer, List<Long>> levelToChildIds = new LinkedHashMap<>();
+        for (ReferralTree node : treeNodes) {
+            levelToChildIds.computeIfAbsent(node.getLevel(), k -> new ArrayList<>()).add(node.getChildId());
+        }
+
+        // 3. 查 product_orders: buyerId IN childIds 且 fulfillStatus = 'completed'
+        int totalConsumption = 0;
+        for (Map.Entry<Integer, List<Long>> entry : levelToChildIds.entrySet()) {
+            Integer level = entry.getKey();
+            List<Long> childIds = entry.getValue();
+            if (childIds.isEmpty()) continue;
+
+            LambdaQueryWrapper<ProductOrder> orderWrapper = new LambdaQueryWrapper<ProductOrder>()
+                    .in(ProductOrder::getBuyerId, childIds)
+                    .eq(ProductOrder::getFulfillStatus, "completed");
+            Long sum = productOrderMapper.selectList(orderWrapper).stream()
+                    .mapToLong(o -> o.getTotalAmount() != null ? o.getTotalAmount() : 0)
+                    .sum();
+
+            int memberCount = childIds.size();
+            totalConsumption += sum;
+
+            Map<String, Object> levelInfo = new LinkedHashMap<>();
+            levelInfo.put("level", level);
+            levelInfo.put("memberCount", memberCount);
+            levelInfo.put("consumption", sum.intValue());
+            levelBreakdown.add(levelInfo);
+        }
+
+        result.put("totalConsumption", totalConsumption);
+        result.put("levelBreakdown", levelBreakdown);
+        result.put("totalMembers", treeNodes.size());
+        result.put("maxLevel", maxLevel);
+        return result;
+    }
+
     /**
      * 获取佣金统计(首页面板数据)
      */