trade:【交易售后】增加申请售后的单元测试

pull/2/head
YunaiV 2022-11-19 14:34:59 +08:00
parent af71a19241
commit 73b92190c6
10 changed files with 199 additions and 49 deletions

View File

@ -18,14 +18,14 @@ public class ProductSkuRespDTO {
* SKU * SKU
*/ */
private Long id; private Long id;
/**
* SPU
*/
private String name;
/** /**
* SPU * SPU
*/ */
private Long spuId; private Long spuId;
/**
* SPU
*/
private String spuName;
/** /**
* JSON * JSON

View File

@ -27,6 +27,7 @@ import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueServ
import cn.iocoder.yudao.module.product.service.sku.ProductSkuServiceImpl; import cn.iocoder.yudao.module.product.service.sku.ProductSkuServiceImpl;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;

View File

@ -18,14 +18,19 @@ public class AppTradeAfterSaleCreateReqVO {
@NotNull(message = "订单项编号不能为空") @NotNull(message = "订单项编号不能为空")
private Long orderItemId; private Long orderItemId;
@ApiModelProperty(name = "售后类型", required = true, example = "1", notes = "对应 TradeAfterSaleTypeEnum 枚举")
@NotNull(message = "售后类型不能为空")
@InEnum(value = TradeAfterSaleTypeEnum.class, message = "售后类型必须是 {value}")
private Integer type;
@ApiModelProperty(name = "退款金额", required = true, example = "100", notes = "单位:分") @ApiModelProperty(name = "退款金额", required = true, example = "100", notes = "单位:分")
@NotNull(message = "退款金额不能为空") @NotNull(message = "退款金额不能为空")
@Min(value = 1, message = "退款金额必须大于 0") @Min(value = 1, message = "退款金额必须大于 0")
private Integer applyPrice; private Integer refundPrice;
@ApiModelProperty(name = "申请原因", required = true, example = "1", notes = "使用数据字典枚举,对应 trade_refund_apply_reason 类型") @ApiModelProperty(name = "申请原因", required = true, example = "1", notes = "使用数据字典枚举,对应 trade_refund_apply_reason 类型")
@NotNull(message = "申请原因不能为空") @NotNull(message = "申请原因不能为空")
private Integer applyReason; private String applyReason;
@ApiModelProperty(name = "补充描述", example = "商品质量不好") @ApiModelProperty(name = "补充描述", example = "商品质量不好")
private String applyDescription; private String applyDescription;
@ -33,9 +38,4 @@ public class AppTradeAfterSaleCreateReqVO {
@ApiModelProperty(name = "补充凭证图片", example = "https://www.iocoder.cn/1.png, https://www.iocoder.cn/2.png") @ApiModelProperty(name = "补充凭证图片", example = "https://www.iocoder.cn/1.png, https://www.iocoder.cn/2.png")
private List<String> applyPicUrls; private List<String> applyPicUrls;
@ApiModelProperty(name = "售后类型", required = true, example = "1", notes = "对应 TradeAfterSaleTypeEnum 枚举")
@NotNull(message = "售后类型不能为空")
@InEnum(value = TradeAfterSaleTypeEnum.class, message = "售后类型必须是 {value}")
private Integer type;
} }

View File

@ -20,7 +20,7 @@ import java.util.List;
* *
* @author * @author
*/ */
@TableName(value = "trade_after_sale") @TableName(value = "trade_after_sale", autoResultMap = true)
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Accessors(chain = true) @Accessors(chain = true)
@ -57,9 +57,10 @@ public class TradeAfterSaleDO extends BaseDO {
/** /**
* *
* *
* 使 trade_refund_apply_reason * type = 退 trade_after_sale_refund_reason
* type = 退退 trade_after_sale_refund_and_return_reason
*/ */
private Integer applyReason; private String applyReason;
/** /**
* *
*/ */
@ -72,25 +73,6 @@ public class TradeAfterSaleDO extends BaseDO {
@TableField(typeHandler = JacksonTypeHandler.class) @TableField(typeHandler = JacksonTypeHandler.class)
private List<String> applyPicUrls; private List<String> applyPicUrls;
// ========== 商家相关 ==========
/**
*
*/
private LocalDateTime auditTime;
/**
*
*
* AdminUserDO id
*/
private Long auditUserId;
/**
*
*
*
*/
private String auditReason;
// ========== 交易订单相关 ========== // ========== 交易订单相关 ==========
/** /**
* *
@ -107,20 +89,60 @@ public class TradeAfterSaleDO extends BaseDO {
/** /**
* SPU * SPU
* *
* ProductSpuDO * ProductSpuDO id
* {@link TradeOrderItemDO#getSpuId()}
*/ */
private Long spuId; private Long spuId;
/**
* SPU
*
* ProductSkuDO name
* {@link TradeOrderItemDO#getSpuName()}
*/
private String spuName;
/** /**
* SKU * SKU
* *
* ProductSkuDO * ProductSkuDO
*/ */
private Integer skuId; private Long skuId;
/**
* JSON
*
* {@link TradeOrderItemDO#getProperties()}
*/
@TableField(typeHandler = TradeOrderItemDO.PropertyTypeHandler.class)
private List<TradeOrderItemDO.Property> properties;
/**
*
*
* {@link TradeOrderItemDO#getPicUrl()}
*/
private String picUrl;
/** /**
* 退 * 退
*/ */
private Integer count; private Integer count;
// ========== 审批相关 ==========
/**
*
*/
private LocalDateTime auditTime;
/**
*
*
* AdminUserDO id
*/
private Long auditUserId;
/**
*
*
*
*/
private String auditReason;
// ========== 退款相关 ========== // ========== 退款相关 ==========
/** /**
* 退 * 退

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.order;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
@ -41,13 +42,19 @@ public class TradeOrderItemDO extends BaseDO {
*/ */
private Long orderId; private Long orderId;
// ========== 商品基本信息 ========== // ========== 商品基本信息; 冗余较多字段,减少关联查询 ==========
/** /**
* SPU * SPU
* *
* ProductSkuDO spuId * ProductSkuDO spuId
*/ */
private Long spuId; private Long spuId;
/**
* SPU
*
* ProductSkuDO spuName
*/
private String spuName;
/** /**
* SKU * SKU
* *
@ -56,15 +63,11 @@ public class TradeOrderItemDO extends BaseDO {
private Long skuId; private Long skuId;
/** /**
* JSON * JSON
*
* ProductSkuDO properties
*/ */
@TableField(typeHandler = PropertyTypeHandler.class) @TableField(typeHandler = PropertyTypeHandler.class)
private List<Property> properties; private List<Property> properties;
/**
*
*
* ProductSpuDO name
*/
private String name;
/** /**
* *
*/ */
@ -142,7 +145,7 @@ public class TradeOrderItemDO extends BaseDO {
* *
* {@link TradeOrderItemAfterSaleStatusEnum} * {@link TradeOrderItemAfterSaleStatusEnum}
* *
* @see cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO * @see TradeAfterSaleDO
*/ */
private Integer afterSaleStatus; private Integer afterSaleStatus;

View File

@ -84,7 +84,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
// TODO 芋艿:超过一定时间,不允许售后 // TODO 芋艿:超过一定时间,不允许售后
// 申请的退款金额,不能超过商品的价格 // 申请的退款金额,不能超过商品的价格
if (createReqVO.getApplyPrice() > orderItem.getOrderDividePrice()) { if (createReqVO.getRefundPrice() > orderItem.getOrderDividePrice()) {
throw exception(AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR); throw exception(AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR);
} }

View File

@ -0,0 +1,87 @@
package cn.iocoder.yudao.module.trade.service.aftersale;
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.app.aftersale.vo.AppTradeAfterSaleCreateReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
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.TradeAfterSaleMapper;
import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum;
import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleTypeEnum;
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.TradeOrderService;
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 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 TradeAfterSaleService}
*
* @author
*/
@Import(TradeAfterSaleServiceImpl.class)
public class TradeAfterSaleServiceTest extends BaseDbUnitTest {
@Resource
private TradeAfterSaleServiceImpl tradeAfterSaleService;
@Resource
private TradeAfterSaleMapper tradeAfterSaleMapper;
@MockBean
private TradeOrderService tradeOrderService;
@MockBean
private PayRefundApi payRefundApi;
@MockBean
private TradeOrderProperties tradeOrderProperties;
@Test
public void testCreateAfterSale() {
// 准备参数
Long userId = 1024L;
AppTradeAfterSaleCreateReqVO createReqVO = new AppTradeAfterSaleCreateReqVO()
.setOrderItemId(1L).setRefundPrice(100).setType(TradeAfterSaleTypeEnum.RETURN_AND_REFUND.getType())
.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).setOrderDividePrice(200);
o.setAfterSaleStatus(TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
});
when(tradeOrderService.getOrderItem(eq(1024L), eq(1L)))
.thenReturn(orderItem);
// mock 方法(交易订单)
TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> o.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()));
when(tradeOrderService.getOrder(eq(1024L), eq(111L))).thenReturn(order);
// 调用
Long afterSaleId = tradeAfterSaleService.createAfterSale(userId, createReqVO);
// 断言
TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(afterSaleId);
assertNotNull(afterSale.getNo());
assertEquals(afterSale.getStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus());
assertPojoEquals(afterSale, createReqVO);
assertEquals(afterSale.getUserId(), 1024L);
assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime");
assertNull(afterSale.getPayRefundId());
assertNull(afterSale.getRefundTime());
assertNull(afterSale.getLogisticsId());
assertNull(afterSale.getLogisticsNo());
assertNull(afterSale.getDeliveryTime());
assertNull(afterSale.getReceiveReason());
}
}

View File

@ -51,7 +51,7 @@ import static org.mockito.Mockito.when;
* @since 2022-09-07 * @since 2022-09-07
*/ */
@Import({TradeOrderServiceImpl.class, TradeOrderConfig.class}) @Import({TradeOrderServiceImpl.class, TradeOrderConfig.class})
class TradeOrderServiceTest extends BaseDbUnitTest { public class TradeOrderServiceTest extends BaseDbUnitTest {
@Resource @Resource
private TradeOrderServiceImpl tradeOrderService; private TradeOrderServiceImpl tradeOrderService;
@ -196,7 +196,7 @@ class TradeOrderServiceTest extends BaseDbUnitTest {
assertEquals(tradeOrderItemDO01.getProperties().size(), 1); assertEquals(tradeOrderItemDO01.getProperties().size(), 1);
assertEquals(tradeOrderItemDO01.getProperties().get(0).getPropertyId(), 111L); assertEquals(tradeOrderItemDO01.getProperties().get(0).getPropertyId(), 111L);
assertEquals(tradeOrderItemDO01.getProperties().get(0).getValueId(), 222L); assertEquals(tradeOrderItemDO01.getProperties().get(0).getValueId(), 222L);
assertEquals(tradeOrderItemDO01.getName(), sku01.getName()); assertEquals(tradeOrderItemDO01.getSpuName(), sku01.getSpuName());
assertEquals(tradeOrderItemDO01.getPicUrl(), sku01.getPicUrl()); assertEquals(tradeOrderItemDO01.getPicUrl(), sku01.getPicUrl());
assertEquals(tradeOrderItemDO01.getCount(), 3); assertEquals(tradeOrderItemDO01.getCount(), 3);
assertEquals(tradeOrderItemDO01.getOriginalPrice(), 150); assertEquals(tradeOrderItemDO01.getOriginalPrice(), 150);
@ -216,7 +216,7 @@ class TradeOrderServiceTest extends BaseDbUnitTest {
assertEquals(tradeOrderItemDO02.getProperties().size(), 1); assertEquals(tradeOrderItemDO02.getProperties().size(), 1);
assertEquals(tradeOrderItemDO02.getProperties().get(0).getPropertyId(), 333L); assertEquals(tradeOrderItemDO02.getProperties().get(0).getPropertyId(), 333L);
assertEquals(tradeOrderItemDO02.getProperties().get(0).getValueId(), 444L); assertEquals(tradeOrderItemDO02.getProperties().get(0).getValueId(), 444L);
assertEquals(tradeOrderItemDO02.getName(), sku02.getName()); assertEquals(tradeOrderItemDO02.getSpuName(), sku02.getSpuName());
assertEquals(tradeOrderItemDO02.getPicUrl(), sku02.getPicUrl()); assertEquals(tradeOrderItemDO02.getPicUrl(), sku02.getPicUrl());
assertEquals(tradeOrderItemDO02.getCount(), 4); assertEquals(tradeOrderItemDO02.getCount(), 4);
assertEquals(tradeOrderItemDO02.getOriginalPrice(), 80); assertEquals(tradeOrderItemDO02.getOriginalPrice(), 80);

View File

@ -1,2 +1,3 @@
DELETE FROM trade_order; DELETE FROM trade_order;
DELETE FROM trade_order_item; DELETE FROM trade_order_item;
DELETE FROM trade_after_sale;

View File

@ -50,9 +50,9 @@ CREATE TABLE IF NOT EXISTS "trade_order_item" (
"user_id" bigint NOT NULL, "user_id" bigint NOT NULL,
"order_id" bigint NOT NULL, "order_id" bigint NOT NULL,
"spu_id" bigint NOT NULL, "spu_id" bigint NOT NULL,
"spu_name" varchar NOT NULL,
"sku_id" bigint NOT NULL, "sku_id" bigint NOT NULL,
"properties" varchar, "properties" varchar,
"name" varchar NOT NULL,
"pic_url" varchar, "pic_url" varchar,
"count" int NOT NULL, "count" int NOT NULL,
"original_price" int NOT NULL, "original_price" int NOT NULL,
@ -69,3 +69,39 @@ CREATE TABLE IF NOT EXISTS "trade_order_item" (
"deleted" bit NOT NULL DEFAULT FALSE, "deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id") PRIMARY KEY ("id")
) COMMENT ''; ) 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,
"user_id" bigint NOT NULL,
"apply_reason" varchar NOT NULL,
"apply_description" varchar,
"apply_pic_urls" varchar,
"order_id" bigint 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 '';