|
|
@@ -0,0 +1,126 @@
|
|
|
+package com.etotem.cfc.service;
|
|
|
+
|
|
|
+import com.etotem.cfc.entity.CfRateTier;
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+import static org.junit.jupiter.api.Assertions.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * CF 值分佣阶梯匹配边界测试。
|
|
|
+ *
|
|
|
+ * 复刻 CfReferralService.matchRateTier 的匹配语义:
|
|
|
+ * WHERE enabled = 1 AND min_team_size <= teamSize
|
|
|
+ * ORDER BY min_team_size DESC LIMIT 1
|
|
|
+ *
|
|
|
+ * 种子数据(DatabaseInitializer 迁移279):
|
|
|
+ * 铜牌 min=0 5% / 银牌 min=3 10% / 金牌 min=10 15%
|
|
|
+ * 铂金 min=30 20% / 钻石 min=100 25%
|
|
|
+ *
|
|
|
+ * 预期边界映射:
|
|
|
+ * 0/1/2 → 铜牌 5
|
|
|
+ * 3~9 → 银牌 10
|
|
|
+ * 10~29 → 金牌 15
|
|
|
+ * 30~99 → 铂金 20
|
|
|
+ * 100+ → 钻石 25
|
|
|
+ */
|
|
|
+class CfCommissionServiceTest {
|
|
|
+
|
|
|
+ private static final List<CfRateTier> SEED_TIERS = buildSeedTiers();
|
|
|
+
|
|
|
+ private static List<CfRateTier> buildSeedTiers() {
|
|
|
+ List<CfRateTier> list = new ArrayList<>();
|
|
|
+ list.add(tier("铜牌", 0, 5, 1));
|
|
|
+ list.add(tier("银牌", 3, 10, 2));
|
|
|
+ list.add(tier("金牌", 10, 15, 3));
|
|
|
+ list.add(tier("铂金", 30, 20, 4));
|
|
|
+ list.add(tier("钻石", 100, 25, 5));
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static CfRateTier tier(String name, int minTeamSize, int ratePercent, int sortOrder) {
|
|
|
+ CfRateTier t = new CfRateTier();
|
|
|
+ t.setTierName(name);
|
|
|
+ t.setMinTeamSize(minTeamSize);
|
|
|
+ t.setRatePercent(ratePercent);
|
|
|
+ t.setSortOrder(sortOrder);
|
|
|
+ t.setEnabled(1);
|
|
|
+ return t;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 等价于 CfReferralService.matchRateTier 的查询语义。
|
|
|
+ * 在内存中对启用的档位按 min_team_size <= teamSize 过滤后取最大 min_team_size 档位。
|
|
|
+ */
|
|
|
+ private CfRateTier matchRateTier(int teamSize) {
|
|
|
+ CfRateTier best = null;
|
|
|
+ for (CfRateTier t : SEED_TIERS) {
|
|
|
+ if (t.getEnabled() != 1 || t.getMinTeamSize() > teamSize) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (best == null || t.getMinTeamSize() > best.getMinTeamSize()) {
|
|
|
+ best = t;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return best;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void teamSize0_shouldMatchBronze5() {
|
|
|
+ assertTier(0, 5, "铜牌");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void teamSize2_shouldMatchBronze5() {
|
|
|
+ assertTier(2, 5, "铜牌");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void teamSize3_shouldMatchSilver10() {
|
|
|
+ assertTier(3, 10, "银牌");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void teamSize9_shouldMatchSilver10() {
|
|
|
+ assertTier(9, 10, "银牌");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void teamSize10_shouldMatchGold15() {
|
|
|
+ assertTier(10, 15, "金牌");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void teamSize29_shouldMatchGold15() {
|
|
|
+ assertTier(29, 15, "金牌");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void teamSize30_shouldMatchPlatinum20() {
|
|
|
+ assertTier(30, 20, "铂金");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void teamSize99_shouldMatchPlatinum20() {
|
|
|
+ assertTier(99, 20, "铂金");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void teamSize100_shouldMatchDiamond25() {
|
|
|
+ assertTier(100, 25, "钻石");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void teamSize100plus_shouldMatchDiamond25() {
|
|
|
+ assertTier(1000, 25, "钻石");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assertTier(int teamSize, int expectedRate, String expectedName) {
|
|
|
+ CfRateTier tier = matchRateTier(teamSize);
|
|
|
+ assertNotNull(tier, "teamSize=" + teamSize + " 应匹配到档位");
|
|
|
+ assertEquals(expectedRate, tier.getRatePercent(), "teamSize=" + teamSize + " 返佣比例");
|
|
|
+ assertEquals(expectedName, tier.getTierName(), "teamSize=" + teamSize + " 档位名");
|
|
|
+ }
|
|
|
+}
|