| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454 |
- package com.etotem.cfc.service;
- import com.baomidou.mybatisplus.core.MybatisConfiguration;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
- import com.etotem.cfc.config.ConfigService;
- import com.etotem.cfc.constant.CfConfigKeys;
- import com.etotem.cfc.dto.CfEarnResult;
- import com.etotem.cfc.entity.CfDirectSalesTier;
- import com.etotem.cfc.entity.CfEarnRule;
- import com.etotem.cfc.entity.CfIndirectSalesTier;
- import com.etotem.cfc.entity.FamilyMember;
- import com.etotem.cfc.entity.OctopusEffectRecord;
- import com.etotem.cfc.entity.OctopusKeyPerson;
- import com.etotem.cfc.entity.PpointConsumptionLog;
- import com.etotem.cfc.entity.Product;
- import com.etotem.cfc.entity.ReferralTree;
- import com.etotem.cfc.entity.User;
- import com.etotem.cfc.mapper.CfTransferRecordMapper;
- import com.etotem.cfc.mapper.FamilyMemberMapper;
- import com.etotem.cfc.mapper.OctopusEffectKeyPersonMapper;
- import com.etotem.cfc.mapper.OctopusEffectRecordMapper;
- import com.etotem.cfc.mapper.OctopusKeyPersonMapper;
- import com.etotem.cfc.mapper.PpointConsumptionLogMapper;
- import com.etotem.cfc.mapper.ProductMapper;
- import com.etotem.cfc.mapper.ReferralTreeMapper;
- import com.etotem.cfc.mapper.UserMapper;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import org.apache.ibatis.builder.MapperBuilderAssistant;
- import org.junit.jupiter.api.BeforeEach;
- import org.junit.jupiter.api.Test;
- import org.mockito.ArgumentCaptor;
- import org.mockito.InjectMocks;
- import org.mockito.Mock;
- import org.mockito.MockitoAnnotations;
- import org.mockito.Spy;
- import java.util.Arrays;
- import java.util.Collections;
- import java.util.Map;
- import static org.junit.jupiter.api.Assertions.assertEquals;
- import static org.junit.jupiter.api.Assertions.assertNotNull;
- import static org.junit.jupiter.api.Assertions.assertTrue;
- import static org.mockito.ArgumentMatchers.any;
- import static org.mockito.ArgumentMatchers.anyLong;
- import static org.mockito.ArgumentMatchers.anyString;
- import static org.mockito.ArgumentMatchers.eq;
- import static org.mockito.Mockito.never;
- import static org.mockito.Mockito.times;
- import static org.mockito.Mockito.verify;
- import static org.mockito.Mockito.when;
- /**
- * CF 分佣收口(F-4)两级销售奖结算行为测试。
- *
- * <p>覆盖口径(计划 §四 / §3.1 / §4.2 / §4.4):</p>
- * <ul>
- * <li>第 1 个非同家庭引荐人 → F03a 直接销售奖,比例取"团队 8 层内滚动一年累计 P 点"档位;</li>
- * <li>第 2 个非同家庭引荐人 → F03b 间接销售奖,比例取"自身滚动一年累计消费 P 点"档位;</li>
- * <li>共同基数 = 本单消费产生的 P 点(商品按有效 P 点比例折算);</li>
- * <li>同家庭互推(D5)跳过并顺延,最多两级;</li>
- * <li>档位比例超 {@code cf_earn_rule.params_json.max_rate_percent} 时按上限封顶;</li>
- * <li>发放统一走 F-2 的 {@code earnByRule}(幂等键复用 F-2 唯一键);销售奖不再写第二套流水
- * ({@code cf_transfer_record} 仅买家 F02 路径写);</li>
- * <li>F03a 发放时创建感恩记录,幂等命中(duplicated)不重复创建。</li>
- * </ul>
- */
- class CfCommissionServiceSettleTest {
- @Mock
- private ReferralTreeMapper referralTreeMapper;
- @Mock
- private UserMapper userMapper;
- @Mock
- private CfReferralService cfReferralService;
- @Mock
- private PlatformPointsService platformPointsService;
- @Mock
- private CfTransferRecordMapper cfTransferRecordMapper;
- @Mock
- private PpointConfigService ppointConfigService;
- @Mock
- private SysConfigService sysConfigService;
- @Mock
- private ProductMapper productMapper;
- @Mock
- private OctopusKeyPersonMapper octopusKeyPersonMapper;
- @Mock
- private OctopusEffectRecordMapper octopusEffectRecordMapper;
- @Mock
- private OctopusEffectKeyPersonMapper octopusEffectKeyPersonMapper;
- @Mock
- private CfBalanceService cfBalanceService;
- @Mock
- private CfEarnRuleService cfEarnRuleService;
- @Mock
- private FamilyMemberMapper familyMemberMapper;
- @Mock
- private PpointConsumptionLogMapper ppointConsumptionLogMapper;
- @Mock
- private ConfigService configService;
- @Spy
- private ObjectMapper objectMapper = new ObjectMapper();
- @InjectMocks
- private CfCommissionService cfCommissionService;
- private static final Long ORDER_ID = 1L;
- private static final Long PRODUCT_ID = 999L;
- private static final Long BUYER_ID = 100L;
- private static final Long BUYER_FAMILY = 100L;
- /** 家庭成员ID = 用户ID + 1000,便于断言 */
- private static Long memberIdOf(Long userId) {
- return userId + 1000;
- }
- @BeforeEach
- void setUp() {
- MockitoAnnotations.openMocks(this);
- TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), ReferralTree.class);
- TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), FamilyMember.class);
- TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), OctopusKeyPerson.class);
- // 商品:有效 P 点=100(商品订单 100 元 → 基数 100 P 点)
- Product p = new Product();
- p.setId(PRODUCT_ID);
- p.setCategoryId(1L);
- when(productMapper.selectById(PRODUCT_ID)).thenReturn(p);
- when(ppointConfigService.getEffectivePpoint(PRODUCT_ID, 1L)).thenReturn(100);
- // 买家 F02 路径(本期不改口径)
- when(sysConfigService.getValue("product_platform_points_share")).thenReturn("1000");
- when(cfTransferRecordMapper.insert(any())).thenReturn(1);
- // 非商品路径的服务费率(L2 配置中心)
- when(configService.getIntConfig(CfConfigKeys.COMMISSION_SERVICE_RATE, 1000)).thenReturn(1000);
- // 用户ID → 家庭成员档案
- when(familyMemberMapper.selectOne(any())).thenAnswer(inv -> {
- LambdaQueryWrapper<FamilyMember> wrapper = inv.getArgument(0);
- // MP 惰性绑定参数:必须先生成 SQL 片段,paramNameValuePairs 才有值
- wrapper.getSqlSegment();
- Long uid = wrapper.getParamNameValuePairs().values().stream()
- .filter(v -> v instanceof Long)
- .map(v -> (Long) v)
- .findFirst()
- .orElse(null);
- return uid == null ? null : member(uid);
- });
- // 规则上限比例:F03a ≤ 70%,F03b ≤ 20%
- when(cfEarnRuleService.getByCode("F03a"))
- .thenReturn(earnRule("F03a", "{\"base\":\"ppoints\",\"tier_table\":\"cf_direct_sales_tier\","
- + "\"window\":\"1y_rolling\",\"team_depth\":8,\"max_rate_percent\":70,\"downgrade\":true}"));
- when(cfEarnRuleService.getByCode("F03b"))
- .thenReturn(earnRule("F03b", "{\"base\":\"ppoints\",\"tier_table\":\"cf_indirect_sales_tier\","
- + "\"window\":\"1y_rolling\",\"max_rate_percent\":20,\"downgrade\":true}"));
- // P 点消费日志写入
- when(ppointConsumptionLogMapper.insert(any())).thenReturn(1);
- // 感恩记录相关
- when(octopusKeyPersonMapper.selectList(any())).thenReturn(Collections.emptyList());
- when(octopusKeyPersonMapper.insert(any())).thenAnswer(inv -> {
- OctopusKeyPerson kp = inv.getArgument(0);
- kp.setId(500L);
- return 1;
- });
- when(octopusEffectRecordMapper.insert(any())).thenAnswer(inv -> {
- OctopusEffectRecord record = inv.getArgument(0);
- record.setId(600L);
- return 1;
- });
- when(octopusEffectKeyPersonMapper.insert(any())).thenReturn(1);
- }
- // ---------------- 测试夹具 ----------------
- private ReferralTree ref(Long parent, int level) {
- ReferralTree r = new ReferralTree();
- r.setParentId(parent);
- r.setChildId(BUYER_ID);
- r.setLevel(level);
- return r;
- }
- private User user(Long id, Long familyId) {
- User u = new User();
- u.setId(id);
- u.setFamilyId(familyId);
- return u;
- }
- private FamilyMember member(Long userId) {
- FamilyMember m = new FamilyMember();
- m.setId(memberIdOf(userId));
- m.setUserId(userId);
- m.setFamilyId(userId + 5000);
- return m;
- }
- private CfDirectSalesTier directTier(String name, int min, int rate) {
- CfDirectSalesTier t = new CfDirectSalesTier();
- t.setTierName(name);
- t.setMinAnnualPpoints(min);
- t.setRatePercent(rate);
- t.setEnabled(1);
- return t;
- }
- private CfIndirectSalesTier indirectTier(String name, int min, int rate) {
- CfIndirectSalesTier t = new CfIndirectSalesTier();
- t.setTierName(name);
- t.setMinSelfPpoints(min);
- t.setRatePercent(rate);
- t.setEnabled(1);
- return t;
- }
- private CfEarnRule earnRule(String code, String paramsJson) {
- CfEarnRule r = new CfEarnRule();
- r.setCode(code);
- r.setEnabled(1);
- r.setRuleType("formula");
- r.setFormula("floor(base_ppoints * rate_percent / 100)");
- r.setParamsJson(paramsJson);
- r.setDedupRefType(code);
- return r;
- }
- private CfEarnResult earnResult(int amount, boolean duplicated) {
- CfEarnResult r = new CfEarnResult();
- r.setEarned(true);
- r.setAmount(amount);
- r.setDuplicated(duplicated);
- return r;
- }
- private void mockReferralChain(ReferralTree... nodes) {
- when(referralTreeMapper.selectList(any(LambdaQueryWrapper.class)))
- .thenReturn(Arrays.asList(nodes));
- }
- // ---------------- 测试 ----------------
- @Test
- void settle_两级销售奖_F03a按团队档位_F03b按自身档位() {
- mockReferralChain(ref(10L, 1), ref(20L, 2));
- when(userMapper.selectById(10L)).thenReturn(user(10L, 200L));
- when(userMapper.selectById(20L)).thenReturn(user(20L, 300L));
- // F03a:团队 8 层滚动一年累计 2000 P 点 → 黄金档 40%
- when(cfReferralService.getTeamAnnualPpoints(10L, 8)).thenReturn(2000);
- when(cfReferralService.matchDirectSalesTier(2000)).thenReturn(directTier("黄金", 2000, 40));
- // F03b:自身滚动一年累计 500 P 点 → 白银档 5%
- when(cfReferralService.getSelfAnnualPpoints(20L)).thenReturn(500);
- when(cfReferralService.matchIndirectSalesTier(500)).thenReturn(indirectTier("白银", 500, 5));
- when(cfBalanceService.earnByRule(eq(memberIdOf(10L)), eq("F03a"), eq(ORDER_ID), any()))
- .thenReturn(earnResult(40, false));
- when(cfBalanceService.earnByRule(eq(memberIdOf(20L)), eq("F03b"), eq(ORDER_ID), any()))
- .thenReturn(earnResult(5, false));
- cfCommissionService.settle(ORDER_ID, "product", BUYER_ID, BUYER_FAMILY, 10000, PRODUCT_ID);
- // F03a:基数 100 P 点 × 40%
- ArgumentCaptor<Map<String, Object>> ctxCaptor = ArgumentCaptor.forClass(Map.class);
- verify(cfBalanceService).earnByRule(eq(memberIdOf(10L)), eq("F03a"), eq(ORDER_ID), ctxCaptor.capture());
- assertEquals(100, ctxCaptor.getValue().get("base_ppoints"));
- assertEquals(40, ctxCaptor.getValue().get("rate_percent"));
- // F03b:基数 100 P 点 × 5%
- ArgumentCaptor<Map<String, Object>> ctxCaptor2 = ArgumentCaptor.forClass(Map.class);
- verify(cfBalanceService).earnByRule(eq(memberIdOf(20L)), eq("F03b"), eq(ORDER_ID), ctxCaptor2.capture());
- assertEquals(100, ctxCaptor2.getValue().get("base_ppoints"));
- assertEquals(5, ctxCaptor2.getValue().get("rate_percent"));
- // 买家 F02 返 CF(本期口径不变):100 元 × 100P点/100 × 10% = 10
- verify(platformPointsService).earn(eq(BUYER_ID), eq(10), eq("order_consume"), eq(ORDER_ID), anyString());
- }
- @Test
- void settle_销售奖只走cfBalance_不再写旧流转记录() {
- mockReferralChain(ref(10L, 1), ref(20L, 2));
- when(userMapper.selectById(10L)).thenReturn(user(10L, 200L));
- when(userMapper.selectById(20L)).thenReturn(user(20L, 300L));
- when(cfReferralService.getTeamAnnualPpoints(10L, 8)).thenReturn(100);
- when(cfReferralService.matchDirectSalesTier(100)).thenReturn(directTier("青铜", 100, 10));
- when(cfReferralService.getSelfAnnualPpoints(20L)).thenReturn(100);
- when(cfReferralService.matchIndirectSalesTier(100)).thenReturn(indirectTier("青铜", 100, 2));
- when(cfBalanceService.earnByRule(anyLong(), anyString(), anyLong(), any()))
- .thenReturn(earnResult(10, false));
- cfCommissionService.settle(ORDER_ID, "product", BUYER_ID, BUYER_FAMILY, 10000, PRODUCT_ID);
- // cf_transfer_record 只写买家 F02 一笔,销售奖不再产生第二套流水
- verify(cfTransferRecordMapper, times(1)).insert(any());
- }
- @Test
- void settle_同家庭引荐人跳过_顺延到下一级拿F03a() {
- mockReferralChain(ref(10L, 1), ref(20L, 2), ref(30L, 3));
- when(userMapper.selectById(10L)).thenReturn(user(10L, BUYER_FAMILY));
- when(userMapper.selectById(20L)).thenReturn(user(20L, 200L));
- when(userMapper.selectById(30L)).thenReturn(user(30L, 300L));
- when(cfReferralService.getTeamAnnualPpoints(20L, 8)).thenReturn(500);
- when(cfReferralService.matchDirectSalesTier(500)).thenReturn(directTier("白银", 500, 25));
- when(cfReferralService.getSelfAnnualPpoints(30L)).thenReturn(100);
- when(cfReferralService.matchIndirectSalesTier(100)).thenReturn(indirectTier("青铜", 100, 2));
- when(cfBalanceService.earnByRule(eq(memberIdOf(20L)), eq("F03a"), eq(ORDER_ID), any()))
- .thenReturn(earnResult(25, false));
- when(cfBalanceService.earnByRule(eq(memberIdOf(30L)), eq("F03b"), eq(ORDER_ID), any()))
- .thenReturn(earnResult(2, false));
- cfCommissionService.settle(ORDER_ID, "product", BUYER_ID, BUYER_FAMILY, 10000, PRODUCT_ID);
- // 同家庭的 level1 不发放
- verify(cfBalanceService, never()).earnByRule(eq(memberIdOf(10L)), anyString(), anyLong(), any());
- verify(cfBalanceService).earnByRule(eq(memberIdOf(20L)), eq("F03a"), eq(ORDER_ID), any());
- verify(cfBalanceService).earnByRule(eq(memberIdOf(30L)), eq("F03b"), eq(ORDER_ID), any());
- }
- @Test
- void settle_最多两级_第三级引荐人不发放() {
- mockReferralChain(ref(10L, 1), ref(20L, 2), ref(30L, 3));
- when(userMapper.selectById(10L)).thenReturn(user(10L, 200L));
- when(userMapper.selectById(20L)).thenReturn(user(20L, 300L));
- when(userMapper.selectById(30L)).thenReturn(user(30L, 400L));
- when(cfReferralService.getTeamAnnualPpoints(10L, 8)).thenReturn(100);
- when(cfReferralService.matchDirectSalesTier(100)).thenReturn(directTier("青铜", 100, 10));
- when(cfReferralService.getSelfAnnualPpoints(20L)).thenReturn(100);
- when(cfReferralService.matchIndirectSalesTier(100)).thenReturn(indirectTier("青铜", 100, 2));
- when(cfBalanceService.earnByRule(anyLong(), anyString(), anyLong(), any()))
- .thenReturn(earnResult(10, false));
- cfCommissionService.settle(ORDER_ID, "product", BUYER_ID, BUYER_FAMILY, 10000, PRODUCT_ID);
- verify(cfBalanceService).earnByRule(eq(memberIdOf(10L)), eq("F03a"), eq(ORDER_ID), any());
- verify(cfBalanceService).earnByRule(eq(memberIdOf(20L)), eq("F03b"), eq(ORDER_ID), any());
- verify(cfBalanceService, never()).earnByRule(eq(memberIdOf(30L)), anyString(), anyLong(), any());
- }
- @Test
- void settle_档位比例超规则上限_按上限封顶() {
- mockReferralChain(ref(10L, 1));
- when(userMapper.selectById(10L)).thenReturn(user(10L, 200L));
- // 运营把档位误配到 90% → 按 F03a 的 max_rate_percent=70 封顶
- when(cfReferralService.getTeamAnnualPpoints(10L, 8)).thenReturn(10000);
- when(cfReferralService.matchDirectSalesTier(10000)).thenReturn(directTier("钻石", 10000, 90));
- when(cfBalanceService.earnByRule(eq(memberIdOf(10L)), eq("F03a"), eq(ORDER_ID), any()))
- .thenReturn(earnResult(70, false));
- cfCommissionService.settle(ORDER_ID, "product", BUYER_ID, BUYER_FAMILY, 10000, PRODUCT_ID);
- ArgumentCaptor<Map<String, Object>> captor = ArgumentCaptor.forClass(Map.class);
- verify(cfBalanceService).earnByRule(eq(memberIdOf(10L)), eq("F03a"), eq(ORDER_ID), captor.capture());
- assertEquals(70, captor.getValue().get("rate_percent"));
- }
- @Test
- void settle_无匹配档位_不发放销售奖() {
- mockReferralChain(ref(10L, 1));
- when(userMapper.selectById(10L)).thenReturn(user(10L, 200L));
- when(cfReferralService.getTeamAnnualPpoints(10L, 8)).thenReturn(99);
- when(cfReferralService.matchDirectSalesTier(99)).thenReturn(null);
- cfCommissionService.settle(ORDER_ID, "product", BUYER_ID, BUYER_FAMILY, 10000, PRODUCT_ID);
- verify(cfBalanceService, never()).earnByRule(anyLong(), anyString(), anyLong(), any());
- }
- @Test
- void settle_落P点消费日志_基数与订单对应() {
- mockReferralChain(ref(10L, 1));
- when(userMapper.selectById(10L)).thenReturn(user(10L, 200L));
- when(cfReferralService.getTeamAnnualPpoints(10L, 8)).thenReturn(100);
- when(cfReferralService.matchDirectSalesTier(100)).thenReturn(directTier("青铜", 100, 10));
- when(cfBalanceService.earnByRule(anyLong(), anyString(), anyLong(), any()))
- .thenReturn(earnResult(10, false));
- cfCommissionService.settle(ORDER_ID, "product", BUYER_ID, BUYER_FAMILY, 10000, PRODUCT_ID);
- ArgumentCaptor<PpointConsumptionLog> captor = ArgumentCaptor.forClass(PpointConsumptionLog.class);
- verify(ppointConsumptionLogMapper).insert(captor.capture());
- PpointConsumptionLog log = captor.getValue();
- assertEquals(BUYER_ID, log.getUserId());
- assertEquals(ORDER_ID, log.getOrderId());
- assertEquals("product", log.getOrderType());
- assertEquals(PRODUCT_ID, log.getProductId());
- assertEquals(10000, log.getAmountCent());
- assertEquals(100, log.getPpoints());
- assertNotNull(log.getCreatedAt());
- }
- @Test
- void settle_F03a发放_自动创建感恩记录() {
- mockReferralChain(ref(10L, 1));
- when(userMapper.selectById(10L)).thenReturn(user(10L, 200L));
- when(userMapper.selectById(BUYER_ID)).thenReturn(user(BUYER_ID, BUYER_FAMILY));
- when(cfReferralService.getTeamAnnualPpoints(10L, 8)).thenReturn(100);
- when(cfReferralService.matchDirectSalesTier(100)).thenReturn(directTier("青铜", 100, 10));
- when(cfBalanceService.earnByRule(eq(memberIdOf(10L)), eq("F03a"), eq(ORDER_ID), any()))
- .thenReturn(earnResult(10, false));
- cfCommissionService.settle(ORDER_ID, "product", BUYER_ID, BUYER_FAMILY, 10000, PRODUCT_ID);
- verify(octopusEffectRecordMapper).insert(any());
- verify(octopusEffectKeyPersonMapper).insert(any());
- }
- @Test
- void settle_幂等命中_不重复创建感恩记录() {
- mockReferralChain(ref(10L, 1));
- when(userMapper.selectById(10L)).thenReturn(user(10L, 200L));
- when(userMapper.selectById(BUYER_ID)).thenReturn(user(BUYER_ID, BUYER_FAMILY));
- when(cfReferralService.getTeamAnnualPpoints(10L, 8)).thenReturn(100);
- when(cfReferralService.matchDirectSalesTier(100)).thenReturn(directTier("青铜", 100, 10));
- // 幂等命中:earned=true 且 duplicated=true
- when(cfBalanceService.earnByRule(eq(memberIdOf(10L)), eq("F03a"), eq(ORDER_ID), any()))
- .thenReturn(earnResult(10, true));
- cfCommissionService.settle(ORDER_ID, "product", BUYER_ID, BUYER_FAMILY, 10000, PRODUCT_ID);
- verify(octopusEffectRecordMapper, never()).insert(any());
- verify(octopusEffectKeyPersonMapper, never()).insert(any());
- }
- @Test
- void settleReferrerOnly_只发销售奖_不返买家CF() {
- mockReferralChain(ref(10L, 1));
- when(userMapper.selectById(10L)).thenReturn(user(10L, 200L));
- when(cfReferralService.getTeamAnnualPpoints(10L, 8)).thenReturn(100);
- when(cfReferralService.matchDirectSalesTier(100)).thenReturn(directTier("青铜", 100, 10));
- when(cfBalanceService.earnByRule(anyLong(), anyString(), anyLong(), any()))
- .thenReturn(earnResult(10, false));
- cfCommissionService.settleReferrerOnly(ORDER_ID, "membership", BUYER_ID, BUYER_FAMILY, 10000);
- verify(platformPointsService, never()).earn(anyLong(), org.mockito.ArgumentMatchers.anyInt(),
- anyString(), any(), anyString());
- verify(cfBalanceService).earnByRule(eq(memberIdOf(10L)), eq("F03a"), eq(ORDER_ID), any());
- // 非商品订单基数:100 元 × 1000bps / 10000 = 10 P 点
- ArgumentCaptor<Map<String, Object>> captor = ArgumentCaptor.forClass(Map.class);
- verify(cfBalanceService).earnByRule(eq(memberIdOf(10L)), eq("F03a"), eq(ORDER_ID), captor.capture());
- assertEquals(10, captor.getValue().get("base_ppoints"));
- }
- @Test
- void settle_无推荐链_不发放也不报错() {
- mockReferralChain();
- cfCommissionService.settle(ORDER_ID, "product", BUYER_ID, BUYER_FAMILY, 10000, PRODUCT_ID);
- verify(cfBalanceService, never()).earnByRule(anyLong(), anyString(), anyLong(), any());
- assertTrue(true);
- }
- }
|