!514 mall交易日志封装

* 交易日志封装
* 交易日志封装
* 交易日志模块
This commit is contained in:
陈賝 2023-06-17 14:00:10 +00:00 committed by 芋道源码
parent 35df912be7
commit 59e16795be
20 changed files with 470 additions and 51 deletions

View File

@ -31,6 +31,7 @@
<module>yudao-spring-boot-starter-biz-sms</module>
<module>yudao-spring-boot-starter-biz-pay</module>
<module>yudao-spring-boot-starter-biz-trade</module>
<module>yudao-spring-boot-starter-biz-weixin</module>
<module>yudao-spring-boot-starter-biz-social</module>
<module>yudao-spring-boot-starter-biz-tenant</module>

View File

@ -0,0 +1,81 @@
package cn.iocoder.yudao.framework.common.util.spel;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
/**
* SpelUtil
*
* @author Chopper
* @version v1.0
* 2021-01-11 10:45
*/
public class SpelUtil {
/**
* spel表达式解析器
*/
private static SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
/**
* 参数名发现器
*/
private static DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
/**
* 转换 jspl参数
*
* @param joinPoint
* @param spel
* @return
*/
public static String compileParams(JoinPoint joinPoint, String spel) { //Spel表达式解析日志信息
//获得方法参数名数组
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = parameterNameDiscoverer.getParameterNames(signature.getMethod());
if (parameterNames != null && parameterNames.length > 0) {
EvaluationContext context = new StandardEvaluationContext();
//获取方法参数值
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
//替换spel里的变量值为实际值 比如 #user --> user对象
context.setVariable(parameterNames[i], args[i]);
}
return spelExpressionParser.parseExpression(spel).getValue(context).toString();
}
return "";
}
/**
* 转换 jspl参数
*
* @param joinPoint
* @param spel
* @return
*/
public static String compileParams(JoinPoint joinPoint, Object rvt, String spel) { //Spel表达式解析日志信息
//获得方法参数名数组
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = parameterNameDiscoverer.getParameterNames(signature.getMethod());
if (parameterNames != null && parameterNames.length > 0) {
EvaluationContext context = new StandardEvaluationContext();
//获取方法参数值
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
//替换spel里的变量值为实际值 比如 #user --> user对象
context.setVariable(parameterNames[i], args[i]);
}
context.setVariable("rvt", rvt);
return spelExpressionParser.parseExpression(spel).getValue(context).toString();
}
return "";
}
}

View File

@ -37,7 +37,7 @@
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行操作日志的记录 -->
<artifactId>yudao-module-system-api</artifactId>
<version>${revision}</version>
</dependency>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-framework</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-spring-boot-starter-biz-trade</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>交易模块</description>
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
<!-- Spring 核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行操作日志的记录 -->
<version>${revision}</version>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.framework.trade.config;
import cn.iocoder.yudao.framework.trade.core.annotations.AfterSaleLog;
import cn.iocoder.yudao.framework.trade.core.aop.AfterSaleLogAspect;
import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
@AutoConfiguration
public class YudaoAfterSaleLogAutoConfiguration {
@Bean
public AfterSaleLogAspect afterSaleLogAspect() {
return new AfterSaleLogAspect();
}
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.framework.trade.core.annotations;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
/**
* 售后日志
*
* @author 陈賝
* @date 2023/6/8 17:04
*/
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AfterSaleLog {
/**
* 售后ID
*/
String id();
/**
* 操作类型
*/
String operateType() default "";
/**
* 日志内容
*/
String content() default "";
}

View File

@ -0,0 +1,87 @@
package cn.iocoder.yudao.framework.trade.core.aop;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.common.util.spel.SpelUtil;
import cn.iocoder.yudao.framework.trade.core.annotations.AfterSaleLog;
import cn.iocoder.yudao.framework.trade.core.dto.TradeAfterSaleLogDTO;
import cn.iocoder.yudao.framework.trade.core.enums.AfterSaleStatusEnum;
import cn.iocoder.yudao.framework.trade.core.service.AfterSaleLogService;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* 售后日志
*
* @author 陈賝
* @date 2023/6/13 13:54
*/
@Slf4j
@Aspect
public class AfterSaleLogAspect {
@AfterReturning(pointcut = "@annotation(afterSaleLog)", returning = "info")
public void doAfterReturning(JoinPoint joinPoint, AfterSaleLog afterSaleLog, Object info) {
try {
//日志对象拼接
Integer userType = WebFrameworkUtils.getLoginUserType();
Long id = WebFrameworkUtils.getLoginUserId();
Map<String, String> formatObj = spelFormat(joinPoint, info);
TradeAfterSaleLogDTO dto = new TradeAfterSaleLogDTO()
.setUserId(id)
.setUserType(userType)
.setAfterSaleId(Long.valueOf(formatObj.get("id")))
.setContent(formatObj.get("content"))
.setOperateType(formatObj.get("operateType"));
// 异步存入数据库
SpringUtil.getBean(AfterSaleLogService.class).insert(dto);
System.out.println(dto.toString());
} catch (Exception exception) {
log.error("日志记录错误", exception);
}
}
/**
* 获取描述信息
*/
public static Map<String, String> spelFormat(JoinPoint joinPoint, Object info) {
Map<String, String> result = new HashMap<>(2);
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
AfterSaleLog afterSaleLogPoint = signature.getMethod().getAnnotation(AfterSaleLog.class);
/*
* 售后ID
*/
String id = SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.id());
result.put("id", id);
/*
* 操作类型
*/
String operateType = SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.operateType());
result.put("operateType", operateType);
/*
* 日志内容
*/
String content = SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.content());
if (CharSequenceUtil.isNotEmpty(afterSaleLogPoint.operateType())) {
content += AfterSaleStatusEnum.valueOf(SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.operateType())).description();
}
result.put("content", content);
return result;
}
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.framework.trade.core.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class TradeAfterSaleLogDTO {
/**
* 编号
*/
private Long id;
/**
* 用户编号
*
* 关联 1AdminUserDO id 字段
* 关联 2MemberUserDO id 字段
*/
private Long userId;
/**
* 用户类型
*/
private Integer userType;
/**
* 售后编号
*/
private Long afterSaleId;
/**
* 操作类型
*/
private String operateType;
/**
* 操作明细
*/
private String content;
}

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.framework.trade.core.enums;
/**
* 售后状态
*
* @author 陈賝
* @date 2023/6/13 13:53
*/
public enum AfterSaleStatusEnum {
/**
* 申请中
*/
APPLY("申请中");
private final String description;
AfterSaleStatusEnum(String description) {
this.description = description;
}
public String description() {
return description;
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.yudao.framework.trade.core;

View File

@ -0,0 +1,16 @@
package cn.iocoder.yudao.framework.trade.core.service;
import cn.iocoder.yudao.framework.trade.core.dto.TradeAfterSaleLogDTO;
import org.springframework.scheduling.annotation.Async;
public interface AfterSaleLogService {
/**
* 日志记录
*
* @param logDTO 日志记录
* @author 陈賝
* @date 2023/6/12 14:18
*/
void insert(TradeAfterSaleLogDTO logDTO);
}

View File

@ -0,0 +1 @@
package cn.iocoder.yudao.framework.trade;

View File

@ -0,0 +1 @@
cn.iocoder.yudao.framework.trade.config.YudaoAfterSaleLogAutoConfiguration

View File

@ -19,23 +19,38 @@ import static cn.hutool.core.util.ArrayUtil.firstMatch;
@Getter
public enum TradeAfterSaleStatusEnum implements IntArrayValuable {
APPLY(10,"申请中", // 申请售后
"会员申请退款"),
SELLER_AGREE(20, "卖家通过", // 卖家通过售后商品待退货
"商家同意退款"),
BUYER_DELIVERY(30,"待卖家收货", // 买家已退货等待卖家收货商家待收货
"会员填写退货物流信息"),
WAIT_REFUND(40, "等待平台退款", // 卖家已收货等待平台退款等待退款等待退款
"商家收货"),
COMPLETE(50, "完成", // 完成退款退款成功
"商家确认退款"),
BUYER_CANCEL(61, "买家取消售后", // 买家取消
"会员取消退款"),
SELLER_DISAGREE(62,"卖家拒绝", // 卖家拒绝售后商家拒绝商家拒绝
"商家拒绝退款"),
SELLER_REFUSE(63,"卖家拒绝收货", // 卖家拒绝收货终止售后商家拒收货
"商家拒绝收货"),
/**
* 申请售后
*/
APPLY(10,"申请中", "会员申请退款"),
/**
* 卖家通过售后商品待退货
*/
SELLER_AGREE(20, "卖家通过", "商家同意退款"),
/**
* 买家已退货等待卖家收货商家待收货
*/
BUYER_DELIVERY(30,"待卖家收货", "会员填写退货物流信息"),
/**
* 卖家已收货等待平台退款等待退款等待退款
*/
WAIT_REFUND(40, "等待平台退款", "商家收货"),
/**
* 完成退款退款成功
*/
COMPLETE(50, "完成", "商家确认退款"),
/**
* 买家取消
*/
BUYER_CANCEL(61, "买家取消售后", "会员取消退款"),
/**
* 卖家拒绝售后商家拒绝商家拒绝
*/
SELLER_DISAGREE(62,"卖家拒绝", "商家拒绝退款"),
/**
* 卖家拒绝收货终止售后商家拒收货
*/
SELLER_REFUSE(63,"卖家拒绝收货", "商家拒绝收货"),
;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleStatusEnum::getStatus).toArray();

View File

@ -58,6 +58,10 @@
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-trade</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
@ -93,6 +97,7 @@
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.admin.aftersale;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.trade.core.annotations.AfterSaleLog;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi;
@ -11,6 +12,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSal
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespPageItemVO;
import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO;
import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService;
@ -110,4 +112,20 @@ public class TradeAfterSaleController {
return success(true);
}
/**
* 售后日志测试
*
* @param createReqVO
* @return cn.iocoder.yudao.framework.common.pojo.CommonResult<java.lang.Long>
* @author 陈賝
* @date 2023/6/14 21:39
*/
@PostMapping(value = "/create")
@AfterSaleLog(id = "#createReqVO.orderItemId", content = "'申请售后:售后编号['+#createReqVO.orderItemId+'] , '", operateType = "#createReqVO.operateType")
public CommonResult<Long> createAfterSale(@RequestBody AppTradeAfterSaleCreateReqVO createReqVO) {
return success(1L);
// return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO));
}
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.framework.trade.core.enums.AfterSaleStatusEnum;
import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@ -31,6 +32,13 @@ public class AppTradeAfterSaleCreateReqVO {
@NotNull(message = "申请原因不能为空")
private String applyReason;
/**
* @see AfterSaleStatusEnum
*/
@Schema(description = "操作类型", required = true, example = "1")
@NotNull(message = "操作类型不能为空")
private String operateType;
@Schema(description = "补充描述", example = "商品质量不好")
private String applyDescription;

View File

@ -52,29 +52,9 @@ public class TradeAfterSaleLogDO extends BaseDO {
*/
private Long afterSaleId;
/**
* 订单编号
*
* 关联 {@link TradeOrderDO#getId()}
* 操作类型 {@link TradeAfterSaleStatusEnum}
*/
private Long orderId;
/**
* 订单项编号
*
* 关联 {@link TradeOrderItemDO#getId()}
*/
private Long orderItemId;
/**
* 售后状态之前
*
* 枚举 {@link TradeAfterSaleStatusEnum}
*/
private Integer beforeStatus;
/**
* 售后状态之后
*
* 枚举 {@link TradeAfterSaleStatusEnum}
*/
private Integer afterStatus;
private String operateType;
/**
* 操作明细
*/

View File

@ -5,6 +5,8 @@ import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.trade.core.dto.TradeAfterSaleLogDTO;
import cn.iocoder.yudao.framework.trade.core.service.AfterSaleLogService;
import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO;
@ -26,6 +28,8 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEn
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 lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
@ -43,9 +47,10 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
*
* @author 芋道源码
*/
@Slf4j
@Service
@Validated
public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSaleLogService {
@Resource
private TradeOrderService tradeOrderService;
@ -80,7 +85,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
/**
* 校验交易订单项是否可以申请售后
*
* @param userId 用户编号
* @param userId 用户编号
* @param createReqVO 售后创建信息
* @return 交易订单项
*/
@ -117,7 +122,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
}
// 如果是退货退款的情况需要额外校验是否发货
if (createReqVO.getWay().equals(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay())
&& !TradeOrderStatusEnum.haveDelivered(order.getStatus())) {
&& !TradeOrderStatusEnum.haveDelivered(order.getStatus())) {
throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED);
}
return orderItem;
@ -133,7 +138,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
TradeOrderDO order = tradeOrderService.getOrder(orderItem.getUserId(), orderItem.getOrderId());
afterSale.setOrderNo(order.getNo()); // 记录 orderNo 订单流水方便后续检索
afterSale.setType(TradeOrderStatusEnum.isCompleted(order.getStatus())
? TradeAfterSaleTypeEnum.AFTER_SALE.getType() : TradeAfterSaleTypeEnum.IN_SALE.getType());
? TradeAfterSaleTypeEnum.AFTER_SALE.getType() : TradeAfterSaleTypeEnum.IN_SALE.getType());
// TODO 退还积分
tradeAfterSaleMapper.insert(afterSale);
@ -380,13 +385,38 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null);
}
@Deprecated
private void createAfterSaleLog(Long userId, Integer userType, TradeAfterSaleDO afterSale,
Integer beforeStatus, Integer afterStatus) {
TradeAfterSaleLogDO afterSaleLog = new TradeAfterSaleLogDO().setUserId(userId).setUserType(userType)
.setAfterSaleId(afterSale.getId()).setOrderId(afterSale.getOrderId())
.setOrderItemId(afterSale.getOrderItemId()).setBeforeStatus(beforeStatus).setAfterStatus(afterStatus)
.setContent(TradeAfterSaleStatusEnum.valueOf(afterStatus).getContent());
tradeAfterSaleLogMapper.insert(afterSaleLog);
TradeAfterSaleLogDTO logDTO = new TradeAfterSaleLogDTO()
.setUserId(userId)
.setUserType(userType)
.setAfterSaleId(afterSale.getId())
.setOperateType(afterStatus.toString());
// TODO 废弃待删除
this.insert(logDTO);
}
/**
* 日志记录
*
* @param logDTO 日志记录
* @author 陈賝
* @date 2023/6/12 14:18
*/
@Override
@Async
public void insert(TradeAfterSaleLogDTO logDTO) {
try {
TradeAfterSaleLogDO afterSaleLog = new TradeAfterSaleLogDO()
.setUserId(logDTO.getUserId())
.setUserType(logDTO.getUserType())
.setAfterSaleId(logDTO.getAfterSaleId())
.setOperateType(logDTO.getOperateType())
.setContent(logDTO.getContent());
tradeAfterSaleLogMapper.insert(afterSaleLog);
}catch (Exception exception){
log.error("日志记录错误", exception);
}
}
}

View File

@ -66,6 +66,7 @@ public class TradeAfterSaleServiceTest extends BaseDbUnitTest {
AppTradeAfterSaleCreateReqVO createReqVO = new AppTradeAfterSaleCreateReqVO()
.setOrderItemId(1L).setRefundPrice(100).setWay(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay())
.setApplyReason("退钱").setApplyDescription("快退")
.setOperateType("APPLY")
.setApplyPicUrls(asList("https://www.baidu.com/1.png", "https://www.baidu.com/2.png"));
// mock 方法交易订单项
TradeOrderItemDO orderItem = randomPojo(TradeOrderItemDO.class, o -> {
@ -102,8 +103,8 @@ public class TradeAfterSaleServiceTest extends BaseDbUnitTest {
assertEquals(afterSaleLog.getUserType(), UserTypeEnum.MEMBER.getValue());
assertEquals(afterSaleLog.getAfterSaleId(), afterSaleId);
assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime");
assertNull(afterSaleLog.getBeforeStatus());
assertEquals(afterSaleLog.getAfterStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus());
// assertNull(afterSaleLog.getBeforeStatus());
// assertEquals(afterSaleLog.getAfterStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus());
assertEquals(afterSaleLog.getContent(), TradeAfterSaleStatusEnum.APPLY.getContent());
}