|
|
@@ -0,0 +1,89 @@
|
|
|
+package com.etotem.cfc.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.etotem.cfc.entity.CfRateTier;
|
|
|
+import com.etotem.cfc.entity.ReferralTree;
|
|
|
+import com.etotem.cfc.entity.User;
|
|
|
+import com.etotem.cfc.mapper.CfRateTierMapper;
|
|
|
+import com.etotem.cfc.mapper.ReferralTreeMapper;
|
|
|
+import com.etotem.cfc.mapper.UserMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 推荐关系物化与团队规模统计(全层级)
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class CfReferralService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ReferralTreeMapper referralTreeMapper;
|
|
|
+ @Resource
|
|
|
+ private UserMapper userMapper;
|
|
|
+ @Resource
|
|
|
+ private CfRateTierMapper cfRateTierMapper;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 绑定推荐关系时物化整条祖先链(含本人 L1)到 referral_tree。
|
|
|
+ * 调用方:CommissionService.bindReferral() 设置 user.referrerId 之后。
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void materializeReferralTree(Long childId) {
|
|
|
+ // 防止重复物化
|
|
|
+ Long cnt = referralTreeMapper.selectCount(
|
|
|
+ new LambdaQueryWrapper<ReferralTree>().eq(ReferralTree::getChildId, childId));
|
|
|
+ if (cnt != null && cnt > 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 沿 referrerId 链收集祖先(child 本人算 level 0)
|
|
|
+ List<Long> chain = new ArrayList<>();
|
|
|
+ User cur = userMapper.selectById(childId);
|
|
|
+ while (cur != null && cur.getReferrerId() != null && !chain.contains(cur.getReferrerId())) {
|
|
|
+ chain.add(cur.getReferrerId());
|
|
|
+ cur = userMapper.selectById(cur.getReferrerId());
|
|
|
+ }
|
|
|
+ // 写 referral_tree:level = 1..n,path = 从根到该祖先
|
|
|
+ // path 格式: /ancestorId/.../directReferrerId/
|
|
|
+ StringBuilder path = new StringBuilder("/");
|
|
|
+ for (int i = chain.size() - 1; i >= 0; i--) {
|
|
|
+ Long parentId = chain.get(i);
|
|
|
+ path.append(parentId).append("/");
|
|
|
+ ReferralTree node = new ReferralTree();
|
|
|
+ node.setParentId(parentId);
|
|
|
+ node.setChildId(childId);
|
|
|
+ node.setLevel(chain.size() - i);
|
|
|
+ node.setPath(path.toString());
|
|
|
+ node.setCreatedAt(new Date());
|
|
|
+ referralTreeMapper.insert(node);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 全层级团队总人数(所有下线,含间接)。
|
|
|
+ * 统计 referral_tree 中 parent_id = userId 的所有记录数。
|
|
|
+ */
|
|
|
+ public int getTotalTeamSize(Long userId) {
|
|
|
+ Long cnt = referralTreeMapper.selectCount(
|
|
|
+ new LambdaQueryWrapper<ReferralTree>().eq(ReferralTree::getParentId, userId));
|
|
|
+ return cnt == null ? 0 : cnt.intValue();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 按团队规模匹配阶梯比例:cf_rate_tier WHERE enabled=1 AND min_team_size <= size ORDER BY min_team_size DESC LIMIT 1
|
|
|
+ * 无匹配返回 0。
|
|
|
+ */
|
|
|
+ public CfRateTier matchRateTier(int teamSize) {
|
|
|
+ List<CfRateTier> tiers = cfRateTierMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<CfRateTier>()
|
|
|
+ .eq(CfRateTier::getEnabled, 1)
|
|
|
+ .le(CfRateTier::getMinTeamSize, teamSize)
|
|
|
+ .orderByDesc(CfRateTier::getMinTeamSize)
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ return tiers.isEmpty() ? null : tiers.get(0);
|
|
|
+ }
|
|
|
+}
|