mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 09:11:52 +08:00
trade:创建订单接口的后端实现的单元测试 50%
This commit is contained in:
parent
01d10b518c
commit
bc2aa78f70
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.convert.order;
|
|||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
|
import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
|
||||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||||
@ -33,7 +34,7 @@ public interface TradeOrderConvert {
|
|||||||
@Mapping(source = "address.postCode", target = "receiverPostCode"),
|
@Mapping(source = "address.postCode", target = "receiverPostCode"),
|
||||||
@Mapping(source = "address.detailAddress", target = "receiverDetailAddress"),
|
@Mapping(source = "address.detailAddress", target = "receiverDetailAddress"),
|
||||||
})
|
})
|
||||||
TradeOrderDO convert(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO,
|
TradeOrderDO convert(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO,
|
||||||
PriceCalculateRespDTO.Order order, AddressRespDTO address);
|
PriceCalculateRespDTO.Order order, AddressRespDTO address);
|
||||||
|
|
||||||
@Mappings({
|
@Mappings({
|
||||||
@ -49,10 +50,13 @@ public interface TradeOrderConvert {
|
|||||||
TradeOrderItemDO tradeOrderItemDO = convert(orderItem, skuMap.get(orderItem.getSkuId()));
|
TradeOrderItemDO tradeOrderItemDO = convert(orderItem, skuMap.get(orderItem.getSkuId()));
|
||||||
tradeOrderItemDO.setOrderId(tradeOrderDO.getId());
|
tradeOrderItemDO.setOrderId(tradeOrderDO.getId());
|
||||||
tradeOrderItemDO.setUserId(tradeOrderDO.getUserId());
|
tradeOrderItemDO.setUserId(tradeOrderDO.getUserId());
|
||||||
tradeOrderItemDO.setRefundStatus(TradeOrderItemRefundStatusEnum.NONE.getStatus());
|
tradeOrderItemDO.setRefundStatus(TradeOrderItemRefundStatusEnum.NONE.getStatus()).setRefundTotal(0); // 退款信息
|
||||||
// tradeOrderItemDO.setCommented(false);
|
// tradeOrderItemDO.setCommented(false);
|
||||||
return tradeOrderItemDO;
|
return tradeOrderItemDO;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mapping(source = "userId" , target = "userId")
|
||||||
|
PriceCalculateReqDTO convert(AppTradeOrderCreateReqVO createReqVO, Long userId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.trade.convert.price;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
|
||||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
|
||||||
import org.mapstruct.Mapper;
|
|
||||||
import org.mapstruct.Mapping;
|
|
||||||
import org.mapstruct.Mappings;
|
|
||||||
import org.mapstruct.factory.Mappers;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface PriceConvert {
|
|
||||||
|
|
||||||
PriceConvert INSTANCE = Mappers.getMapper(PriceConvert.class);
|
|
||||||
|
|
||||||
@Mappings(
|
|
||||||
@Mapping(source = "userId" , target = "userId")
|
|
||||||
)
|
|
||||||
PriceCalculateReqDTO convert(AppTradeOrderCreateReqVO createReqVO, Long userId);
|
|
||||||
|
|
||||||
}
|
|
@ -138,19 +138,19 @@ public class TradeOrderItemDO extends BaseDO {
|
|||||||
* 枚举 {@link TradeOrderItemRefundStatusEnum}
|
* 枚举 {@link TradeOrderItemRefundStatusEnum}
|
||||||
*/
|
*/
|
||||||
private Integer refundStatus; // TODO 芋艿:可以考虑去查
|
private Integer refundStatus; // TODO 芋艿:可以考虑去查
|
||||||
// // 如上字段,举个例子:
|
// 如上字段,举个例子:
|
||||||
// // 假设购买三个,即 stock = 3 。
|
// 假设购买三个,即 stock = 3 。
|
||||||
// // originPrice = 15
|
// originPrice = 15
|
||||||
// // 使用限时折扣(单品优惠)8 折,buyPrice = 12
|
// 使用限时折扣(单品优惠)8 折,buyPrice = 12
|
||||||
// // 开始算总的价格
|
// 开始算总的价格
|
||||||
// // buyTotal = buyPrice * stock = 12 * 3 = 36
|
// buyTotal = buyPrice * stock = 12 * 3 = 36
|
||||||
// // discountTotal ,假设有满减送(分组优惠)满 20 减 10 ,并且使用优惠劵满 1.01 减 1 ,则 discountTotal = 10 + 1 = 11
|
// discountTotal ,假设有满减送(分组优惠)满 20 减 10 ,并且使用优惠劵满 1.01 减 1 ,则 discountTotal = 10 + 1 = 11
|
||||||
// // presentTotal = buyTotal - discountTotal = 24 - 11 = 13
|
// presentTotal = buyTotal - discountTotal = 24 - 11 = 13
|
||||||
// // 最终 presentPrice = presentTotal / stock = 13 / 3 = 4.33
|
// 最终 presentPrice = presentTotal / stock = 13 / 3 = 4.33
|
||||||
// /**
|
/**
|
||||||
// * 退款总金额,单位:分 TODO
|
* 退款总金额,单位:分 TODO
|
||||||
// */
|
*/
|
||||||
// private Integer refundTotal;
|
private Integer refundTotal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品属性
|
* 商品属性
|
||||||
|
@ -14,9 +14,10 @@ public interface TradeOrderService {
|
|||||||
* 创建交易订单
|
* 创建交易订单
|
||||||
*
|
*
|
||||||
* @param loginUserId 登录用户
|
* @param loginUserId 登录用户
|
||||||
* @param clientIp 用户 IP 地址
|
* @param userIp 用户 IP 地址
|
||||||
* @param createReqVO 创建交易订单请求模型
|
* @param createReqVO 创建交易订单请求模型
|
||||||
* @return 交易订单的编号
|
* @return 交易订单的编号
|
||||||
*/
|
*/
|
||||||
Long createTradeOrder(Long loginUserId, String clientIp, AppTradeOrderCreateReqVO createReqVO);
|
Long createTradeOrder(Long loginUserId, String userIp, AppTradeOrderCreateReqVO createReqVO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,10 @@ 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.api.spu.dto.ProductSpuRespDTO;
|
||||||
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
|
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
|
||||||
import cn.iocoder.yudao.module.promotion.api.price.PriceApi;
|
import cn.iocoder.yudao.module.promotion.api.price.PriceApi;
|
||||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
|
||||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO.Item;
|
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO.Item;
|
||||||
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
|
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
|
||||||
import cn.iocoder.yudao.module.trade.convert.price.PriceConvert;
|
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
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.dataobject.order.TradeOrderItemDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
|
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
|
||||||
@ -82,20 +80,19 @@ public class TradeOrderServiceImpl implements TradeOrderService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Long createTradeOrder(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO) {
|
public Long createTradeOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) {
|
||||||
// 商品 SKU 检查:可售状态、库存
|
// 商品 SKU 检查:可售状态、库存
|
||||||
List<ProductSkuRespDTO> skus = validateSkuSaleable(createReqVO.getItems());
|
List<ProductSkuRespDTO> skus = validateSkuSaleable(createReqVO.getItems());
|
||||||
// 商品 SPU 检查:可售状态
|
// 商品 SPU 检查:可售状态
|
||||||
List<ProductSpuRespDTO> spus = validateSpuSaleable(convertSet(skus, ProductSkuRespDTO::getSpuId));
|
validateSpuSaleable(convertSet(skus, ProductSkuRespDTO::getSpuId));
|
||||||
// 用户收件地址的校验
|
// 用户收件地址的校验
|
||||||
AddressRespDTO address = validateAddress(userId, createReqVO.getAddressId());
|
AddressRespDTO address = validateAddress(userId, createReqVO.getAddressId());
|
||||||
|
|
||||||
// 价格计算
|
// 价格计算
|
||||||
PriceCalculateReqDTO priceCalculateReqDTO = PriceConvert.INSTANCE.convert(createReqVO, userId);
|
PriceCalculateRespDTO priceResp = priceApi.calculatePrice(TradeOrderConvert.INSTANCE.convert(createReqVO, userId));
|
||||||
PriceCalculateRespDTO priceResp = priceApi.calculatePrice(priceCalculateReqDTO);
|
|
||||||
|
|
||||||
// 插入 TradeOrderDO 订单
|
// 插入 TradeOrderDO 订单
|
||||||
TradeOrderDO tradeOrderDO = createTradeOrder(userId, clientIp, createReqVO, priceResp.getOrder(), address);
|
TradeOrderDO tradeOrderDO = createTradeOrder(userId, userIp, createReqVO, priceResp.getOrder(), address);
|
||||||
// 插入 TradeOrderItemDO 订单项
|
// 插入 TradeOrderItemDO 订单项
|
||||||
createTradeOrderItems(tradeOrderDO, priceResp.getOrder().getItems(), skus);
|
createTradeOrderItems(tradeOrderDO, priceResp.getOrder().getItems(), skus);
|
||||||
|
|
||||||
@ -208,7 +205,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
|
|||||||
// 校验是否存在禁用的 SPU
|
// 校验是否存在禁用的 SPU
|
||||||
ProductSpuRespDTO spu = CollectionUtils.findFirst(spus,
|
ProductSpuRespDTO spu = CollectionUtils.findFirst(spus,
|
||||||
spuDTO -> ObjectUtil.notEqual(ProductSpuStatusEnum.ENABLE.getStatus(), spuDTO.getStatus()));
|
spuDTO -> ObjectUtil.notEqual(ProductSpuStatusEnum.ENABLE.getStatus(), spuDTO.getStatus()));
|
||||||
if (Objects.isNull(spu)) {
|
if (spu != null) {
|
||||||
throw exception(ErrorCodeConstants.ORDER_CREATE_SPU_NOT_SALE);
|
throw exception(ErrorCodeConstants.ORDER_CREATE_SPU_NOT_SALE);
|
||||||
}
|
}
|
||||||
return spus;
|
return spus;
|
||||||
@ -238,6 +235,9 @@ public class TradeOrderServiceImpl implements TradeOrderService {
|
|||||||
tradeOrderDO.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus());
|
tradeOrderDO.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus());
|
||||||
tradeOrderDO.setProductCount(getSumValue(order.getItems(), PriceCalculateRespDTO.OrderItem::getCount, Integer::sum));
|
tradeOrderDO.setProductCount(getSumValue(order.getItems(), PriceCalculateRespDTO.OrderItem::getCount, Integer::sum));
|
||||||
tradeOrderDO.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源?
|
tradeOrderDO.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源?
|
||||||
|
tradeOrderDO.setAdjustPrice(0).setPayed(false); // 支付信息
|
||||||
|
tradeOrderDO.setDeliveryStatus(false); // 物流信息
|
||||||
|
tradeOrderDO.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0); // 退款信息
|
||||||
tradeOrderMapper.insert(tradeOrderDO);
|
tradeOrderMapper.insert(tradeOrderDO);
|
||||||
return tradeOrderDO;
|
return tradeOrderDO;
|
||||||
}
|
}
|
||||||
|
@ -1,110 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.trade.service.order;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
|
||||||
import cn.iocoder.yudao.module.promotion.api.price.PriceApi;
|
|
||||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
|
||||||
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
|
|
||||||
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.SpuInfoRespDTO;
|
|
||||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
|
||||||
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.order.TradeOrderMapper;
|
|
||||||
import cn.iocoder.yudao.module.trade.dal.mysql.orderitem.TradeOrderItemMapper;
|
|
||||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
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.util.Collections;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomInteger;
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
// TODO @芋艿: 单测的 review; 最后搞;
|
|
||||||
/**
|
|
||||||
* @author LeeYan9
|
|
||||||
* @since 2022-09-07
|
|
||||||
*/
|
|
||||||
@Import({TradeOrderServiceImpl.class, TradeOrderConfig.class})
|
|
||||||
class TradeOrderServiceTest extends BaseDbUnitTest {
|
|
||||||
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
TradeOrderService tradeOrderService;
|
|
||||||
@Resource
|
|
||||||
TradeOrderMapper tradeOrderMapper;
|
|
||||||
@Resource
|
|
||||||
TradeOrderItemMapper tradeOrderItemMapper;
|
|
||||||
@MockBean
|
|
||||||
ProductSpuApi productSpuApi;
|
|
||||||
@MockBean
|
|
||||||
ProductSkuApi productSkuApi;
|
|
||||||
@MockBean
|
|
||||||
PriceApi priceApi;
|
|
||||||
@MockBean
|
|
||||||
private PayOrderApi payOrderApi;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testCreateTradeOrder_success() {
|
|
||||||
// mock 商品SPU数据
|
|
||||||
SpuInfoRespDTO spuInfoRespDTO = randomPojo(SpuInfoRespDTO.class, spuInfo -> {
|
|
||||||
spuInfo.setId(1L);
|
|
||||||
spuInfo.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
|
||||||
});
|
|
||||||
when(productSpuApi.getSpuList(Collections.singleton(1L))).thenReturn(Lists.newArrayList(spuInfoRespDTO));
|
|
||||||
// mock 商品SkU数据
|
|
||||||
ProductSkuRespDTO skuInfoRespDTO = randomPojo(ProductSkuRespDTO.class, skuInfo -> {
|
|
||||||
skuInfo.setId(1L);
|
|
||||||
skuInfo.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
|
||||||
skuInfo.setStock(randomInteger());
|
|
||||||
skuInfo.setSpuId(1L);
|
|
||||||
});
|
|
||||||
when(productSkuApi.getSkuList(Collections.singleton(1L))).thenReturn(Lists.newArrayList(skuInfoRespDTO));
|
|
||||||
// mock 价格信息
|
|
||||||
PriceCalculateRespDTO calculateRespDTO = randomPojo(PriceCalculateRespDTO.class, priceCalculateRespDTO -> {
|
|
||||||
PriceCalculateRespDTO.OrderItem item = priceCalculateRespDTO.getOrder().getItems().get(0);
|
|
||||||
item.setSkuId(1L);
|
|
||||||
item.setCount(2);
|
|
||||||
priceCalculateRespDTO.getOrder().setItems(Collections.singletonList(item));
|
|
||||||
});
|
|
||||||
when(priceApi.calculatePrice(any())).thenReturn(calculateRespDTO);
|
|
||||||
//mock 支付订单信息
|
|
||||||
when(payOrderApi.createPayOrder(any())).thenReturn(1L);
|
|
||||||
|
|
||||||
// 准备请求数据
|
|
||||||
AppTradeOrderCreateReqVO tradeOrderCreateReqVO = randomPojo(AppTradeOrderCreateReqVO.class, reqVO -> {
|
|
||||||
AppTradeOrderCreateReqVO.Item item = randomPojo(AppTradeOrderCreateReqVO.Item.class, o -> {
|
|
||||||
o.setSkuId(1L);
|
|
||||||
o.setCount(2);
|
|
||||||
});
|
|
||||||
reqVO.setItems(Collections.singletonList(item));
|
|
||||||
});
|
|
||||||
// 创建交易订单,支付订单记录
|
|
||||||
Long payOrderId = tradeOrderService.createTradeOrder(1L, "127.0.0.1", tradeOrderCreateReqVO);
|
|
||||||
//断言交易订单
|
|
||||||
TradeOrderDO tradeOrderDO = tradeOrderMapper.selectOne(TradeOrderDO::getUserId, 1L);
|
|
||||||
assertNotNull(tradeOrderDO);
|
|
||||||
//价格&用户
|
|
||||||
assertEquals(calculateRespDTO.getOrder().getPayPrice(), tradeOrderDO.getPayPrice());
|
|
||||||
assertEquals(1L, tradeOrderDO.getUserId());
|
|
||||||
//断言交易订单项
|
|
||||||
TradeOrderItemDO tradeOrderItemDO = tradeOrderItemMapper.selectOne(TradeOrderItemDO::getOrderId, tradeOrderDO.getId());
|
|
||||||
assertNotNull(tradeOrderDO);
|
|
||||||
//商品&用户
|
|
||||||
assertEquals(skuInfoRespDTO.getId(), tradeOrderItemDO.getSkuId());
|
|
||||||
assertEquals(1L, tradeOrderItemDO.getUserId());
|
|
||||||
//价格
|
|
||||||
assertEquals(calculateRespDTO.getOrder().getItems().get(0).getPresentPrice(), tradeOrderItemDO.getPresentPrice());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
/**todo cancelType 设置默认值 0?*/
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `trade_order`
|
|
||||||
(
|
|
||||||
`id` number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
||||||
`sn` varchar(32) NOT NULL,
|
|
||||||
`type` int NOT NULL,
|
|
||||||
`terminal` int NOT NULL,
|
|
||||||
`user_id` bigint unsigned NOT NULL,
|
|
||||||
`user_ip` varchar(30) NOT NULL,
|
|
||||||
`user_remark` varchar(200),
|
|
||||||
`status` int NOT NULL,
|
|
||||||
`product_count` int NOT NULL,
|
|
||||||
`cancel_type` int DEFAULT NULL,
|
|
||||||
`remark` varchar(200),
|
|
||||||
`payed` bit(1) NOT NULL DEFAULT FALSE,
|
|
||||||
`pay_time` datetime DEFAULT NULL,
|
|
||||||
`finish_time` datetime DEFAULT NULL,
|
|
||||||
`cancel_time` datetime DEFAULT NULL,
|
|
||||||
`sku_original_price` int NOT NULL DEFAULT '0',
|
|
||||||
`sku_promotion_price` int NOT NULL DEFAULT '0',
|
|
||||||
`order_promotion_price` int NOT NULL DEFAULT '0',
|
|
||||||
`delivery_price` int NOT NULL DEFAULT '0',
|
|
||||||
`pay_price` int DEFAULT '0',
|
|
||||||
`pay_order_id` int DEFAULT NULL,
|
|
||||||
`pay_channel` int DEFAULT NULL,
|
|
||||||
`delivery_type` int NOT NULL DEFAULT '1',
|
|
||||||
`actual_delivery_type` int NOT NULL DEFAULT '1',
|
|
||||||
`delivery_template_id` int DEFAULT NULL,
|
|
||||||
`express_no` int DEFAULT NULL,
|
|
||||||
`delivery_status` bit(1) NOT NULL DEFAULT FALSE,
|
|
||||||
`delivery_time` datetime DEFAULT NULL,
|
|
||||||
`receive_time` datetime DEFAULT NULL,
|
|
||||||
`receiver_name` varchar(20) DEFAULT NULL,
|
|
||||||
`receiver_mobile` varchar(20) DEFAULT NULL,
|
|
||||||
`receiver_area_id` int DEFAULT NULL,
|
|
||||||
`receiver_post_code` int DEFAULT NULL,
|
|
||||||
`receiver_detail_address` varchar(255) DEFAULT NULL,
|
|
||||||
`refund_status` int NOT NULL DEFAULT '0',
|
|
||||||
`refund_price` int NOT NULL DEFAULT '0',
|
|
||||||
`coupon_id` bigint unsigned DEFAULT NULL,
|
|
||||||
`creator` varchar(64) DEFAULT '',
|
|
||||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`updater` varchar(64) DEFAULT '',
|
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
`deleted` bit(1) NOT NULL DEFAULT FALSE,
|
|
||||||
PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `trade_order_item`
|
|
||||||
(
|
|
||||||
`id` number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
||||||
`user_id` bigint unsigned NOT NULL,
|
|
||||||
`order_id` bigint unsigned NOT NULL,
|
|
||||||
`spu_id` bigint unsigned NOT NULL,
|
|
||||||
`sku_id` bigint unsigned NOT NULL,
|
|
||||||
`properties` json DEFAULT NULL,
|
|
||||||
`name` varchar(128) DEFAULT NULL,
|
|
||||||
`pic_url` varchar(200) DEFAULT NULL,
|
|
||||||
`count` int NOT NULL,
|
|
||||||
`commented` bit(1) DEFAULT NULL,
|
|
||||||
`original_price` int NOT NULL DEFAULT '0',
|
|
||||||
`total_original_price` int NOT NULL DEFAULT '0',
|
|
||||||
`total_promotion_price` int NOT NULL DEFAULT '0',
|
|
||||||
`present_price` int NOT NULL DEFAULT '0',
|
|
||||||
`total_present_price` int NOT NULL DEFAULT '0',
|
|
||||||
`total_pay_price` int NOT NULL DEFAULT '0',
|
|
||||||
`refund_status` int NOT NULL DEFAULT '0',
|
|
||||||
`refund_total` int NOT NULL DEFAULT '0',
|
|
||||||
`creator` varchar(64) DEFAULT '',
|
|
||||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`updater` varchar(64) DEFAULT '',
|
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
`deleted` bit(1) DEFAULT FALSE,
|
|
||||||
PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
@ -0,0 +1,145 @@
|
|||||||
|
package cn.iocoder.yudao.module.trade.service.order;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
|
import cn.iocoder.yudao.module.member.api.address.AddressApi;
|
||||||
|
import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
|
||||||
|
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.promotion.api.price.PriceApi;
|
||||||
|
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
|
||||||
|
import cn.iocoder.yudao.module.trade.dal.mysql.orderitem.TradeOrderItemMapper;
|
||||||
|
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig;
|
||||||
|
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.util.Arrays;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
||||||
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link TradeOrderServiceImpl} 的单元测试类
|
||||||
|
*
|
||||||
|
* @author LeeYan9
|
||||||
|
* @since 2022-09-07
|
||||||
|
*/
|
||||||
|
@Import({TradeOrderServiceImpl.class, TradeOrderConfig.class})
|
||||||
|
class TradeOrderServiceTest extends BaseDbUnitTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TradeOrderServiceImpl tradeOrderService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TradeOrderMapper tradeOrderMapper;
|
||||||
|
@Resource
|
||||||
|
private TradeOrderItemMapper tradeOrderItemMapper;
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private ProductSpuApi productSpuApi;
|
||||||
|
@MockBean
|
||||||
|
private ProductSkuApi productSkuApi;
|
||||||
|
@MockBean
|
||||||
|
private PriceApi priceApi;
|
||||||
|
@MockBean
|
||||||
|
private PayOrderApi payOrderApi;
|
||||||
|
@MockBean
|
||||||
|
private AddressApi addressApi;
|
||||||
|
|
||||||
|
// 1, 3 个,50 块;打折 20;总和 = 60;42;
|
||||||
|
// 2, 4 个,20 块;打折 10;总和 = 40;28;
|
||||||
|
// 优惠劵,满 100 减 30
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateTradeOrder_success() {
|
||||||
|
// 准备参数
|
||||||
|
Long userId = 100L;
|
||||||
|
String clientIp = "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)));
|
||||||
|
// mock 方法(商品 SKU 检查)
|
||||||
|
ProductSkuRespDTO sku01 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(1L).setSpuId(11L)
|
||||||
|
.setPrice(50).setStock(100).setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
||||||
|
ProductSkuRespDTO sku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(2L).setSpuId(21L)
|
||||||
|
.setPrice(20).setStock(50).setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
||||||
|
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()));
|
||||||
|
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 方法(用户收件地址的校验)
|
||||||
|
AddressRespDTO addressRespDTO = new AddressRespDTO().setId(10L).setUserId(userId).setName("芋艿")
|
||||||
|
.setMobile("15601691300").setAreaId(3306L).setPostCode("85757").setDetailAddress("土豆村");
|
||||||
|
when(addressApi.getAddress(eq(userId), eq(10L))).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()
|
||||||
|
.setOriginalPrice(230).setOrderPrice(100).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));
|
||||||
|
|
||||||
|
// 调用方法
|
||||||
|
Long tradeOrderId = tradeOrderService.createTradeOrder(userId, clientIp, reqVO);
|
||||||
|
System.out.println(tradeOrderId);
|
||||||
|
|
||||||
|
// // mock 价格信息
|
||||||
|
// PriceCalculateRespDTO calculateRespDTO = randomPojo(PriceCalculateRespDTO.class, priceCalculateRespDTO -> {
|
||||||
|
// PriceCalculateRespDTO.OrderItem item = priceCalculateRespDTO.getOrder().getItems().get(0);
|
||||||
|
// item.setSkuId(1L);
|
||||||
|
// item.setCount(2);
|
||||||
|
// priceCalculateRespDTO.getOrder().setItems(Collections.singletonList(item));
|
||||||
|
// });
|
||||||
|
// when(priceApi.calculatePrice(any())).thenReturn(calculateRespDTO);
|
||||||
|
// //mock 支付订单信息
|
||||||
|
// when(payOrderApi.createPayOrder(any())).thenReturn(1L);
|
||||||
|
|
||||||
|
|
||||||
|
// // 创建交易订单,支付订单记录
|
||||||
|
// Long payOrderId = tradeOrderService.createTradeOrder(1L, "127.0.0.1", tradeOrderCreateReqVO);
|
||||||
|
// //断言交易订单
|
||||||
|
// TradeOrderDO tradeOrderDO = tradeOrderMapper.selectOne(TradeOrderDO::getUserId, 1L);
|
||||||
|
// assertNotNull(tradeOrderDO);
|
||||||
|
// //价格&用户
|
||||||
|
// assertEquals(calculateRespDTO.getOrder().getPayPrice(), tradeOrderDO.getPayPrice());
|
||||||
|
// assertEquals(1L, tradeOrderDO.getUserId());
|
||||||
|
// //断言交易订单项
|
||||||
|
// TradeOrderItemDO tradeOrderItemDO = tradeOrderItemMapper.selectOne(TradeOrderItemDO::getOrderId, tradeOrderDO.getId());
|
||||||
|
// assertNotNull(tradeOrderDO);
|
||||||
|
// //商品&用户
|
||||||
|
// assertEquals(skuInfoRespDTO.getId(), tradeOrderItemDO.getSkuId());
|
||||||
|
// assertEquals(1L, tradeOrderItemDO.getUserId());
|
||||||
|
// //价格
|
||||||
|
// assertEquals(calculateRespDTO.getOrder().getItems().get(0).getPresentPrice(), tradeOrderItemDO.getPresentPrice());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
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,
|
||||||
|
"payed" 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" int,
|
||||||
|
"pay_channel" int,
|
||||||
|
"delivery_templateid" int,
|
||||||
|
"express_no" int,
|
||||||
|
"delivery_status" bit NOT NULL,
|
||||||
|
"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,
|
||||||
|
"refund_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,
|
||||||
|
"sku_id" bigint NOT NULL,
|
||||||
|
"properties" varchar,
|
||||||
|
"name" varchar NOT NULL,
|
||||||
|
"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,
|
||||||
|
"refund_status" int NOT NULL,
|
||||||
|
"refund_total" 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 '交易订单明细表';
|
Loading…
Reference in New Issue
Block a user