liyong
10 天以前 450bcae3cfffe9923dc09dea2a4e89312bb373d7
yudao-module-mall/yudao-module-trade/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordServiceImplTest.java
@@ -1,36 +1,42 @@
package cn.iocoder.yudao.module.trade.service.brokerage;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.NumberUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageRecordMapper;
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import java.math.RoundingMode;
import static cn.hutool.core.util.RandomUtil.randomEle;
import static cn.hutool.core.util.RandomUtil.randomInt;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomInteger;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
// TODO @芋艿:单测后续看看
/**
 * {@link BrokerageRecordServiceImpl} 的单元测试类
 *
 * @author owen
 */
@Disabled // TODO 芋艿:后续 fix 补充的单测
@Import(BrokerageRecordServiceImpl.class)
public class BrokerageRecordServiceImplTest extends BaseDbUnitTest {
@@ -43,31 +49,43 @@
    private TradeConfigService tradeConfigService;
    @MockitoBean
    private BrokerageUserService brokerageUserService;
    @MockitoBean
    private ProductSpuApi productSpuApi;
    @MockitoBean
    private ProductSkuApi productSkuApi;
    @Test
    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
    public void testGetBrokerageRecordPage() {
        // mock 数据
        BrokerageRecordDO dbBrokerageRecord = randomPojo(BrokerageRecordDO.class, o -> { // 等会查询到
            o.setUserId(null);
            o.setBizType(null);
            o.setStatus(null);
            o.setCreateTime(null);
            o.setUserId(1L);
            o.setBizType(BrokerageRecordBizTypeEnum.ORDER.getType());
            o.setStatus(BrokerageRecordStatusEnum.SETTLEMENT.getStatus());
            o.setSourceUserLevel(1);
            o.setSourceUserId(100L);
            o.setCreateTime(buildTime(2023, 2, 10));
            o.setDeleted(false);
        });
        brokerageRecordMapper.insert(dbBrokerageRecord);
        // 测试 userId 不匹配
        brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setUserId(null)));
        brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setUserId(2L)));
        // 测试 bizType 不匹配
        brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setBizType(null)));
        brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord,
                o -> o.setBizType(BrokerageRecordBizTypeEnum.WITHDRAW.getType())));
        // 测试 status 不匹配
        brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setStatus(null)));
        brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord,
                o -> o.setStatus(BrokerageRecordStatusEnum.CANCEL.getStatus())));
        // 测试 sourceUserLevel 不匹配
        brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setSourceUserLevel(2)));
        // 测试 createTime 不匹配
        brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setCreateTime(null)));
        brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord,
                o -> o.setCreateTime(buildTime(2023, 3, 1))));
        // 准备参数
        BrokerageRecordPageReqVO reqVO = new BrokerageRecordPageReqVO();
        reqVO.setUserId(null);
        reqVO.setBizType(null);
        reqVO.setStatus(null);
        reqVO.setUserId(1L);
        reqVO.setBizType(BrokerageRecordBizTypeEnum.ORDER.getType());
        reqVO.setStatus(BrokerageRecordStatusEnum.SETTLEMENT.getStatus());
        reqVO.setSourceUserLevel(1);
        reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
        // 调用
@@ -81,37 +99,159 @@
    @Test
    public void testCalculatePrice_useFixedPrice() {
        // mock 数据
        Integer payPrice = randomInteger();
        Integer percent = randomInt(1, 101);
        Integer fixedPrice = randomInt();
        Integer payPrice = 1000;
        Integer percent = 10;
        Integer fixedPrice = 88;
        // 调用
        int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice);
        // 断言
        assertEquals(brokerage, fixedPrice);
        assertEquals(fixedPrice, brokerage);
    }
    @Test
    public void testCalculatePrice_usePercent() {
        // mock 数据
        Integer payPrice = randomInteger();
        Integer percent = randomInt(1, 101);
        Integer fixedPrice = randomEle(new Integer[]{0, null});
        System.out.println("fixedPrice=" + fixedPrice);
        // mock 数据:fixedPrice 为 null 时,按比例计算佣金
        Integer payPrice = 1000;
        Integer percent = 10;
        Integer fixedPrice = null;
        // 调用
        int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice);
        // 断言
        assertEquals(brokerage, NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue());
        assertEquals(NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0,
                RoundingMode.DOWN).intValue(), brokerage);
    }
    @Test
    public void testCalculatePrice_fixedPriceIsZero() {
        // mock 数据:fixedPrice 为 0 时,仍使用固定佣金,不回退到比例计算
        Integer payPrice = 1000;
        Integer percent = 10;
        Integer fixedPrice = 0;
        // 调用
        int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice);
        // 断言
        assertEquals(0, brokerage);
    }
    @Test
    public void testCalculatePrice_equalsZero() {
        // mock 数据
        // mock 数据:三个参数均无效时,返回 0
        Integer payPrice = null;
        Integer percent = null;
        Integer fixedPrice = null;
        // 调用
        int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice);
        // 断言
        assertEquals(brokerage, 0);
        assertEquals(0, brokerage);
    }
    @Test
    public void testCalculateProductBrokeragePrice_globalPercent() {
        // mock:分销功能已开启,比例 10%,当前用户有分销资格
        TradeConfigDO tradeConfig = new TradeConfigDO();
        tradeConfig.setBrokerageEnabled(true);
        tradeConfig.setBrokerageFirstPercent(10);
        when(tradeConfigService.getTradeConfig()).thenReturn(tradeConfig);
        when(brokerageUserService.getUserBrokerageEnabled(100L)).thenReturn(true);
        // mock:商品未开启独立分销(subCommissionType = false),SKU 售价 1000 分
        ProductSpuRespDTO spu = new ProductSpuRespDTO();
        spu.setSubCommissionType(false);
        when(productSpuApi.getSpu(1L)).thenReturn(spu);
        ProductSkuRespDTO sku = new ProductSkuRespDTO();
        sku.setPrice(1000);
        when(productSkuApi.getSkuListBySpuId(ListUtil.of(1L))).thenReturn(ListUtil.of(sku));
        // 调用
        AppBrokerageProductPriceRespVO result = brokerageRecordService.calculateProductBrokeragePrice(100L, 1L);
        // 断言:按 10% 比例计算,1000 * 10% = 100 分(向下取整)
        assertTrue(result.getEnabled());
        assertEquals(100, result.getBrokerageMinPrice());
        assertEquals(100, result.getBrokerageMaxPrice());
    }
    @Test
    public void testCalculateProductBrokeragePrice_subCommissionZeroFixed() {
        // mock:分销功能已开启,比例 10%,当前用户有分销资格
        TradeConfigDO tradeConfig = new TradeConfigDO();
        tradeConfig.setBrokerageEnabled(true);
        tradeConfig.setBrokerageFirstPercent(10);
        when(tradeConfigService.getTradeConfig()).thenReturn(tradeConfig);
        when(brokerageUserService.getUserBrokerageEnabled(100L)).thenReturn(true);
        // mock:商品开启独立分销(subCommissionType = true),SKU 固定佣金为 0(商家主动设置)
        ProductSpuRespDTO spu = new ProductSpuRespDTO();
        spu.setSubCommissionType(true);
        when(productSpuApi.getSpu(2L)).thenReturn(spu);
        ProductSkuRespDTO sku = new ProductSkuRespDTO();
        sku.setPrice(1000);
        sku.setFirstBrokeragePrice(0);
        when(productSkuApi.getSkuListBySpuId(ListUtil.of(2L))).thenReturn(ListUtil.of(sku));
        // 调用
        AppBrokerageProductPriceRespVO result = brokerageRecordService.calculateProductBrokeragePrice(100L, 2L);
        // 断言:独立分销固定佣金为 0,应返回 0,不得回退到全局比例
        assertTrue(result.getEnabled());
        assertEquals(0, result.getBrokerageMinPrice());
        assertEquals(0, result.getBrokerageMaxPrice());
    }
    @Test
    public void testCalculateProductBrokeragePrice_subCommissionNullFixed() {
        // mock:分销功能已开启,比例 10%,当前用户有分销资格
        TradeConfigDO tradeConfig = new TradeConfigDO();
        tradeConfig.setBrokerageEnabled(true);
        tradeConfig.setBrokerageFirstPercent(10);
        when(tradeConfigService.getTradeConfig()).thenReturn(tradeConfig);
        when(brokerageUserService.getUserBrokerageEnabled(100L)).thenReturn(true);
        // mock:商品开启独立分销,其中一个 SKU 固定佣金未配置
        ProductSpuRespDTO spu = new ProductSpuRespDTO();
        spu.setSubCommissionType(true);
        when(productSpuApi.getSpu(3L)).thenReturn(spu);
        ProductSkuRespDTO nullBrokerageSku = new ProductSkuRespDTO();
        nullBrokerageSku.setPrice(1000);
        nullBrokerageSku.setFirstBrokeragePrice(null);
        ProductSkuRespDTO fixedBrokerageSku = new ProductSkuRespDTO();
        fixedBrokerageSku.setPrice(2000);
        fixedBrokerageSku.setFirstBrokeragePrice(200);
        when(productSkuApi.getSkuListBySpuId(ListUtil.of(3L))).thenReturn(ListUtil.of(nullBrokerageSku, fixedBrokerageSku));
        // 调用
        AppBrokerageProductPriceRespVO result = brokerageRecordService.calculateProductBrokeragePrice(100L, 3L);
        // 断言:独立分销固定佣金为空时按 0 处理,避免比较最小/最大佣金时报错
        assertTrue(result.getEnabled());
        assertEquals(0, result.getBrokerageMinPrice());
        assertEquals(200, result.getBrokerageMaxPrice());
    }
    @Test
    public void testCalculateProductBrokeragePrice_subCommissionEmptySkuList() {
        // mock:分销功能已开启,比例 10%,当前用户有分销资格
        TradeConfigDO tradeConfig = new TradeConfigDO();
        tradeConfig.setBrokerageEnabled(true);
        tradeConfig.setBrokerageFirstPercent(10);
        when(tradeConfigService.getTradeConfig()).thenReturn(tradeConfig);
        when(brokerageUserService.getUserBrokerageEnabled(100L)).thenReturn(true);
        // mock:商品开启独立分销,但查询不到 SKU 固定佣金
        ProductSpuRespDTO spu = new ProductSpuRespDTO();
        spu.setSubCommissionType(true);
        when(productSpuApi.getSpu(4L)).thenReturn(spu);
        when(productSkuApi.getSkuListBySpuId(ListUtil.of(4L))).thenReturn(ListUtil.of());
        // 调用
        AppBrokerageProductPriceRespVO result = brokerageRecordService.calculateProductBrokeragePrice(100L, 4L);
        // 断言:独立分销没有固定佣金时,不回退到全局比例
        assertTrue(result.getEnabled());
        assertEquals(0, result.getBrokerageMinPrice());
        assertEquals(0, result.getBrokerageMaxPrice());
    }
}