初始化提交

This commit is contained in:
YangJ
2024-03-20 09:42:17 +08:00
commit 72f30209cf
3705 changed files with 285827 additions and 0 deletions

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kd100.Kd100ExpressClient;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* {@link Kd100ExpressClient} 的集成测试
*
* @author jason
*/
@Slf4j
public class Kd100ExpressClientIntegrationTest {
private Kd100ExpressClient client;
@BeforeEach
public void init() {
RestTemplate restTemplate = new RestTemplateBuilder().build();
TradeExpressProperties.Kd100Config config = new TradeExpressProperties.Kd100Config()
.setKey("pLXUGAwK5305")
.setCustomer("E77DF18BE109F454A5CD319E44BF5177");
client = new Kd100ExpressClient(restTemplate, config);
}
@Test
@Disabled("集成测试,暂时忽略")
public void testGetExpressTrackList() {
ExpressTrackQueryReqDTO reqDTO = new ExpressTrackQueryReqDTO();
reqDTO.setExpressCode("STO");
reqDTO.setLogisticsNo("773220402764314");
List<ExpressTrackRespDTO> tracks = client.getExpressTrackList(reqDTO);
System.out.println(JsonUtils.toJsonPrettyString(tracks));
}
}

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.trade.framework.delivery.config.TradeExpressProperties;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.impl.kdniao.KdNiaoExpressClient;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* {@link KdNiaoExpressClient} 的集成测试
*
* @author jason
*/
@Slf4j
public class KdNiaoExpressClientIntegrationTest {
private KdNiaoExpressClient client;
@BeforeEach
public void init() {
RestTemplate restTemplate = new RestTemplateBuilder().build();
TradeExpressProperties.KdNiaoConfig config = new TradeExpressProperties.KdNiaoConfig()
.setApiKey("cb022f1e-48f1-4c4a-a723-9001ac9676b8")
.setBusinessId("1809751");
client = new KdNiaoExpressClient(restTemplate, config);
}
@Test
@Disabled("集成测试,暂时忽略")
public void testGetExpressTrackList() {
ExpressTrackQueryReqDTO reqDTO = new ExpressTrackQueryReqDTO();
reqDTO.setExpressCode("STO");
reqDTO.setLogisticsNo("777168349863987");
List<ExpressTrackRespDTO> tracks = client.getExpressTrackList(reqDTO);
System.out.println(JsonUtils.toJsonPrettyString(tracks));
}
}

View File

@ -0,0 +1,158 @@
package cn.iocoder.yudao.module.trade.service.aftersale;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO;
import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.AfterSaleLogMapper;
import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.AfterSaleMapper;
import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleStatusEnum;
import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleTypeEnum;
import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleWayEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.time.LocalDateTime;
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.randomPojo;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
* {@link AfterSaleService} 的单元测试
*
* @author 芋道源码
*/
@Disabled // TODO 芋艿:后续 fix 补充的单测
@Import(AfterSaleServiceImpl.class)
public class AfterSaleServiceTest extends BaseDbUnitTest {
@Resource
private AfterSaleServiceImpl tradeAfterSaleService;
@Resource
private AfterSaleMapper tradeAfterSaleMapper;
@Resource
private AfterSaleLogMapper tradeAfterSaleLogMapper;
@MockBean
private TradeOrderUpdateService tradeOrderUpdateService;
@Resource
private TradeOrderQueryService tradeOrderQueryService;
@MockBean
private PayRefundApi payRefundApi;
@MockBean
private TradeOrderProperties tradeOrderProperties;
@Test
public void testCreateAfterSale() {
// 准备参数
Long userId = 1024L;
AppAfterSaleCreateReqVO createReqVO = new AppAfterSaleCreateReqVO()
.setOrderItemId(1L).setRefundPrice(100).setWay(AfterSaleWayEnum.RETURN_AND_REFUND.getWay())
.setApplyReason("退钱").setApplyDescription("快退")
.setApplyPicUrls(asList("https://www.baidu.com/1.png", "https://www.baidu.com/2.png"));
// mock 方法(交易订单项)
TradeOrderItemDO orderItem = randomPojo(TradeOrderItemDO.class, o -> {
o.setOrderId(111L).setUserId(userId).setPayPrice(200);
o.setAfterSaleStatus(TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
});
when(tradeOrderQueryService.getOrderItem(eq(1024L), eq(1L)))
.thenReturn(orderItem);
// mock 方法(交易订单)
TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> o.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus())
.setNo("202211301234"));
when(tradeOrderQueryService.getOrder(eq(1024L), eq(111L))).thenReturn(order);
// 调用
Long afterSaleId = tradeAfterSaleService.createAfterSale(userId, createReqVO);
// 断言TradeAfterSaleDO
AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(afterSaleId);
assertNotNull(afterSale.getNo());
assertEquals(afterSale.getStatus(), AfterSaleStatusEnum.APPLY.getStatus());
assertEquals(afterSale.getType(), AfterSaleTypeEnum.IN_SALE.getType());
assertPojoEquals(afterSale, createReqVO);
assertEquals(afterSale.getUserId(), 1024L);
assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime");
assertEquals(afterSale.getOrderNo(), "202211301234");
assertNull(afterSale.getPayRefundId());
assertNull(afterSale.getRefundTime());
assertNull(afterSale.getLogisticsId());
assertNull(afterSale.getLogisticsNo());
assertNull(afterSale.getDeliveryTime());
assertNull(afterSale.getReceiveReason());
// 断言TradeAfterSaleLogDO
AfterSaleLogDO afterSaleLog = tradeAfterSaleLogMapper.selectList().get(0);
assertEquals(afterSaleLog.getUserId(), userId);
assertEquals(afterSaleLog.getUserType(), UserTypeEnum.MEMBER.getValue());
assertEquals(afterSaleLog.getAfterSaleId(), afterSaleId);
assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime");
assertEquals(afterSaleLog.getContent(), AfterSaleStatusEnum.APPLY.getContent());
}
@Test
public void testGetAfterSalePage() {
// mock 数据
AfterSaleDO dbAfterSale = randomPojo(AfterSaleDO.class, o -> { // 等会查询到
o.setNo("202211190847450020500077");
o.setStatus(AfterSaleStatusEnum.APPLY.getStatus());
o.setWay(AfterSaleWayEnum.RETURN_AND_REFUND.getWay());
o.setType(AfterSaleTypeEnum.IN_SALE.getType());
o.setOrderNo("202211190847450020500011");
o.setSpuName("芋艿");
o.setCreateTime(buildTime(2022, 1, 15));
});
tradeAfterSaleMapper.insert(dbAfterSale);
// 测试 no 不匹配
tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setNo("202211190847450020500066")));
// 测试 status 不匹配
tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setStatus(AfterSaleStatusEnum.SELLER_REFUSE.getStatus())));
// 测试 way 不匹配
tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setWay(AfterSaleWayEnum.REFUND.getWay())));
// 测试 type 不匹配
tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setType(AfterSaleTypeEnum.AFTER_SALE.getType())));
// 测试 orderNo 不匹配
tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setOrderNo("202211190847450020500022")));
// 测试 spuName 不匹配
tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setSpuName("土豆")));
// 测试 createTime 不匹配
tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setCreateTime(buildTime(2022, 1, 20))));
// 准备参数
AfterSalePageReqVO reqVO = new AfterSalePageReqVO();
reqVO.setNo("20221119084745002050007");
reqVO.setStatus(AfterSaleStatusEnum.APPLY.getStatus());
reqVO.setWay(AfterSaleWayEnum.RETURN_AND_REFUND.getWay());
reqVO.setType(AfterSaleTypeEnum.IN_SALE.getType());
reqVO.setOrderNo("20221119084745002050001");
reqVO.setSpuName("");
reqVO.setCreateTime(new LocalDateTime[]{buildTime(2022, 1, 1), buildTime(2022, 1, 16)});
// 调用
PageResult<AfterSaleDO> pageResult = tradeAfterSaleService.getAfterSalePage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbAfterSale, pageResult.getList().get(0));
}
}

View File

@ -0,0 +1,117 @@
package cn.iocoder.yudao.module.trade.service.brokerage;
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.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageRecordMapper;
import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
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.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;
// TODO @芋艿:单测后续看看
/**
* {@link BrokerageRecordServiceImpl} 的单元测试类
*
* @author owen
*/
@Disabled // TODO 芋艿:后续 fix 补充的单测
@Import(BrokerageRecordServiceImpl.class)
public class BrokerageRecordServiceImplTest extends BaseDbUnitTest {
@Resource
private BrokerageRecordServiceImpl brokerageRecordService;
@Resource
private BrokerageRecordMapper brokerageRecordMapper;
@MockBean
private TradeConfigService tradeConfigService;
@MockBean
private BrokerageUserService brokerageUserService;
@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);
});
brokerageRecordMapper.insert(dbBrokerageRecord);
// 测试 userId 不匹配
brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setUserId(null)));
// 测试 bizType 不匹配
brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setBizType(null)));
// 测试 status 不匹配
brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setStatus(null)));
// 测试 createTime 不匹配
brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setCreateTime(null)));
// 准备参数
BrokerageRecordPageReqVO reqVO = new BrokerageRecordPageReqVO();
reqVO.setUserId(null);
reqVO.setBizType(null);
reqVO.setStatus(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbBrokerageRecord, pageResult.getList().get(0));
}
@Test
public void testCalculatePrice_useFixedPrice() {
// mock 数据
Integer payPrice = randomInteger();
Integer percent = randomInt(1, 101);
Integer fixedPrice = randomInt();
// 调用
int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice);
// 断言
assertEquals(brokerage, fixedPrice);
}
@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);
// 调用
int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice);
// 断言
assertEquals(brokerage, NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue());
}
@Test
public void testCalculatePrice_equalsZero() {
// mock 数据
Integer payPrice = null;
Integer percent = null;
Integer fixedPrice = null;
// 调用
int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice);
// 断言
assertEquals(brokerage, 0);
}
}

View File

@ -0,0 +1,66 @@
package cn.iocoder.yudao.module.trade.service.brokerage;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserPageReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageUserMapper;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
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.randomPojo;
import static org.junit.jupiter.api.Assertions.assertEquals;
// TODO @芋艿:单测后续看看
/**
* {@link BrokerageUserServiceImpl} 的单元测试类
*
* @author owen
*/
@Disabled // TODO 芋艿:后续 fix 补充的单测
@Import(BrokerageUserServiceImpl.class)
public class BrokerageUserServiceImplTest extends BaseDbUnitTest {
@Resource
private BrokerageUserServiceImpl brokerageUserService;
@Resource
private BrokerageUserMapper brokerageUserMapper;
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetBrokerageUserPage() {
// mock 数据
BrokerageUserDO dbBrokerageUser = randomPojo(BrokerageUserDO.class, o -> { // 等会查询到
o.setBindUserId(null);
o.setBrokerageEnabled(null);
o.setCreateTime(null);
});
brokerageUserMapper.insert(dbBrokerageUser);
// 测试 brokerageUserId 不匹配
brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setBindUserId(null)));
// 测试 brokerageEnabled 不匹配
brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setBrokerageEnabled(null)));
// 测试 createTime 不匹配
brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setCreateTime(null)));
// 准备参数
BrokerageUserPageReqVO reqVO = new BrokerageUserPageReqVO();
reqVO.setBindUserId(null);
reqVO.setBrokerageEnabled(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<BrokerageUserDO> pageResult = brokerageUserService.getBrokerageUserPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbBrokerageUser, pageResult.getList().get(0));
}
}

View File

@ -0,0 +1,118 @@
package cn.iocoder.yudao.module.trade.service.brokerage;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageWithdrawMapper;
import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import javax.validation.Validator;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
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.randomPojo;
import static org.junit.jupiter.api.Assertions.assertEquals;
// TODO 芋艿:后续 review
/**
* {@link BrokerageWithdrawServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Disabled // TODO 芋艿:后续 fix 补充的单测
@Import(BrokerageWithdrawServiceImpl.class)
public class BrokerageWithdrawServiceImplTest extends BaseDbUnitTest {
@Resource
private BrokerageWithdrawServiceImpl brokerageWithdrawService;
@Resource
private BrokerageWithdrawMapper brokerageWithdrawMapper;
@MockBean
private BrokerageRecordService brokerageRecordService;
@MockBean
private BrokerageUserService brokerageUserService;
@MockBean
private TradeConfigService tradeConfigService;
@MockBean
private NotifyMessageSendApi notifyMessageSendApi;
@Resource
private Validator validator;
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetBrokerageWithdrawPage() {
// mock 数据
BrokerageWithdrawDO dbBrokerageWithdraw = randomPojo(BrokerageWithdrawDO.class, o -> { // 等会查询到
o.setUserId(null);
o.setType(null);
o.setName(null);
o.setAccountNo(null);
o.setBankName(null);
o.setStatus(null);
o.setCreateTime(null);
});
brokerageWithdrawMapper.insert(dbBrokerageWithdraw);
// 测试 userId 不匹配
brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setUserId(null)));
// 测试 type 不匹配
brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setType(null)));
// 测试 name 不匹配
brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setName(null)));
// 测试 accountNo 不匹配
brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setAccountNo(null)));
// 测试 bankName 不匹配
brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setBankName(null)));
// 测试 status 不匹配
brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setStatus(null)));
// 测试 auditReason 不匹配
brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setAuditReason(null)));
// 测试 auditTime 不匹配
brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setAuditTime(null)));
// 测试 remark 不匹配
brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setRemark(null)));
// 测试 createTime 不匹配
brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setCreateTime(null)));
// 准备参数
BrokerageWithdrawPageReqVO reqVO = new BrokerageWithdrawPageReqVO();
reqVO.setUserId(null);
reqVO.setType(null);
reqVO.setName(null);
reqVO.setAccountNo(null);
reqVO.setBankName(null);
reqVO.setStatus(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbBrokerageWithdraw, pageResult.getList().get(0));
}
@Test
public void testCalculateFeePrice() {
Integer withdrawPrice = 100;
// 测试手续费比例未设置
Integer percent = null;
assertEquals(brokerageWithdrawService.calculateFeePrice(withdrawPrice, percent), 0);
// 测试手续费给为0
percent = 0;
assertEquals(brokerageWithdrawService.calculateFeePrice(withdrawPrice, percent), 0);
// 测试手续费
percent = 1;
assertEquals(brokerageWithdrawService.calculateFeePrice(withdrawPrice, percent), 1);
}
}

View File

@ -0,0 +1,299 @@
package cn.iocoder.yudao.module.trade.service.order;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.time.Duration;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
* {@link TradeOrderUpdateServiceImpl} 的单元测试类
*
* @author LeeYan9
* @since 2022-09-07
*/
@Disabled // TODO 芋艿:后续 fix 补充的单测
@Import({TradeOrderUpdateServiceImpl.class, TradeOrderConfig.class})
public class TradeOrderUpdateServiceTest extends BaseDbUnitTest {
@Resource
private TradeOrderUpdateServiceImpl tradeOrderUpdateService;
@Resource
private TradeOrderMapper tradeOrderMapper;
@Resource
private TradeOrderItemMapper tradeOrderItemMapper;
@MockBean
private MemberUserApi memberUserApi;
@MockBean
private ProductSpuApi productSpuApi;
@MockBean
private ProductSkuApi productSkuApi;
// @MockBean
// private PriceApi priceApi;
@MockBean
private PayOrderApi payOrderApi;
@MockBean
private MemberAddressApi addressApi;
@MockBean
private CouponApi couponApi;
@MockBean
private TradeOrderProperties tradeOrderProperties;
@BeforeEach
public void setUp() {
when(tradeOrderProperties.getAppId()).thenReturn(888L);
when(tradeOrderProperties.getPayExpireTime()).thenReturn(Duration.ofDays(1));
}
// @Test
// public void testCreateTradeOrder_success() {
// // 准备参数
// Long userId = 100L;
// String userIp = "127.0.0.1";
//// AppTradeOrderCreateReqVO reqVO = new AppTradeOrderCreateReqVO()
//// .setAddressId(10L).setCouponId(101L).setRemark("我是备注").setFromCart(true)
//// .setItems(Arrays.asList(new AppTradeOrderCreateReqVO.Item().setSkuId(1L).setCount(3),
//// new AppTradeOrderCreateReqVO.Item().setSkuId(2L).setCount(4)));
// AppTradeOrderCreateReqVO reqVO = null;
// // TODO 芋艿:重新高下
// // mock 方法(商品 SKU 检查)
// ProductSkuRespDTO sku01 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(1L).setSpuId(11L)
// .setPrice(50).setStock(100)
// .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(111L).setValueId(222L))));
// ProductSkuRespDTO sku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(2L).setSpuId(21L)
// .setPrice(20).setStock(50))
// .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(333L).setValueId(444L)));
// when(productSkuApi.getSkuList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(sku01, sku02));
// // mock 方法(商品 SPU 检查)
// ProductSpuRespDTO spu01 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(11L)
// .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()).setName("商品 1"));
// ProductSpuRespDTO spu02 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(21L)
// .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()));
// when(productSpuApi.getSpuList(eq(asSet(11L, 21L)))).thenReturn(Arrays.asList(spu01, spu02));
// // mock 方法(用户收件地址的校验)
// MemberAddressRespDTO addressRespDTO = new MemberAddressRespDTO().setId(10L).setUserId(userId).setName("芋艿")
// .setMobile("15601691300").setAreaId(3306).setDetailAddress("土豆村");
// when(addressApi.getAddress(eq(10L), eq(userId))).thenReturn(addressRespDTO);
// // mock 方法(价格计算)
// PriceCalculateRespDTO.OrderItem priceOrderItem01 = new PriceCalculateRespDTO.OrderItem()
// .setSpuId(11L).setSkuId(1L).setCount(3).setOriginalPrice(150).setOriginalUnitPrice(50)
// .setDiscountPrice(20).setPayPrice(130).setOrderPartPrice(7).setOrderDividePrice(35);
// PriceCalculateRespDTO.OrderItem priceOrderItem02 = new PriceCalculateRespDTO.OrderItem()
// .setSpuId(21L).setSkuId(2L).setCount(4).setOriginalPrice(80).setOriginalUnitPrice(20)
// .setDiscountPrice(40).setPayPrice(40).setOrderPartPrice(15).setOrderDividePrice(25);
// PriceCalculateRespDTO.Order priceOrder = new PriceCalculateRespDTO.Order()
// .setTotalPrice(230).setDiscountPrice(0).setCouponPrice(30)
// .setPointPrice(10).setDeliveryPrice(20).setPayPrice(80).setCouponId(101L).setCouponPrice(30)
// .setItems(Arrays.asList(priceOrderItem01, priceOrderItem02));
// when(priceApi.calculatePrice(argThat(priceCalculateReqDTO -> {
// assertEquals(priceCalculateReqDTO.getUserId(), 100L);
// assertEquals(priceCalculateReqDTO.getCouponId(), 101L);
// assertEquals(priceCalculateReqDTO.getItems().get(0).getSkuId(), 1L);
// assertEquals(priceCalculateReqDTO.getItems().get(0).getCount(), 3);
// assertEquals(priceCalculateReqDTO.getItems().get(1).getSkuId(), 2L);
// assertEquals(priceCalculateReqDTO.getItems().get(1).getCount(), 4);
// return true;
// }))).thenReturn(new PriceCalculateRespDTO().setOrder(priceOrder));
// // mock 方法(创建支付单)
// when(payOrderApi.createOrder(argThat(createReqDTO -> {
// assertEquals(createReqDTO.getAppId(), 888L);
// assertEquals(createReqDTO.getUserIp(), userIp);
// assertNotNull(createReqDTO.getMerchantOrderId()); // 由于 tradeOrderId 后生成,只能校验非空
// assertEquals(createReqDTO.getSubject(), "商品 1 等多件");
// assertNull(createReqDTO.getBody());
// assertEquals(createReqDTO.getPrice(), 80);
// assertNotNull(createReqDTO.getExpireTime());
// return true;
// }))).thenReturn(1000L);
//
// // 调用方法
// TradeOrderDO order = tradeOrderUpdateService.createOrder(userId, userIp, reqVO, null);
// // 断言 TradeOrderDO 订单
// List<TradeOrderDO> tradeOrderDOs = tradeOrderMapper.selectList();
// assertEquals(tradeOrderDOs.size(), 1);
// TradeOrderDO tradeOrderDO = tradeOrderDOs.get(0);
// assertEquals(tradeOrderDO.getId(), order.getId());
// assertNotNull(tradeOrderDO.getNo());
// assertEquals(tradeOrderDO.getType(), TradeOrderTypeEnum.NORMAL.getType());
// assertEquals(tradeOrderDO.getTerminal(), TerminalEnum.H5.getTerminal());
// assertEquals(tradeOrderDO.getUserId(), userId);
// assertEquals(tradeOrderDO.getUserIp(), userIp);
// assertEquals(tradeOrderDO.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus());
// assertEquals(tradeOrderDO.getProductCount(), 7);
// assertNull(tradeOrderDO.getFinishTime());
// assertNull(tradeOrderDO.getCancelTime());
// assertNull(tradeOrderDO.getCancelType());
// assertEquals(tradeOrderDO.getUserRemark(), "我是备注");
// assertNull(tradeOrderDO.getRemark());
// assertFalse(tradeOrderDO.getPayStatus());
// assertNull(tradeOrderDO.getPayTime());
// assertEquals(tradeOrderDO.getTotalPrice(), 230);
// assertEquals(tradeOrderDO.getDiscountPrice(), 0);
// assertEquals(tradeOrderDO.getAdjustPrice(), 0);
// assertEquals(tradeOrderDO.getPayPrice(), 80);
// assertEquals(tradeOrderDO.getPayOrderId(), 1000L);
// assertNull(tradeOrderDO.getPayChannelCode());
// assertNull(tradeOrderDO.getLogisticsId());
// assertNull(tradeOrderDO.getDeliveryTime());
// assertNull(tradeOrderDO.getReceiveTime());
// assertEquals(tradeOrderDO.getReceiverName(), "芋艿");
// assertEquals(tradeOrderDO.getReceiverMobile(), "15601691300");
// assertEquals(tradeOrderDO.getReceiverAreaId(), 3306);
// assertEquals(tradeOrderDO.getReceiverDetailAddress(), "土豆村");
// assertEquals(tradeOrderDO.getRefundStatus(), TradeOrderRefundStatusEnum.NONE.getStatus());
// assertEquals(tradeOrderDO.getRefundPrice(), 0);
// assertEquals(tradeOrderDO.getCouponPrice(), 30);
// assertEquals(tradeOrderDO.getPointPrice(), 10);
// // 断言 TradeOrderItemDO 订单(第 1 个)
// List<TradeOrderItemDO> tradeOrderItemDOs = tradeOrderItemMapper.selectList();
// assertEquals(tradeOrderItemDOs.size(), 2);
// TradeOrderItemDO tradeOrderItemDO01 = tradeOrderItemDOs.get(0);
// assertNotNull(tradeOrderItemDO01.getId());
// assertEquals(tradeOrderItemDO01.getUserId(), userId);
// assertEquals(tradeOrderItemDO01.getOrderId(), order.getId());
// assertEquals(tradeOrderItemDO01.getSpuId(), 11L);
// assertEquals(tradeOrderItemDO01.getSkuId(), 1L);
// assertEquals(tradeOrderItemDO01.getProperties().size(), 1);
// assertEquals(tradeOrderItemDO01.getProperties().get(0).getPropertyId(), 111L);
// assertEquals(tradeOrderItemDO01.getProperties().get(0).getValueId(), 222L);
// //assertEquals(tradeOrderItemDO01.getSpuName(), sku01.getSpuName()); TODO 找不到spuName
// assertEquals(tradeOrderItemDO01.getPicUrl(), sku01.getPicUrl());
// assertEquals(tradeOrderItemDO01.getCount(), 3);
//// assertEquals(tradeOrderItemDO01.getOriginalPrice(), 150);
// assertEquals(tradeOrderItemDO01.getPrice(), 50);
// assertEquals(tradeOrderItemDO01.getDiscountPrice(), 20);
// assertEquals(tradeOrderItemDO01.getPayPrice(), 130);
// assertEquals(tradeOrderItemDO01.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
// // 断言 TradeOrderItemDO 订单(第 2 个)
// TradeOrderItemDO tradeOrderItemDO02 = tradeOrderItemDOs.get(1);
// assertNotNull(tradeOrderItemDO02.getId());
// assertEquals(tradeOrderItemDO02.getUserId(), userId);
// assertEquals(tradeOrderItemDO02.getOrderId(), order.getId());
// assertEquals(tradeOrderItemDO02.getSpuId(), 21L);
// assertEquals(tradeOrderItemDO02.getSkuId(), 2L);
// assertEquals(tradeOrderItemDO02.getProperties().size(), 1);
// assertEquals(tradeOrderItemDO02.getProperties().get(0).getPropertyId(), 333L);
// assertEquals(tradeOrderItemDO02.getProperties().get(0).getValueId(), 444L);
// //assertEquals(tradeOrderItemDO02.getSpuName(), sku02.getSpuName()); TODO 找不到spuName
// assertEquals(tradeOrderItemDO02.getPicUrl(), sku02.getPicUrl());
// assertEquals(tradeOrderItemDO02.getCount(), 4);
//// assertEquals(tradeOrderItemDO02.getOriginalPrice(), 80);
// assertEquals(tradeOrderItemDO02.getPrice(), 20);
// assertEquals(tradeOrderItemDO02.getDiscountPrice(), 40);
// assertEquals(tradeOrderItemDO02.getPayPrice(), 40);
// assertEquals(tradeOrderItemDO02.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
// // 校验调用
// verify(productSkuApi).updateSkuStock(argThat(updateStockReqDTO -> {
// assertEquals(updateStockReqDTO.getItems().size(), 2);
// assertEquals(updateStockReqDTO.getItems().get(0).getId(), 1L);
// assertEquals(updateStockReqDTO.getItems().get(0).getIncrCount(), 3);
// assertEquals(updateStockReqDTO.getItems().get(1).getId(), 2L);
// assertEquals(updateStockReqDTO.getItems().get(1).getIncrCount(), 4);
// return true;
// }));
// verify(couponApi).useCoupon(argThat(reqDTO -> {
// assertEquals(reqDTO.getId(), reqVO.getCouponId());
// assertEquals(reqDTO.getUserId(), userId);
// assertEquals(reqDTO.getOrderId(), order.getId());
// return true;
// }));
// }
@Test
public void testUpdateOrderPaid() {
// mock 数据TradeOrder
TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> {
o.setId(1L).setStatus(TradeOrderStatusEnum.UNPAID.getStatus());
o.setPayOrderId(10L).setPayStatus(false).setPayPrice(100).setPayTime(null);
});
tradeOrderMapper.insert(order);
// 准备参数
Long id = 1L;
Long payOrderId = 10L;
// mock 方法(支付单)
when(payOrderApi.getOrder(eq(10L))).thenReturn(randomPojo(PayOrderRespDTO.class,
o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()).setChannelCode("wx_pub")
.setMerchantOrderId("1")).setPrice(100));
// 调用
tradeOrderUpdateService.updateOrderPaid(id, payOrderId);
// 断言
TradeOrderDO dbOrder = tradeOrderMapper.selectById(id);
assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus());
assertTrue(dbOrder.getPayStatus());
assertNotNull(dbOrder.getPayTime());
assertEquals(dbOrder.getPayChannelCode(), "wx_pub");
}
@Test
public void testDeliveryOrder() {
// mock 数据TradeOrder
TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> {
o.setId(1L).setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus());
o.setLogisticsId(null).setLogisticsNo(null).setDeliveryTime(null);
});
tradeOrderMapper.insert(order);
// 准备参数
TradeOrderDeliveryReqVO deliveryReqVO = new TradeOrderDeliveryReqVO().setId(1L)
.setLogisticsId(10L).setLogisticsNo("100");
// mock 方法(支付单)
// 调用
tradeOrderUpdateService.deliveryOrder(deliveryReqVO);
// 断言
TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L);
assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.DELIVERED.getStatus());
assertPojoEquals(dbOrder, deliveryReqVO);
assertNotNull(dbOrder.getDeliveryTime());
}
@Test
public void testReceiveOrder() {
// mock 数据TradeOrder
TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> {
o.setId(1L).setUserId(10L).setStatus(TradeOrderStatusEnum.DELIVERED.getStatus());
o.setReceiveTime(null);
});
tradeOrderMapper.insert(order);
// 准备参数
Long id = 1L;
Long userId = 10L;
// mock 方法(支付单)
// 调用
tradeOrderUpdateService.receiveOrderByMember(userId, id);
// 断言
TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L);
assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus());
assertNotNull(dbOrder.getReceiveTime());
}
}

View File

@ -0,0 +1,137 @@
package cn.iocoder.yudao.module.trade.service.price;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
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.product.enums.spu.ProductSpuStatusEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import java.util.Arrays;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
/**
* {@link TradePriceServiceImpl} 的单元测试
*
* @author 芋道源码
*/
@Disabled // TODO 芋艿:后续 fix 补充的单测
public class TradePriceServiceImplTest extends BaseMockitoUnitTest {
@InjectMocks
private TradePriceServiceImpl tradePriceService;
@Mock
private ProductSkuApi productSkuApi;
@Mock
private ProductSpuApi productSpuApi;
@Mock
private List<TradePriceCalculator> priceCalculators;
@Test
public void testCalculatePrice() {
// 准备参数
TradePriceCalculateReqBO calculateReqBO = new TradePriceCalculateReqBO()
.setUserId(10L)
.setCouponId(20L).setAddressId(30L)
.setItems(Arrays.asList(
new TradePriceCalculateReqBO.Item().setSkuId(100L).setCount(1).setSelected(true),
new TradePriceCalculateReqBO.Item().setSkuId(200L).setCount(3).setSelected(true),
new TradePriceCalculateReqBO.Item().setSkuId(300L).setCount(6).setCartId(233L).setSelected(false)
));
// mock 方法
List<ProductSkuRespDTO> skuList = Arrays.asList(
new ProductSkuRespDTO().setId(100L).setStock(500).setPrice(1000).setPicUrl("https://t.cn/1.png").setSpuId(1001L)
.setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(1L).setPropertyName("颜色")
.setValueId(2L).setValueName("红色"))),
new ProductSkuRespDTO().setId(200L).setStock(400).setPrice(2000).setPicUrl("https://t.cn/2.png").setSpuId(1001L)
.setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(1L).setPropertyName("颜色")
.setValueId(3L).setValueName("黄色"))),
new ProductSkuRespDTO().setId(300L).setStock(600).setPrice(3000).setPicUrl("https://t.cn/3.png").setSpuId(1001L)
.setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(1L).setPropertyName("颜色")
.setValueId(4L).setValueName("黑色")))
);
when(productSkuApi.getSkuList(Mockito.eq(asSet(100L, 200L, 300L)))).thenReturn(skuList);
when(productSpuApi.getSpuList(Mockito.eq(asSet(1001L))))
.thenReturn(singletonList(new ProductSpuRespDTO().setId(1001L).setName("小菜").setCategoryId(666L)
.setStatus(ProductSpuStatusEnum.ENABLE.getStatus())));
// 调用
TradePriceCalculateRespBO calculateRespBO = tradePriceService.calculatePrice(calculateReqBO);
// 断言
assertEquals(TradeOrderTypeEnum.NORMAL.getType(), calculateRespBO.getType());
assertEquals(0, calculateRespBO.getPromotions().size());
assertNull(calculateRespBO.getCouponId());
// 断言:订单价格
assertEquals(7000, calculateRespBO.getPrice().getTotalPrice());
assertEquals(0, calculateRespBO.getPrice().getDiscountPrice());
assertEquals(0, calculateRespBO.getPrice().getDeliveryPrice());
assertEquals(0, calculateRespBO.getPrice().getCouponPrice());
assertEquals(0, calculateRespBO.getPrice().getPointPrice());
assertEquals(7000, calculateRespBO.getPrice().getPayPrice());
// 断言SKU 1
assertEquals(1001L, calculateRespBO.getItems().get(0).getSpuId());
assertEquals(100L, calculateRespBO.getItems().get(0).getSkuId());
assertEquals(1, calculateRespBO.getItems().get(0).getCount());
assertNull(calculateRespBO.getItems().get(0).getCartId());
assertTrue(calculateRespBO.getItems().get(0).getSelected());
assertEquals(1000, calculateRespBO.getItems().get(0).getPrice());
assertEquals(0, calculateRespBO.getItems().get(0).getDiscountPrice());
assertEquals(0, calculateRespBO.getItems().get(0).getDeliveryPrice());
assertEquals(0, calculateRespBO.getItems().get(0).getCouponPrice());
assertEquals(0, calculateRespBO.getItems().get(0).getPointPrice());
assertEquals(1000, calculateRespBO.getItems().get(0).getPayPrice());
assertEquals("小菜", calculateRespBO.getItems().get(0).getSpuName());
assertEquals("https://t.cn/1.png", calculateRespBO.getItems().get(0).getPicUrl());
assertEquals(666L, calculateRespBO.getItems().get(0).getCategoryId());
assertEquals(skuList.get(0).getProperties(), calculateRespBO.getItems().get(0).getProperties());
// 断言SKU 2
assertEquals(1001L, calculateRespBO.getItems().get(1).getSpuId());
assertEquals(200L, calculateRespBO.getItems().get(1).getSkuId());
assertEquals(3, calculateRespBO.getItems().get(1).getCount());
assertNull(calculateRespBO.getItems().get(1).getCartId());
assertTrue(calculateRespBO.getItems().get(1).getSelected());
assertEquals(2000, calculateRespBO.getItems().get(1).getPrice());
assertEquals(0, calculateRespBO.getItems().get(1).getDiscountPrice());
assertEquals(0, calculateRespBO.getItems().get(1).getDeliveryPrice());
assertEquals(0, calculateRespBO.getItems().get(1).getCouponPrice());
assertEquals(0, calculateRespBO.getItems().get(1).getPointPrice());
assertEquals(6000, calculateRespBO.getItems().get(1).getPayPrice());
assertEquals("小菜", calculateRespBO.getItems().get(1).getSpuName());
assertEquals("https://t.cn/2.png", calculateRespBO.getItems().get(1).getPicUrl());
assertEquals(666L, calculateRespBO.getItems().get(1).getCategoryId());
assertEquals(skuList.get(1).getProperties(), calculateRespBO.getItems().get(1).getProperties());
// 断言SKU 3
assertEquals(1001L, calculateRespBO.getItems().get(2).getSpuId());
assertEquals(300L, calculateRespBO.getItems().get(2).getSkuId());
assertEquals(6, calculateRespBO.getItems().get(2).getCount());
assertEquals(233L, calculateRespBO.getItems().get(2).getCartId());
assertFalse(calculateRespBO.getItems().get(2).getSelected());
assertEquals(3000, calculateRespBO.getItems().get(2).getPrice());
assertEquals(0, calculateRespBO.getItems().get(2).getDiscountPrice());
assertEquals(0, calculateRespBO.getItems().get(2).getDeliveryPrice());
assertEquals(0, calculateRespBO.getItems().get(2).getCouponPrice());
assertEquals(0, calculateRespBO.getItems().get(2).getPointPrice());
assertEquals(18000, calculateRespBO.getItems().get(2).getPayPrice());
assertEquals("小菜", calculateRespBO.getItems().get(2).getSpuName());
assertEquals("https://t.cn/3.png", calculateRespBO.getItems().get(2).getPicUrl());
assertEquals(666L, calculateRespBO.getItems().get(2).getCategoryId());
assertEquals(skuList.get(2).getProperties(), calculateRespBO.getItems().get(2).getProperties());
}
}

View File

@ -0,0 +1,146 @@
package cn.iocoder.yudao.module.trade.service.price.calculator;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO;
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.ArrayList;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
* {@link TradeCouponPriceCalculator} 的单元测试类
*
* @author 芋道源码
*/
public class TradeCouponPriceCalculatorTest extends BaseMockitoUnitTest {
@InjectMocks
private TradeCouponPriceCalculator tradeCouponPriceCalculator;
@Mock
private CouponApi couponApi;
@Test
public void testCalculate() {
// 准备参数
TradePriceCalculateReqBO param = new TradePriceCalculateReqBO()
.setUserId(233L).setCouponId(1024L)
.setItems(asList(
new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 匹配优惠劵
new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 匹配优惠劵
new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(true), // 不匹配优惠劵
new TradePriceCalculateReqBO.Item().setSkuId(40L).setCount(5).setSelected(false) // 匹配优惠劵,但是未选中
));
TradePriceCalculateRespBO result = new TradePriceCalculateRespBO()
.setType(TradeOrderTypeEnum.NORMAL.getType())
.setPrice(new TradePriceCalculateRespBO.Price())
.setPromotions(new ArrayList<>())
.setItems(asList(
new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true)
.setPrice(100).setSpuId(1L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true)
.setPrice(50).setSpuId(2L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(4).setSelected(true)
.setPrice(30).setSpuId(3L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(40L).setCount(5).setSelected(false)
.setPrice(60).setSpuId(1L)
));
// 保证价格被初始化上
TradePriceCalculatorHelper.recountPayPrice(result.getItems());
TradePriceCalculatorHelper.recountAllPrice(result);
// mock 方法(优惠劵 Coupon 信息)
CouponRespDTO coupon = randomPojo(CouponRespDTO.class, o -> o.setId(1024L).setName("程序员节")
.setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L))
.setUsePrice(350).setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType())
.setDiscountPercent(50).setDiscountLimitPrice(70));
when(couponApi.validateCoupon(eq(new CouponValidReqDTO().setId(1024L).setUserId(233L)))).thenReturn(coupon);
// 调用
tradeCouponPriceCalculator.calculate(param, result);
// 断言
assertEquals(result.getCouponId(), 1024L);
// 断言Price 部分
TradePriceCalculateRespBO.Price price = result.getPrice();
assertEquals(price.getTotalPrice(), 470);
assertEquals(price.getDiscountPrice(), 0);
assertEquals(price.getPointPrice(), 0);
assertEquals(price.getDeliveryPrice(), 0);
assertEquals(price.getCouponPrice(), 70);
assertEquals(price.getPayPrice(), 400);
// 断言SKU 1
TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0);
assertEquals(orderItem01.getSkuId(), 10L);
assertEquals(orderItem01.getCount(), 2);
assertEquals(orderItem01.getPrice(), 100);
assertEquals(orderItem01.getDiscountPrice(), 0);
assertEquals(orderItem01.getDeliveryPrice(), 0);
assertEquals(orderItem01.getCouponPrice(), 40);
assertEquals(orderItem01.getPointPrice(), 0);
assertEquals(orderItem01.getPayPrice(), 160);
// 断言SKU 2
TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1);
assertEquals(orderItem02.getSkuId(), 20L);
assertEquals(orderItem02.getCount(), 3);
assertEquals(orderItem02.getPrice(), 50);
assertEquals(orderItem02.getDiscountPrice(), 0);
assertEquals(orderItem02.getDeliveryPrice(), 0);
assertEquals(orderItem02.getCouponPrice(), 30);
assertEquals(orderItem02.getPointPrice(), 0);
assertEquals(orderItem02.getPayPrice(), 120);
// 断言SKU 3
TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2);
assertEquals(orderItem03.getSkuId(), 30L);
assertEquals(orderItem03.getCount(), 4);
assertEquals(orderItem03.getPrice(), 30);
assertEquals(orderItem03.getDiscountPrice(), 0);
assertEquals(orderItem03.getCouponPrice(), 0);
assertEquals(orderItem03.getPointPrice(), 0);
assertEquals(orderItem03.getPayPrice(), 120);
// 断言SKU 4
TradePriceCalculateRespBO.OrderItem orderItem04 = result.getItems().get(3);
assertEquals(orderItem04.getSkuId(), 40L);
assertEquals(orderItem04.getCount(), 5);
assertEquals(orderItem04.getPrice(), 60);
assertEquals(orderItem04.getDiscountPrice(), 0);
assertEquals(orderItem04.getCouponPrice(), 0);
assertEquals(orderItem04.getPointPrice(), 0);
assertEquals(orderItem04.getPayPrice(), 300);
// 断言Promotion 部分
assertEquals(result.getPromotions().size(), 1);
TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0);
assertEquals(promotion01.getId(), 1024L);
assertEquals(promotion01.getName(), "程序员节");
assertEquals(promotion01.getType(), PromotionTypeEnum.COUPON.getType());
assertEquals(promotion01.getTotalPrice(), 350);
assertEquals(promotion01.getDiscountPrice(), 70);
assertTrue(promotion01.getMatch());
assertEquals(promotion01.getDescription(), "优惠劵:省 0.70 元");
assertEquals(promotion01.getItems().size(), 2);
TradePriceCalculateRespBO.PromotionItem promotionItem011 = promotion01.getItems().get(0);
assertEquals(promotionItem011.getSkuId(), 10L);
assertEquals(promotionItem011.getTotalPrice(), 200);
assertEquals(promotionItem011.getDiscountPrice(), 40);
TradePriceCalculateRespBO.PromotionItem promotionItem012 = promotion01.getItems().get(1);
assertEquals(promotionItem012.getSkuId(), 20L);
assertEquals(promotionItem012.getTotalPrice(), 150);
assertEquals(promotionItem012.getDiscountPrice(), 30);
}
}

View File

@ -0,0 +1,193 @@
package cn.iocoder.yudao.module.trade.service.price.calculator;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService;
import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.ArrayList;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
* {@link TradeDeliveryPriceCalculator} 的单元测试
*
* @author jason
*/
public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
@InjectMocks
private TradeDeliveryPriceCalculator calculator;
@Mock
private MemberAddressApi addressApi;
@Mock
private DeliveryExpressTemplateService deliveryExpressTemplateService;
@Mock
private TradeConfigService tradeConfigService;
private TradePriceCalculateReqBO reqBO;
private TradePriceCalculateRespBO resultBO;
private DeliveryExpressTemplateRespBO templateRespBO;
private DeliveryExpressTemplateRespBO.Charge chargeBO;
private DeliveryExpressTemplateRespBO.Free freeBO;
@BeforeEach
public void init(){
// 准备参数
reqBO = new TradePriceCalculateReqBO()
.setDeliveryType(DeliveryTypeEnum.EXPRESS.getType())
.setAddressId(10L)
.setUserId(1L)
.setItems(asList(
new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true),
new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(10).setSelected(true),
new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(false) // 未选中
));
resultBO = new TradePriceCalculateRespBO()
.setPrice(new TradePriceCalculateRespBO.Price())
.setPromotions(new ArrayList<>())
.setItems(asList(
new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(10L).setCount(2).setSelected(true)
.setWeight(10d).setVolume(10d).setPrice(100),
new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(20L).setCount(10).setSelected(true)
.setWeight(10d).setVolume(10d).setPrice(200),
new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(30L).setCount(1).setSelected(false)
.setWeight(10d).setVolume(10d).setPrice(300)
));
// 保证价格被初始化上
TradePriceCalculatorHelper.recountPayPrice(resultBO.getItems());
TradePriceCalculatorHelper.recountAllPrice(resultBO);
// 准备收件地址数据
MemberAddressRespDTO addressResp = randomPojo(MemberAddressRespDTO.class, item -> item.setAreaId(10));
when(addressApi.getAddress(eq(10L), eq(1L))).thenReturn(addressResp);
// 准备运费模板费用配置数据
chargeBO = randomPojo(DeliveryExpressTemplateRespBO.Charge.class,
item -> item.setStartCount(10D).setStartPrice(1000).setExtraCount(10D).setExtraPrice(2000));
// 准备运费模板包邮配置数据:订单总件数 < 包邮件数时 12 < 20
freeBO = randomPojo(DeliveryExpressTemplateRespBO.Free.class,
item -> item.setFreeCount(20).setFreePrice(100));
// 准备 SP 运费模板数据
templateRespBO = randomPojo(DeliveryExpressTemplateRespBO.class,
item -> item.setChargeMode(DeliveryExpressChargeModeEnum.COUNT.getType())
.setCharge(chargeBO).setFree(freeBO));
}
@Test
@DisplayName("全场包邮")
public void testCalculate_expressGlobalFree() {
// mock 方法(全场包邮)
when(tradeConfigService.getTradeConfig()).thenReturn(new TradeConfigDO().setDeliveryExpressFreeEnabled(true)
.setDeliveryExpressFreePrice(2200));
// 调用
calculator.calculate(reqBO, resultBO);
TradePriceCalculateRespBO.Price price = resultBO.getPrice();
assertThat(price)
.extracting("totalPrice","discountPrice","couponPrice","pointPrice","deliveryPrice","payPrice")
.containsExactly(2200, 0, 0, 0, 0, 2200);
assertThat(resultBO.getItems()).hasSize(3);
// 断言SKU1
assertThat(resultBO.getItems().get(0))
.extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
.containsExactly(100, 2, 0, 0, 0, 0, 200);
// 断言SKU2
assertThat(resultBO.getItems().get(1))
.extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
.containsExactly(200, 10, 0, 0, 0, 0, 2000);
// 断言SKU3 未选中
assertThat(resultBO.getItems().get(2))
.extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
.containsExactly(300, 1, 0, 0, 0, 0, 300);
}
@Test
@DisplayName("按件计算运费不包邮的情况")
public void testCalculate_expressTemplateCharge() {
// SKU 1 : 100 * 2 = 200
// SKU 2 200 * 10 = 2000
// 运费 首件 1000 + 续件 2000 = 3000
// mock 方法
when(deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(eq(asSet(1L)), eq(10)))
.thenReturn(MapUtil.of(1L, templateRespBO));
// 调用
calculator.calculate(reqBO, resultBO);
// 断言
TradePriceCalculateRespBO.Price price = resultBO.getPrice();
assertThat(price)
.extracting("totalPrice","discountPrice","couponPrice","pointPrice","deliveryPrice","payPrice")
.containsExactly(2200, 0, 0, 0, 3000, 5200);
assertThat(resultBO.getItems()).hasSize(3);
// 断言SKU1
assertThat(resultBO.getItems().get(0))
.extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
.containsExactly(100, 2, 0, 0, 0, 500, 700);
// 断言SKU2
assertThat(resultBO.getItems().get(1))
.extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
.containsExactly(200, 10, 0, 0, 0, 2500, 4500);
// 断言SKU3 未选中
assertThat(resultBO.getItems().get(2))
.extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
.containsExactly(300, 1, 0, 0, 0, 0, 300);
}
@Test
@DisplayName("按件计算运费包邮的情况")
public void testCalculate_expressTemplateFree() {
// SKU 1 : 100 * 2 = 200
// SKU 2 200 * 10 = 2000
// 运费 0
// mock 方法
// 准备运费模板包邮配置数据 包邮 订单总件数 > 包邮件数时 12 > 10
templateRespBO.setFree(randomPojo(DeliveryExpressTemplateRespBO.Free.class,
item -> item.setFreeCount(10).setFreePrice(1000)));
when(deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(eq(asSet(1L)), eq(10)))
.thenReturn(MapUtil.of(1L, templateRespBO));
// 调用
calculator.calculate(reqBO, resultBO);
// 断言
TradePriceCalculateRespBO.Price price = resultBO.getPrice();
assertThat(price)
.extracting("totalPrice","discountPrice","couponPrice","pointPrice","deliveryPrice","payPrice")
.containsExactly(2200, 0, 0, 0, 0, 2200);
assertThat(resultBO.getItems()).hasSize(3);
// 断言SKU1
assertThat(resultBO.getItems().get(0))
.extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
.containsExactly(100, 2, 0, 0, 0, 0, 200);
// 断言SKU2
assertThat(resultBO.getItems().get(1))
.extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
.containsExactly(200, 10, 0, 0, 0, 0, 2000);
// 断言SKU3 未选中
assertThat(resultBO.getItems().get(2))
.extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
.containsExactly(300, 1, 0, 0, 0, 0, 300);
}
}

View File

@ -0,0 +1,120 @@
package cn.iocoder.yudao.module.trade.service.price.calculator;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi;
import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.ArrayList;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
* {@link TradeDiscountActivityPriceCalculator} 的单元测试类
*
* @author 芋道源码
*/
public class TradeDiscountActivityPriceCalculatorTest extends BaseMockitoUnitTest {
@InjectMocks
private TradeDiscountActivityPriceCalculator tradeDiscountActivityPriceCalculator;
@Mock
private DiscountActivityApi discountActivityApi;
@Test
public void testCalculate() {
// 准备参数
TradePriceCalculateReqBO param = new TradePriceCalculateReqBO()
.setItems(asList(
new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 匹配活动,且已选中
new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(false) // 匹配活动,但未选中
));
TradePriceCalculateRespBO result = new TradePriceCalculateRespBO()
.setType(TradeOrderTypeEnum.NORMAL.getType())
.setPrice(new TradePriceCalculateRespBO.Price())
.setPromotions(new ArrayList<>())
.setItems(asList(
new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true)
.setPrice(100),
new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(false)
.setPrice(50)
));
// 保证价格被初始化上
TradePriceCalculatorHelper.recountPayPrice(result.getItems());
TradePriceCalculatorHelper.recountAllPrice(result);
// mock 方法(限时折扣活动)
when(discountActivityApi.getMatchDiscountProductList(eq(asSet(10L, 20L)))).thenReturn(asList(
randomPojo(DiscountProductRespDTO.class, o -> o.setActivityId(1000L)
.setActivityName("活动 1000 号").setSkuId(10L)
.setDiscountType(PromotionDiscountTypeEnum.PRICE.getType()).setDiscountPrice(40)),
randomPojo(DiscountProductRespDTO.class, o -> o.setActivityId(2000L)
.setActivityName("活动 2000 号").setSkuId(20L)
.setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType()).setDiscountPercent(60))
));
// 10L: 100 * 2 - 40 * 2 = 120
// 20L50 * 3 - 50 * 3 * 0.4 = 90
// 调用
tradeDiscountActivityPriceCalculator.calculate(param, result);
// 断言Price 部分
TradePriceCalculateRespBO.Price price = result.getPrice();
assertEquals(price.getTotalPrice(), 200);
assertEquals(price.getDiscountPrice(), 80);
assertEquals(price.getPointPrice(), 0);
assertEquals(price.getDeliveryPrice(), 0);
assertEquals(price.getCouponPrice(), 0);
assertEquals(price.getPayPrice(), 120);
assertNull(result.getCouponId());
// 断言SKU 1
assertEquals(result.getItems().size(), 2);
TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0);
assertEquals(orderItem01.getSkuId(), 10L);
assertEquals(orderItem01.getCount(), 2);
assertEquals(orderItem01.getPrice(), 100);
assertEquals(orderItem01.getDiscountPrice(), 80);
assertEquals(orderItem01.getDeliveryPrice(), 0);
assertEquals(orderItem01.getCouponPrice(), 0);
assertEquals(orderItem01.getPointPrice(), 0);
assertEquals(orderItem01.getPayPrice(), 120);
// 断言SKU 2
TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1);
assertEquals(orderItem02.getSkuId(), 20L);
assertEquals(orderItem02.getCount(), 3);
assertEquals(orderItem02.getPrice(), 50);
assertEquals(orderItem02.getDiscountPrice(), 60);
assertEquals(orderItem02.getDeliveryPrice(), 0);
assertEquals(orderItem02.getCouponPrice(), 0);
assertEquals(orderItem02.getPointPrice(), 0);
assertEquals(orderItem02.getPayPrice(), 90);
// 断言Promotion 部分
assertEquals(result.getPromotions().size(), 1);
TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0);
assertEquals(promotion01.getId(), 1000L);
assertEquals(promotion01.getName(), "活动 1000 号");
assertEquals(promotion01.getType(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType());
assertEquals(promotion01.getTotalPrice(), 200);
assertEquals(promotion01.getDiscountPrice(), 80);
assertTrue(promotion01.getMatch());
assertEquals(promotion01.getDescription(), "限时折扣:省 0.80 元");
TradePriceCalculateRespBO.PromotionItem promotionItem01 = promotion01.getItems().get(0);
assertEquals(promotion01.getItems().size(), 1);
assertEquals(promotionItem01.getSkuId(), 10L);
assertEquals(promotionItem01.getTotalPrice(), 200);
assertEquals(promotionItem01.getDiscountPrice(), 80);
}
}

View File

@ -0,0 +1,118 @@
package cn.iocoder.yudao.module.trade.service.price.calculator;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.ArrayList;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
* {@link TradeMemberLevelPriceCalculator} 的单元测试类
*
* @author 芋道源码
*/
public class TradeMemberLevelPriceCalculatorTest extends BaseMockitoUnitTest {
@InjectMocks
private TradeMemberLevelPriceCalculator memberLevelPriceCalculator;
@Mock
private MemberLevelApi memberLevelApi;
@Mock
private MemberUserApi memberUserApi;
@Test
public void testCalculate() {
// 准备参数
TradePriceCalculateReqBO param = new TradePriceCalculateReqBO()
.setUserId(1024L)
.setItems(asList(
new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 匹配活动,且已选中
new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(false) // 匹配活动,但未选中
));
TradePriceCalculateRespBO result = new TradePriceCalculateRespBO()
.setType(TradeOrderTypeEnum.NORMAL.getType())
.setPrice(new TradePriceCalculateRespBO.Price())
.setPromotions(new ArrayList<>())
.setItems(asList(
new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true)
.setPrice(100),
new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(false)
.setPrice(50)
));
// 保证价格被初始化上
TradePriceCalculatorHelper.recountPayPrice(result.getItems());
TradePriceCalculatorHelper.recountAllPrice(result);
// mock 方法(会员等级)
when(memberUserApi.getUser(eq(1024L))).thenReturn(new MemberUserRespDTO().setLevelId(2048L));
when(memberLevelApi.getMemberLevel(eq(2048L))).thenReturn(
new MemberLevelRespDTO().setId(2048L).setName("VIP 会员").setDiscountPercent(60));
// 调用
memberLevelPriceCalculator.calculate(param, result);
// 断言Price 部分
TradePriceCalculateRespBO.Price price = result.getPrice();
assertEquals(price.getTotalPrice(), 200);
assertEquals(price.getDiscountPrice(), 0);
assertEquals(price.getPointPrice(), 0);
assertEquals(price.getDeliveryPrice(), 0);
assertEquals(price.getCouponPrice(), 0);
assertEquals(price.getVipPrice(), 80);
assertEquals(price.getPayPrice(), 120);
assertNull(result.getCouponId());
// 断言SKU 1
assertEquals(result.getItems().size(), 2);
TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0);
assertEquals(orderItem01.getSkuId(), 10L);
assertEquals(orderItem01.getCount(), 2);
assertEquals(orderItem01.getPrice(), 100);
assertEquals(orderItem01.getDiscountPrice(), 0);
assertEquals(orderItem01.getDeliveryPrice(), 0);
assertEquals(orderItem01.getCouponPrice(), 0);
assertEquals(orderItem01.getPointPrice(), 0);
assertEquals(orderItem01.getVipPrice(), 80);
assertEquals(orderItem01.getPayPrice(), 120);
// 断言SKU 2
TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1);
assertEquals(orderItem02.getSkuId(), 20L);
assertEquals(orderItem02.getCount(), 3);
assertEquals(orderItem02.getPrice(), 50);
assertEquals(orderItem02.getDiscountPrice(), 0);
assertEquals(orderItem02.getDeliveryPrice(), 0);
assertEquals(orderItem02.getCouponPrice(), 0);
assertEquals(orderItem02.getPointPrice(), 0);
assertEquals(orderItem02.getVipPrice(), 60);
assertEquals(orderItem02.getPayPrice(), 90);
// 断言Promotion 部分
assertEquals(result.getPromotions().size(), 1);
TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0);
assertEquals(promotion01.getId(), 2048L);
assertEquals(promotion01.getName(), "VIP 会员");
assertEquals(promotion01.getType(), PromotionTypeEnum.MEMBER_LEVEL.getType());
assertEquals(promotion01.getTotalPrice(), 200);
assertEquals(promotion01.getDiscountPrice(), 80);
assertTrue(promotion01.getMatch());
assertEquals(promotion01.getDescription(), "会员等级折扣:省 0.80 元");
TradePriceCalculateRespBO.PromotionItem promotionItem01 = promotion01.getItems().get(0);
assertEquals(promotion01.getItems().size(), 1);
assertEquals(promotionItem01.getSkuId(), 10L);
assertEquals(promotionItem01.getTotalPrice(), 200);
assertEquals(promotionItem01.getDiscountPrice(), 80);
}
}

View File

@ -0,0 +1,99 @@
package cn.iocoder.yudao.module.trade.service.price.calculator;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.member.api.config.MemberConfigApi;
import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.ArrayList;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
// TODO 芋艿:晚点 review
/**
* {@link TradePointGiveCalculator} 的单元测试类
*
* @author owen
*/
public class TradePointGiveCalculatorTest extends BaseMockitoUnitTest {
@InjectMocks
private TradePointGiveCalculator tradePointGiveCalculator;
@Mock
private MemberConfigApi memberConfigApi;
@Test
public void testCalculate() {
// 准备参数
TradePriceCalculateReqBO param = new TradePriceCalculateReqBO()
.setUserId(233L)
.setItems(asList(
new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 全局积分
new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 全局积分 + SKU 积分
new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(false), // 全局积分,但是未选中
new TradePriceCalculateReqBO.Item().setSkuId(40L).setCount(5).setSelected(false) // 全局积分 + SKU 积分,但是未选中
));
TradePriceCalculateRespBO result = new TradePriceCalculateRespBO()
.setType(TradeOrderTypeEnum.NORMAL.getType())
.setPrice(new TradePriceCalculateRespBO.Price())
.setPromotions(new ArrayList<>())
.setItems(asList(
new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true)
.setPrice(100).setSpuId(1L).setGivePoint(0),
new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true)
.setPrice(50).setSpuId(2L).setGivePoint(100),
new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(4).setSelected(false)
.setPrice(30).setSpuId(3L).setGivePoint(0),
new TradePriceCalculateRespBO.OrderItem().setSkuId(40L).setCount(5).setSelected(false)
.setPrice(60).setSpuId(1L).setGivePoint(100)
));
// 保证价格被初始化上
TradePriceCalculatorHelper.recountPayPrice(result.getItems());
TradePriceCalculatorHelper.recountAllPrice(result);
// mock 方法(积分配置 信息)
MemberConfigRespDTO memberConfig = randomPojo(MemberConfigRespDTO.class,
o -> o.setPointTradeDeductEnable(true) // 启用积分折扣
.setPointTradeGivePoint(100)); // 1 元赠送多少分
when(memberConfigApi.getConfig()).thenReturn(memberConfig);
// 调用
tradePointGiveCalculator.calculate(param, result);
// 断言Price 部分
assertEquals(result.getGivePoint(), 2 * 100 + 3 * 50 + 100);
// 断言SKU 1
TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0);
assertEquals(orderItem01.getSkuId(), 10L);
assertEquals(orderItem01.getCount(), 2);
assertEquals(orderItem01.getPrice(), 100);
assertEquals(orderItem01.getGivePoint(), 2 * 100); // 全局积分
// 断言SKU 2
TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1);
assertEquals(orderItem02.getSkuId(), 20L);
assertEquals(orderItem02.getCount(), 3);
assertEquals(orderItem02.getPrice(), 50);
assertEquals(orderItem02.getGivePoint(), 3 * 50 + 100); // 全局积分 + SKU 积分
// 断言SKU 3
TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2);
assertEquals(orderItem03.getSkuId(), 30L);
assertEquals(orderItem03.getCount(), 4);
assertEquals(orderItem03.getPrice(), 30);
assertEquals(orderItem03.getGivePoint(), 0); // 全局积分,但是未选中
// 断言SKU 4
TradePriceCalculateRespBO.OrderItem orderItem04 = result.getItems().get(3);
assertEquals(orderItem04.getSkuId(), 40L);
assertEquals(orderItem04.getCount(), 5);
assertEquals(orderItem04.getPrice(), 60);
assertEquals(orderItem04.getGivePoint(), 100); // 全局积分 + SKU 积分,但是未选中
}
}

View File

@ -0,0 +1,333 @@
package cn.iocoder.yudao.module.trade.service.price.calculator;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.member.api.config.MemberConfigApi;
import cn.iocoder.yudao.module.member.api.config.dto.MemberConfigRespDTO;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.ArrayList;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
// TODO 芋艿:晚点 review
/**
* {@link TradePointUsePriceCalculator } 的单元测试类
*
* @author owen
*/
public class TradePointUsePriceCalculatorTest extends BaseMockitoUnitTest {
@InjectMocks
private TradePointUsePriceCalculator tradePointUsePriceCalculator;
@Mock
private MemberConfigApi memberConfigApi;
@Mock
private MemberUserApi memberUserApi;
@Test
public void testCalculate_success() {
// 准备参数
TradePriceCalculateReqBO param = new TradePriceCalculateReqBO()
.setUserId(233L).setPointStatus(true) // 是否使用积分
.setItems(asList(
new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 使用积分
new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 使用积分
new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(5).setSelected(false) // 未选中,不使用积分
));
TradePriceCalculateRespBO result = new TradePriceCalculateRespBO()
.setType(TradeOrderTypeEnum.NORMAL.getType())
.setPrice(new TradePriceCalculateRespBO.Price())
.setPromotions(new ArrayList<>())
.setItems(asList(
new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true)
.setPrice(100).setSpuId(1L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true)
.setPrice(50).setSpuId(2L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(5).setSelected(false)
.setPrice(30).setSpuId(3L)
));
// 保证价格被初始化上
TradePriceCalculatorHelper.recountPayPrice(result.getItems());
TradePriceCalculatorHelper.recountAllPrice(result);
// mock 方法(积分配置 信息)
MemberConfigRespDTO memberConfig = randomPojo(MemberConfigRespDTO.class,
o -> o.setPointTradeDeductEnable(true) // 启用积分折扣
.setPointTradeDeductUnitPrice(1) // 1 积分抵扣多少金额(单位分)
.setPointTradeDeductMaxPrice(100)); // 积分抵扣最大值
when(memberConfigApi.getConfig()).thenReturn(memberConfig);
// mock 方法(会员 信息)
MemberUserRespDTO user = randomPojo(MemberUserRespDTO.class, o -> o.setId(param.getUserId()).setPoint(100));
when(memberUserApi.getUser(user.getId())).thenReturn(user);
// 调用
tradePointUsePriceCalculator.calculate(param, result);
// 断言:使用了多少积分
assertEquals(result.getUsePoint(), 100);
// 断言Price 部分
TradePriceCalculateRespBO.Price price = result.getPrice();
assertEquals(price.getTotalPrice(), 350);
assertEquals(price.getPayPrice(), 250);
assertEquals(price.getPointPrice(), 100);
// 断言SKU 1
TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0);
assertEquals(orderItem01.getSkuId(), 10L);
assertEquals(orderItem01.getCount(), 2);
assertEquals(orderItem01.getPrice(), 100);
assertEquals(orderItem01.getPointPrice(), 57);
assertEquals(orderItem01.getPayPrice(), 143);
// 断言SKU 2
TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1);
assertEquals(orderItem02.getSkuId(), 20L);
assertEquals(orderItem02.getCount(), 3);
assertEquals(orderItem02.getPrice(), 50);
assertEquals(orderItem02.getPointPrice(), 43);
assertEquals(orderItem02.getPayPrice(), 107);
// 断言SKU 3
TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2);
assertEquals(orderItem03.getSkuId(), 30L);
assertEquals(orderItem03.getCount(), 5);
assertEquals(orderItem03.getPrice(), 30);
assertEquals(orderItem03.getPointPrice(), 0);
assertEquals(orderItem03.getPayPrice(), 150);
// 断言Promotion 部分
assertEquals(result.getPromotions().size(), 1);
TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0);
assertEquals(promotion01.getId(), user.getId());
assertEquals(promotion01.getName(), "积分抵扣");
assertEquals(promotion01.getType(), PromotionTypeEnum.POINT.getType());
assertEquals(promotion01.getTotalPrice(), 350);
assertEquals(promotion01.getDiscountPrice(), 100);
assertTrue(promotion01.getMatch());
assertEquals(promotion01.getDescription(), "积分抵扣:省 1.00 元");
assertEquals(promotion01.getItems().size(), 2);
TradePriceCalculateRespBO.PromotionItem promotionItem011 = promotion01.getItems().get(0);
assertEquals(promotionItem011.getSkuId(), 10L);
assertEquals(promotionItem011.getTotalPrice(), 200);
assertEquals(promotionItem011.getDiscountPrice(), 57);
TradePriceCalculateRespBO.PromotionItem promotionItem012 = promotion01.getItems().get(1);
assertEquals(promotionItem012.getSkuId(), 20L);
assertEquals(promotionItem012.getTotalPrice(), 150);
assertEquals(promotionItem012.getDiscountPrice(), 43);
}
/**
* 当用户积分充足时,抵扣的金额为:配置表的“积分抵扣最大值”
*/
@Test
public void testCalculate_TradeDeductMaxPrice() {
// 准备参数
TradePriceCalculateReqBO param = new TradePriceCalculateReqBO()
.setUserId(233L).setPointStatus(true) // 是否使用积分
.setItems(asList(
new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 使用积分
new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 使用积分
new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(5).setSelected(false) // 未选中,不使用积分
));
TradePriceCalculateRespBO result = new TradePriceCalculateRespBO()
.setType(TradeOrderTypeEnum.NORMAL.getType())
.setPrice(new TradePriceCalculateRespBO.Price())
.setPromotions(new ArrayList<>())
.setItems(asList(
new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true)
.setPrice(100).setSpuId(1L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true)
.setPrice(50).setSpuId(2L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(5).setSelected(false)
.setPrice(30).setSpuId(3L)
));
// 保证价格被初始化上
TradePriceCalculatorHelper.recountPayPrice(result.getItems());
TradePriceCalculatorHelper.recountAllPrice(result);
// mock 方法(积分配置 信息)
MemberConfigRespDTO memberConfig = randomPojo(MemberConfigRespDTO.class,
o -> o.setPointTradeDeductEnable(true) // 启用积分折扣
.setPointTradeDeductUnitPrice(1) // 1 积分抵扣多少金额(单位分)
.setPointTradeDeductMaxPrice(50)); // 积分抵扣最大值
when(memberConfigApi.getConfig()).thenReturn(memberConfig);
// mock 方法(会员 信息)
MemberUserRespDTO user = randomPojo(MemberUserRespDTO.class, o -> o.setId(param.getUserId()).setPoint(100));
when(memberUserApi.getUser(user.getId())).thenReturn(user);
// 调用
tradePointUsePriceCalculator.calculate(param, result);
// 断言:使用了多少积分
assertEquals(result.getUsePoint(), 50);
// 断言Price 部分
TradePriceCalculateRespBO.Price price = result.getPrice();
assertEquals(price.getTotalPrice(), 350);
assertEquals(price.getPayPrice(), 300);
assertEquals(price.getPointPrice(), 50);
// 断言SKU 1
TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0);
assertEquals(orderItem01.getSkuId(), 10L);
assertEquals(orderItem01.getCount(), 2);
assertEquals(orderItem01.getPrice(), 100);
assertEquals(orderItem01.getPointPrice(), 28);
assertEquals(orderItem01.getPayPrice(), 172);
// 断言SKU 2
TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1);
assertEquals(orderItem02.getSkuId(), 20L);
assertEquals(orderItem02.getCount(), 3);
assertEquals(orderItem02.getPrice(), 50);
assertEquals(orderItem02.getPointPrice(), 22);
assertEquals(orderItem02.getPayPrice(), 128);
// 断言SKU 3
TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2);
assertEquals(orderItem03.getSkuId(), 30L);
assertEquals(orderItem03.getCount(), 5);
assertEquals(orderItem03.getPrice(), 30);
assertEquals(orderItem03.getPointPrice(), 0);
assertEquals(orderItem03.getPayPrice(), 150);
// 断言Promotion 部分
assertEquals(result.getPromotions().size(), 1);
TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0);
assertEquals(promotion01.getId(), user.getId());
assertEquals(promotion01.getName(), "积分抵扣");
assertEquals(promotion01.getType(), PromotionTypeEnum.POINT.getType());
assertEquals(promotion01.getTotalPrice(), 350);
assertEquals(promotion01.getDiscountPrice(), 50);
assertTrue(promotion01.getMatch());
assertEquals(promotion01.getDescription(), "积分抵扣:省 0.50 元");
assertEquals(promotion01.getItems().size(), 2);
TradePriceCalculateRespBO.PromotionItem promotionItem011 = promotion01.getItems().get(0);
assertEquals(promotionItem011.getSkuId(), 10L);
assertEquals(promotionItem011.getTotalPrice(), 200);
assertEquals(promotionItem011.getDiscountPrice(), 28);
TradePriceCalculateRespBO.PromotionItem promotionItem012 = promotion01.getItems().get(1);
assertEquals(promotionItem012.getSkuId(), 20L);
assertEquals(promotionItem012.getTotalPrice(), 150);
assertEquals(promotionItem012.getDiscountPrice(), 22);
}
/**
* 订单不使用积分,不会产生优惠
*/
@Test
public void testCalculate_PointStatusFalse() {
// 准备参数
TradePriceCalculateReqBO param = new TradePriceCalculateReqBO()
.setUserId(233L).setPointStatus(false) // 是否使用积分
.setItems(asList(
new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 使用积分
new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 使用积分
new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(5).setSelected(false) // 未选中,不使用积分
));
TradePriceCalculateRespBO result = new TradePriceCalculateRespBO()
.setType(TradeOrderTypeEnum.NORMAL.getType())
.setPrice(new TradePriceCalculateRespBO.Price())
.setPromotions(new ArrayList<>())
.setItems(asList(
new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true)
.setPrice(100).setSpuId(1L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true)
.setPrice(50).setSpuId(2L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(5).setSelected(false)
.setPrice(30).setSpuId(3L)
));
// 保证价格被初始化上
TradePriceCalculatorHelper.recountPayPrice(result.getItems());
TradePriceCalculatorHelper.recountAllPrice(result);
// 调用
tradePointUsePriceCalculator.calculate(param, result);
// 断言:没有使用积分
assertNotUsePoint(result);
}
/**
* 会员积分不足,不会产生优惠
*/
@Test
public void testCalculate_UserPointNotEnough() {
// 准备参数
TradePriceCalculateReqBO param = new TradePriceCalculateReqBO()
.setUserId(233L).setPointStatus(true) // 是否使用积分
.setItems(asList(
new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 使用积分
new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 使用积分
new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(5).setSelected(false) // 未选中,不使用积分
));
TradePriceCalculateRespBO result = new TradePriceCalculateRespBO()
.setType(TradeOrderTypeEnum.NORMAL.getType())
.setPrice(new TradePriceCalculateRespBO.Price())
.setPromotions(new ArrayList<>())
.setItems(asList(
new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true)
.setPrice(100).setSpuId(1L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true)
.setPrice(50).setSpuId(2L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(5).setSelected(false)
.setPrice(30).setSpuId(3L)
));
// 保证价格被初始化上
TradePriceCalculatorHelper.recountPayPrice(result.getItems());
TradePriceCalculatorHelper.recountAllPrice(result);
// mock 方法(积分配置 信息)
MemberConfigRespDTO memberConfig = randomPojo(MemberConfigRespDTO.class,
o -> o.setPointTradeDeductEnable(true) // 启用积分折扣
.setPointTradeDeductUnitPrice(1) // 1 积分抵扣多少金额(单位分)
.setPointTradeDeductMaxPrice(100)); // 积分抵扣最大值
when(memberConfigApi.getConfig()).thenReturn(memberConfig);
// mock 方法(会员 信息)
MemberUserRespDTO user = randomPojo(MemberUserRespDTO.class, o -> o.setId(param.getUserId()).setPoint(0));
when(memberUserApi.getUser(user.getId())).thenReturn(user);
// 调用
tradePointUsePriceCalculator.calculate(param, result);
// 断言:没有使用积分
assertNotUsePoint(result);
}
/**
* 断言:没有使用积分
*/
private static void assertNotUsePoint(TradePriceCalculateRespBO result) {
// 断言:使用了多少积分
assertEquals(result.getUsePoint(), 0);
// 断言Price 部分
TradePriceCalculateRespBO.Price price = result.getPrice();
assertEquals(price.getTotalPrice(), 350);
assertEquals(price.getPayPrice(), 350);
assertEquals(price.getPointPrice(), 0);
// 断言SKU 1
TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0);
assertEquals(orderItem01.getSkuId(), 10L);
assertEquals(orderItem01.getCount(), 2);
assertEquals(orderItem01.getPrice(), 100);
assertEquals(orderItem01.getPointPrice(), 0);
assertEquals(orderItem01.getPayPrice(), 200);
// 断言SKU 2
TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1);
assertEquals(orderItem02.getSkuId(), 20L);
assertEquals(orderItem02.getCount(), 3);
assertEquals(orderItem02.getPrice(), 50);
assertEquals(orderItem02.getPointPrice(), 0);
assertEquals(orderItem02.getPayPrice(), 150);
// 断言SKU 3
TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2);
assertEquals(orderItem03.getSkuId(), 30L);
assertEquals(orderItem03.getCount(), 5);
assertEquals(orderItem03.getPrice(), 30);
assertEquals(orderItem03.getPointPrice(), 0);
assertEquals(orderItem03.getPayPrice(), 150);
// 断言Promotion 部分
assertEquals(result.getPromotions().size(), 0);
}
}

View File

@ -0,0 +1,235 @@
package cn.iocoder.yudao.module.trade.service.price.calculator;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi;
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.ArrayList;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
* {@link TradeRewardActivityPriceCalculator} 的单元测试类
*
* @author 芋道源码
*/
public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest {
@InjectMocks
private TradeRewardActivityPriceCalculator tradeRewardActivityPriceCalculator;
@Mock
private RewardActivityApi rewardActivityApi;
@Test
public void testCalculate_match() {
// 准备参数
TradePriceCalculateReqBO param = new TradePriceCalculateReqBO()
.setItems(asList(
new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 匹配活动 1
new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 匹配活动 1
new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(true) // 匹配活动 2
));
TradePriceCalculateRespBO result = new TradePriceCalculateRespBO()
.setType(TradeOrderTypeEnum.NORMAL.getType())
.setPrice(new TradePriceCalculateRespBO.Price())
.setPromotions(new ArrayList<>())
.setItems(asList(
new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true)
.setPrice(100).setSpuId(1L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true)
.setPrice(50).setSpuId(2L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(4).setSelected(true)
.setPrice(30).setSpuId(3L)
));
// 保证价格被初始化上
TradePriceCalculatorHelper.recountPayPrice(result.getItems());
TradePriceCalculatorHelper.recountAllPrice(result);
// mock 方法(限时折扣 DiscountActivity 信息)
when(rewardActivityApi.getMatchRewardActivityList(eq(asSet(1L, 2L, 3L)))).thenReturn(asList(
randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号")
.setSpuIds(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType())
.setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(200).setDiscountPrice(70)))),
randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(2000L).setName("活动 2000 号")
.setSpuIds(singletonList(3L)).setConditionType(PromotionConditionTypeEnum.COUNT.getType())
.setRules(asList(new RewardActivityMatchRespDTO.Rule().setLimit(1).setDiscountPrice(10),
new RewardActivityMatchRespDTO.Rule().setLimit(2).setDiscountPrice(60), // 最大可满足,因为是 4 个
new RewardActivityMatchRespDTO.Rule().setLimit(10).setDiscountPrice(100))))
));
// 调用
tradeRewardActivityPriceCalculator.calculate(param, result);
// 断言 Order 部分
TradePriceCalculateRespBO.Price price = result.getPrice();
assertEquals(price.getTotalPrice(), 470);
assertEquals(price.getDiscountPrice(), 130);
assertEquals(price.getPointPrice(), 0);
assertEquals(price.getDeliveryPrice(), 0);
assertEquals(price.getCouponPrice(), 0);
assertEquals(price.getPayPrice(), 340);
assertNull(result.getCouponId());
// 断言SKU 1
assertEquals(result.getItems().size(), 3);
TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0);
assertEquals(orderItem01.getSkuId(), 10L);
assertEquals(orderItem01.getCount(), 2);
assertEquals(orderItem01.getPrice(), 100);
assertEquals(orderItem01.getDiscountPrice(), 40);
assertEquals(orderItem01.getDeliveryPrice(), 0);
assertEquals(orderItem01.getCouponPrice(), 0);
assertEquals(orderItem01.getPointPrice(), 0);
assertEquals(orderItem01.getPayPrice(), 160);
// 断言SKU 2
TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1);
assertEquals(orderItem02.getSkuId(), 20L);
assertEquals(orderItem02.getCount(), 3);
assertEquals(orderItem02.getPrice(), 50);
assertEquals(orderItem02.getDiscountPrice(), 30);
assertEquals(orderItem02.getDeliveryPrice(), 0);
assertEquals(orderItem02.getCouponPrice(), 0);
assertEquals(orderItem02.getPointPrice(), 0);
assertEquals(orderItem02.getPayPrice(), 120);
// 断言SKU 3
TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2);
assertEquals(orderItem03.getSkuId(), 30L);
assertEquals(orderItem03.getCount(), 4);
assertEquals(orderItem03.getPrice(), 30);
assertEquals(orderItem03.getDiscountPrice(), 60);
assertEquals(orderItem03.getDeliveryPrice(), 0);
assertEquals(orderItem03.getCouponPrice(), 0);
assertEquals(orderItem03.getPointPrice(), 0);
assertEquals(orderItem03.getPayPrice(), 60);
// 断言Promotion 部分(第一个)
assertEquals(result.getPromotions().size(), 2);
TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0);
assertEquals(promotion01.getId(), 1000L);
assertEquals(promotion01.getName(), "活动 1000 号");
assertEquals(promotion01.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType());
assertEquals(promotion01.getTotalPrice(), 350);
assertEquals(promotion01.getDiscountPrice(), 70);
assertTrue(promotion01.getMatch());
assertEquals(promotion01.getDescription(), "满减送:省 0.70 元");
assertEquals(promotion01.getItems().size(), 2);
TradePriceCalculateRespBO.PromotionItem promotionItem011 = promotion01.getItems().get(0);
assertEquals(promotionItem011.getSkuId(), 10L);
assertEquals(promotionItem011.getTotalPrice(), 200);
assertEquals(promotionItem011.getDiscountPrice(), 40);
TradePriceCalculateRespBO.PromotionItem promotionItem012 = promotion01.getItems().get(1);
assertEquals(promotionItem012.getSkuId(), 20L);
assertEquals(promotionItem012.getTotalPrice(), 150);
assertEquals(promotionItem012.getDiscountPrice(), 30);
// 断言Promotion 部分(第二个)
TradePriceCalculateRespBO.Promotion promotion02 = result.getPromotions().get(1);
assertEquals(promotion02.getId(), 2000L);
assertEquals(promotion02.getName(), "活动 2000 号");
assertEquals(promotion02.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType());
assertEquals(promotion02.getTotalPrice(), 120);
assertEquals(promotion02.getDiscountPrice(), 60);
assertTrue(promotion02.getMatch());
assertEquals(promotion02.getDescription(), "满减送:省 0.60 元");
TradePriceCalculateRespBO.PromotionItem promotionItem02 = promotion02.getItems().get(0);
assertEquals(promotion02.getItems().size(), 1);
assertEquals(promotionItem02.getSkuId(), 30L);
assertEquals(promotionItem02.getTotalPrice(), 120);
assertEquals(promotionItem02.getDiscountPrice(), 60);
}
@Test
public void testCalculate_notMatch() {
// 准备参数
TradePriceCalculateReqBO param = new TradePriceCalculateReqBO()
.setItems(asList(
new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true),
new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true),
new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(true)
));
TradePriceCalculateRespBO result = new TradePriceCalculateRespBO()
.setType(TradeOrderTypeEnum.NORMAL.getType())
.setPrice(new TradePriceCalculateRespBO.Price())
.setPromotions(new ArrayList<>())
.setItems(asList(
new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true)
.setPrice(100).setSpuId(1L),
new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true)
.setPrice(50).setSpuId(2L)
));
// 保证价格被初始化上
TradePriceCalculatorHelper.recountPayPrice(result.getItems());
TradePriceCalculatorHelper.recountAllPrice(result);
// mock 方法(限时折扣 DiscountActivity 信息)
when(rewardActivityApi.getMatchRewardActivityList(eq(asSet(1L, 2L)))).thenReturn(singletonList(
randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号")
.setSpuIds(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType())
.setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(351).setDiscountPrice(70))))
));
// 调用
tradeRewardActivityPriceCalculator.calculate(param, result);
// 断言 Order 部分
TradePriceCalculateRespBO.Price price = result.getPrice();
assertEquals(price.getTotalPrice(), 350);
assertEquals(price.getDiscountPrice(), 0);
assertEquals(price.getPointPrice(), 0);
assertEquals(price.getDeliveryPrice(), 0);
assertEquals(price.getCouponPrice(), 0);
assertEquals(price.getPayPrice(), 350);
assertNull(result.getCouponId());
// 断言SKU 1
assertEquals(result.getItems().size(), 2);
TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0);
assertEquals(orderItem01.getSkuId(), 10L);
assertEquals(orderItem01.getCount(), 2);
assertEquals(orderItem01.getPrice(), 100);
assertEquals(orderItem01.getDiscountPrice(), 0);
assertEquals(orderItem01.getDeliveryPrice(), 0);
assertEquals(orderItem01.getCouponPrice(), 0);
assertEquals(orderItem01.getPointPrice(), 0);
assertEquals(orderItem01.getPayPrice(), 200);
// 断言SKU 2
TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1);
assertEquals(orderItem02.getSkuId(), 20L);
assertEquals(orderItem02.getCount(), 3);
assertEquals(orderItem02.getPrice(), 50);
assertEquals(orderItem02.getDiscountPrice(), 0);
assertEquals(orderItem02.getDeliveryPrice(), 0);
assertEquals(orderItem02.getCouponPrice(), 0);
assertEquals(orderItem02.getPointPrice(), 0);
assertEquals(orderItem02.getPayPrice(), 150);
// 断言 Promotion 部分
assertEquals(result.getPromotions().size(), 1);
TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0);
assertEquals(promotion01.getId(), 1000L);
assertEquals(promotion01.getName(), "活动 1000 号");
assertEquals(promotion01.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType());
assertEquals(promotion01.getTotalPrice(), 350);
assertEquals(promotion01.getDiscountPrice(), 0);
assertFalse(promotion01.getMatch());
assertEquals(promotion01.getDescription(), "TODO"); // TODO 芋艿:后面再想想
assertEquals(promotion01.getItems().size(), 2);
TradePriceCalculateRespBO.PromotionItem promotionItem011 = promotion01.getItems().get(0);
assertEquals(promotionItem011.getSkuId(), 10L);
assertEquals(promotionItem011.getTotalPrice(), 200);
assertEquals(promotionItem011.getDiscountPrice(), 0);
TradePriceCalculateRespBO.PromotionItem promotionItem012 = promotion01.getItems().get(1);
assertEquals(promotionItem012.getSkuId(), 20L);
assertEquals(promotionItem012.getTotalPrice(), 150);
assertEquals(promotionItem012.getDiscountPrice(), 0);
}
}

View File

@ -0,0 +1,61 @@
spring:
main:
lazy-initialization: true # 开启懒加载,加快速度
banner-mode: off # 单元测试,禁用 Banner
--- #################### 数据库相关配置 ####################
spring:
# 数据源配置项
datasource:
name: ruoyi-vue-pro
url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式DATABASE_TO_UPPER 配置表和字段使用小写
driver-class-name: org.h2.Driver
username: sa
password:
druid:
async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
initial-size: 1 # 单元测试,配置为 1提升启动速度
sql:
init:
schema-locations: classpath:/sql/create_tables.sql
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis:
host: 127.0.0.1 # 地址
port: 16379 # 端口(单元测试,使用 16379 端口)
database: 0 # 数据库索引
mybatis:
lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
--- #################### 定时任务相关配置 ####################
--- #################### 配置中心相关配置 ####################
--- #################### 服务保障相关配置 ####################
# Lock4j 配置项(单元测试,禁用 Lock4j
# Resilience4j 配置项
--- #################### 监控相关配置 ####################
--- #################### 芋道相关配置 ####################
# 芋道配置项,设置当前项目所有自定义的配置
yudao:
info:
base-package: cn.iocoder.yudao.module
trade:
order:
app-id: 1
merchant-order-id: 1
express:
kd-niao:
api-key: xxxx
business-id: xxxxx
kd100:
customer: xxxxx
key: xxxxx
client: not_provide

View File

@ -0,0 +1,4 @@
<configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
</configuration>

View File

@ -0,0 +1,7 @@
DELETE FROM trade_order;
DELETE FROM trade_order_item;
DELETE FROM trade_after_sale;
DELETE FROM trade_after_sale_log;
DELETE FROM trade_brokerage_user;
DELETE FROM trade_brokerage_record;
DELETE FROM "trade_brokerage_withdraw";

View File

@ -0,0 +1,191 @@
CREATE TABLE IF NOT EXISTS "trade_order" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"no" varchar NOT NULL,
"type" int NOT NULL,
"terminal" int NOT NULL,
"user_id" bigint NOT NULL,
"user_ip" varchar NOT NULL,
"user_remark" varchar,
"status" int NOT NULL,
"product_count" int NOT NULL,
"cancel_type" int,
"remark" varchar,
"pay_status" bit NOT NULL,
"pay_time" datetime,
"finish_time" datetime,
"cancel_time" datetime,
"original_price" int NOT NULL,
"order_price" int NOT NULL,
"discount_price" int NOT NULL,
"delivery_price" int NOT NULL,
"adjust_price" int NOT NULL,
"pay_price" int NOT NULL,
"pay_order_id" bigint,
"pay_channel_code" varchar,
"delivery_template_id" bigint,
"logistics_id" bigint,
"logistics_no" varchar,
"delivery_time" datetime,
"receive_time" datetime,
"receiver_name" varchar NOT NULL,
"receiver_mobile" varchar NOT NULL,
"receiver_area_id" int NOT NULL,
"receiver_post_code" int,
"receiver_detail_address" varchar NOT NULL,
"after_sale_status" int NOT NULL,
"refund_price" int NOT NULL,
"coupon_id" bigint NOT NULL,
"coupon_price" int NOT NULL,
"point_price" int NOT NULL,
"creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '交易订单表';
CREATE TABLE IF NOT EXISTS "trade_order_item" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"user_id" bigint NOT NULL,
"order_id" bigint NOT NULL,
"spu_id" bigint NOT NULL,
"spu_name" varchar NOT NULL,
"sku_id" bigint NOT NULL,
"properties" varchar,
"pic_url" varchar,
"count" int NOT NULL,
"original_price" int NOT NULL,
"original_unit_price" int NOT NULL,
"discount_price" int NOT NULL,
"pay_price" int NOT NULL,
"order_part_price" int NOT NULL,
"order_divide_price" int NOT NULL,
"after_sale_status" int NOT NULL,
"creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '交易订单明细表';
CREATE TABLE IF NOT EXISTS "trade_after_sale" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"no" varchar NOT NULL,
"status" int NOT NULL,
"type" int NOT NULL,
"way" int NOT NULL,
"user_id" bigint NOT NULL,
"apply_reason" varchar NOT NULL,
"apply_description" varchar,
"apply_pic_urls" varchar,
"order_id" bigint NOT NULL,
"order_no" varchar NOT NULL,
"order_item_id" bigint NOT NULL,
"spu_id" bigint NOT NULL,
"spu_name" varchar NOT NULL,
"sku_id" bigint NOT NULL,
"properties" varchar,
"pic_url" varchar,
"count" int NOT NULL,
"audit_time" varchar,
"audit_user_id" bigint,
"audit_reason" varchar,
"refund_price" int NOT NULL,
"pay_refund_id" bigint,
"refund_time" varchar,
"logistics_id" bigint,
"logistics_no" varchar,
"delivery_time" varchar,
"receive_time" varchar,
"receive_reason" varchar,
"creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '交易售后表';
CREATE TABLE IF NOT EXISTS "trade_after_sale_log" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"user_id" bigint NOT NULL,
"user_type" int NOT NULL,
"after_sale_id" bigint NOT NULL,
"order_id" bigint NOT NULL,
"order_item_id" bigint NOT NULL,
"before_status" int,
"after_status" int NOT NULL,
"content" varchar NOT NULL,
"creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '交易售后日志';
CREATE TABLE IF NOT EXISTS "trade_brokerage_user"
(
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"bind_user_id" bigint NOT NULL,
"bind_user_time" varchar,
"brokerage_enabled" bit NOT NULL,
"brokerage_time" varchar,
"price" int NOT NULL,
"frozen_price" int NOT NULL,
"creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint NOT NULL DEFAULT '0',
PRIMARY KEY ("id")
) COMMENT '分销用户';
CREATE TABLE IF NOT EXISTS "trade_brokerage_record"
(
"id" int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"user_id" bigint NOT NULL,
"biz_id" varchar NOT NULL,
"biz_type" varchar NOT NULL,
"title" varchar NOT NULL,
"price" int NOT NULL,
"total_price" int NOT NULL,
"description" varchar NOT NULL,
"status" varchar NOT NULL,
"frozen_days" int NOT NULL,
"unfreeze_time" varchar,
"creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
PRIMARY KEY ("id")
) COMMENT '佣金记录';
CREATE TABLE IF NOT EXISTS "trade_brokerage_withdraw"
(
"id" int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"user_id" bigint NOT NULL,
"price" int NOT NULL,
"fee_price" int NOT NULL,
"total_price" int NOT NULL,
"type" varchar NOT NULL,
"name" varchar,
"account_no" varchar,
"bank_name" varchar,
"bank_address" varchar,
"account_qr_code_url" varchar,
"status" varchar NOT NULL,
"audit_reason" varchar,
"audit_time" varchar,
"remark" varchar,
"creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
PRIMARY KEY ("id")
) COMMENT '佣金提现';