Commit 59e16795be0009d381ae501bb0ddf92526d04cb6

Authored by 陈賝
Committed by 芋道源码
1 parent 35df912b

!514 mall交易日志封装

* 交易日志封装
* 交易日志封装
* 交易日志模块
Showing 20 changed files with 470 additions and 51 deletions
yudao-framework/pom.xml
@@ -31,6 +31,7 @@ @@ -31,6 +31,7 @@
31 <module>yudao-spring-boot-starter-biz-sms</module> 31 <module>yudao-spring-boot-starter-biz-sms</module>
32 32
33 <module>yudao-spring-boot-starter-biz-pay</module> 33 <module>yudao-spring-boot-starter-biz-pay</module>
  34 + <module>yudao-spring-boot-starter-biz-trade</module>
34 <module>yudao-spring-boot-starter-biz-weixin</module> 35 <module>yudao-spring-boot-starter-biz-weixin</module>
35 <module>yudao-spring-boot-starter-biz-social</module> 36 <module>yudao-spring-boot-starter-biz-social</module>
36 <module>yudao-spring-boot-starter-biz-tenant</module> 37 <module>yudao-spring-boot-starter-biz-tenant</module>
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spel/SpelUtil.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.common.util.spel;
  2 +
  3 +import org.aspectj.lang.JoinPoint;
  4 +import org.aspectj.lang.reflect.MethodSignature;
  5 +import org.springframework.core.DefaultParameterNameDiscoverer;
  6 +import org.springframework.expression.EvaluationContext;
  7 +import org.springframework.expression.spel.standard.SpelExpressionParser;
  8 +import org.springframework.expression.spel.support.StandardEvaluationContext;
  9 +
  10 +/**
  11 + * SpelUtil
  12 + *
  13 + * @author Chopper
  14 + * @version v1.0
  15 + * 2021-01-11 10:45
  16 + */
  17 +public class SpelUtil {
  18 +
  19 +
  20 + /**
  21 + * spel表达式解析器
  22 + */
  23 + private static SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
  24 + /**
  25 + * 参数名发现器
  26 + */
  27 + private static DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
  28 +
  29 + /**
  30 + * 转换 jspl参数
  31 + *
  32 + * @param joinPoint
  33 + * @param spel
  34 + * @return
  35 + */
  36 + public static String compileParams(JoinPoint joinPoint, String spel) { //Spel表达式解析日志信息
  37 + //获得方法参数名数组
  38 + MethodSignature signature = (MethodSignature) joinPoint.getSignature();
  39 +
  40 + String[] parameterNames = parameterNameDiscoverer.getParameterNames(signature.getMethod());
  41 + if (parameterNames != null && parameterNames.length > 0) {
  42 + EvaluationContext context = new StandardEvaluationContext();
  43 +
  44 + //获取方法参数值
  45 + Object[] args = joinPoint.getArgs();
  46 + for (int i = 0; i < args.length; i++) {
  47 + //替换spel里的变量值为实际值, 比如 #user --> user对象
  48 + context.setVariable(parameterNames[i], args[i]);
  49 + }
  50 + return spelExpressionParser.parseExpression(spel).getValue(context).toString();
  51 + }
  52 + return "";
  53 + }
  54 +
  55 + /**
  56 + * 转换 jspl参数
  57 + *
  58 + * @param joinPoint
  59 + * @param spel
  60 + * @return
  61 + */
  62 + public static String compileParams(JoinPoint joinPoint, Object rvt, String spel) { //Spel表达式解析日志信息
  63 + //获得方法参数名数组
  64 + MethodSignature signature = (MethodSignature) joinPoint.getSignature();
  65 +
  66 + String[] parameterNames = parameterNameDiscoverer.getParameterNames(signature.getMethod());
  67 + if (parameterNames != null && parameterNames.length > 0) {
  68 + EvaluationContext context = new StandardEvaluationContext();
  69 +
  70 + //获取方法参数值
  71 + Object[] args = joinPoint.getArgs();
  72 + for (int i = 0; i < args.length; i++) {
  73 + //替换spel里的变量值为实际值, 比如 #user --> user对象
  74 + context.setVariable(parameterNames[i], args[i]);
  75 + }
  76 + context.setVariable("rvt", rvt);
  77 + return spelExpressionParser.parseExpression(spel).getValue(context).toString();
  78 + }
  79 + return "";
  80 + }
  81 +}
yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml
@@ -37,7 +37,7 @@ @@ -37,7 +37,7 @@
37 <!-- 业务组件 --> 37 <!-- 业务组件 -->
38 <dependency> 38 <dependency>
39 <groupId>cn.iocoder.boot</groupId> 39 <groupId>cn.iocoder.boot</groupId>
40 - <artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行操作日志的记录 --> 40 + <artifactId>yudao-module-system-api</artifactId>
41 <version>${revision}</version> 41 <version>${revision}</version>
42 </dependency> 42 </dependency>
43 43
yudao-framework/yudao-spring-boot-starter-biz-trade/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <groupId>cn.iocoder.boot</groupId>
  7 + <artifactId>yudao-framework</artifactId>
  8 + <version>${revision}</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 + <artifactId>yudao-spring-boot-starter-biz-trade</artifactId>
  12 + <packaging>jar</packaging>
  13 +
  14 + <name>${project.artifactId}</name>
  15 + <description>交易模块</description>
  16 + <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
  17 +
  18 + <dependencies>
  19 + <dependency>
  20 + <groupId>cn.iocoder.boot</groupId>
  21 + <artifactId>yudao-common</artifactId>
  22 + </dependency>
  23 +
  24 + <!-- Spring 核心 -->
  25 + <dependency>
  26 + <groupId>org.springframework.boot</groupId>
  27 + <artifactId>spring-boot-starter-aop</artifactId>
  28 + </dependency>
  29 +
  30 + <!-- Web 相关 -->
  31 + <dependency>
  32 + <groupId>cn.iocoder.boot</groupId>
  33 + <artifactId>yudao-spring-boot-starter-web</artifactId>
  34 + <scope>provided</scope>
  35 + </dependency>
  36 +
  37 + <!-- 业务组件 -->
  38 + <dependency>
  39 + <groupId>cn.iocoder.boot</groupId>
  40 + <artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行操作日志的记录 -->
  41 + <version>${revision}</version>
  42 + </dependency>
  43 +
  44 + <!-- 工具类相关 -->
  45 + <dependency>
  46 + <groupId>com.google.guava</groupId>
  47 + <artifactId>guava</artifactId>
  48 + </dependency>
  49 + <dependency>
  50 + <groupId>cn.iocoder.boot</groupId>
  51 + <artifactId>yudao-spring-boot-starter-security</artifactId>
  52 + </dependency>
  53 + </dependencies>
  54 +</project>
yudao-framework/yudao-spring-boot-starter-biz-trade/src/main/java/cn/iocoder/yudao/framework/trade/config/YudaoAfterSaleLogAutoConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.trade.config;
  2 +
  3 +import cn.iocoder.yudao.framework.trade.core.annotations.AfterSaleLog;
  4 +import cn.iocoder.yudao.framework.trade.core.aop.AfterSaleLogAspect;
  5 +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
  6 +import org.springframework.boot.autoconfigure.AutoConfiguration;
  7 +import org.springframework.context.annotation.Bean;
  8 +
  9 +@AutoConfiguration
  10 +public class YudaoAfterSaleLogAutoConfiguration {
  11 +
  12 + @Bean
  13 + public AfterSaleLogAspect afterSaleLogAspect() {
  14 + return new AfterSaleLogAspect();
  15 + }
  16 +
  17 +}
yudao-framework/yudao-spring-boot-starter-biz-trade/src/main/java/cn/iocoder/yudao/framework/trade/core/annotations/AfterSaleLog.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.trade.core.annotations;
  2 +
  3 +import org.aspectj.lang.annotation.Aspect;
  4 +import org.springframework.stereotype.Component;
  5 +
  6 +import java.lang.annotation.*;
  7 +
  8 +/**
  9 + * 售后日志
  10 + *
  11 + * @author 陈賝
  12 + * @date 2023/6/8 17:04
  13 + */
  14 +@Target({ElementType.METHOD,ElementType.TYPE})
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +@Documented
  17 +public @interface AfterSaleLog {
  18 +
  19 + /**
  20 + * 售后ID
  21 + */
  22 + String id();
  23 +
  24 + /**
  25 + * 操作类型
  26 + */
  27 + String operateType() default "";
  28 +
  29 + /**
  30 + * 日志内容
  31 + */
  32 + String content() default "";
  33 +
  34 +}
yudao-framework/yudao-spring-boot-starter-biz-trade/src/main/java/cn/iocoder/yudao/framework/trade/core/aop/AfterSaleLogAspect.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.trade.core.aop;
  2 +
  3 +import cn.hutool.core.text.CharSequenceUtil;
  4 +import cn.hutool.extra.spring.SpringUtil;
  5 +import cn.iocoder.yudao.framework.common.util.spel.SpelUtil;
  6 +import cn.iocoder.yudao.framework.trade.core.annotations.AfterSaleLog;
  7 +import cn.iocoder.yudao.framework.trade.core.dto.TradeAfterSaleLogDTO;
  8 +import cn.iocoder.yudao.framework.trade.core.enums.AfterSaleStatusEnum;
  9 +import cn.iocoder.yudao.framework.trade.core.service.AfterSaleLogService;
  10 +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.aspectj.lang.JoinPoint;
  13 +import org.aspectj.lang.annotation.AfterReturning;
  14 +import org.aspectj.lang.annotation.Around;
  15 +import org.aspectj.lang.annotation.Aspect;
  16 +import org.aspectj.lang.reflect.MethodSignature;
  17 +import org.springframework.stereotype.Component;
  18 +
  19 +import java.util.HashMap;
  20 +import java.util.Map;
  21 +
  22 +/**
  23 + * 售后日志
  24 + *
  25 + * @author 陈賝
  26 + * @date 2023/6/13 13:54
  27 + */
  28 +@Slf4j
  29 +@Aspect
  30 +public class AfterSaleLogAspect {
  31 +
  32 + @AfterReturning(pointcut = "@annotation(afterSaleLog)", returning = "info")
  33 + public void doAfterReturning(JoinPoint joinPoint, AfterSaleLog afterSaleLog, Object info) {
  34 + try {
  35 + //日志对象拼接
  36 + Integer userType = WebFrameworkUtils.getLoginUserType();
  37 + Long id = WebFrameworkUtils.getLoginUserId();
  38 + Map<String, String> formatObj = spelFormat(joinPoint, info);
  39 + TradeAfterSaleLogDTO dto = new TradeAfterSaleLogDTO()
  40 + .setUserId(id)
  41 + .setUserType(userType)
  42 + .setAfterSaleId(Long.valueOf(formatObj.get("id")))
  43 + .setContent(formatObj.get("content"))
  44 + .setOperateType(formatObj.get("operateType"));
  45 + // 异步存入数据库
  46 + SpringUtil.getBean(AfterSaleLogService.class).insert(dto);
  47 + System.out.println(dto.toString());
  48 + } catch (Exception exception) {
  49 + log.error("日志记录错误", exception);
  50 + }
  51 + }
  52 +
  53 + /**
  54 + * 获取描述信息
  55 + */
  56 + public static Map<String, String> spelFormat(JoinPoint joinPoint, Object info) {
  57 +
  58 + Map<String, String> result = new HashMap<>(2);
  59 + MethodSignature signature = (MethodSignature) joinPoint.getSignature();
  60 + AfterSaleLog afterSaleLogPoint = signature.getMethod().getAnnotation(AfterSaleLog.class);
  61 +
  62 + /*
  63 + * 售后ID
  64 + */
  65 + String id = SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.id());
  66 + result.put("id", id);
  67 +
  68 + /*
  69 + * 操作类型
  70 + */
  71 + String operateType = SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.operateType());
  72 + result.put("operateType", operateType);
  73 +
  74 + /*
  75 + * 日志内容
  76 + */
  77 + String content = SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.content());
  78 + if (CharSequenceUtil.isNotEmpty(afterSaleLogPoint.operateType())) {
  79 + content += AfterSaleStatusEnum.valueOf(SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.operateType())).description();
  80 + }
  81 + result.put("content", content);
  82 + return result;
  83 +
  84 + }
  85 +
  86 +
  87 +}
yudao-framework/yudao-spring-boot-starter-biz-trade/src/main/java/cn/iocoder/yudao/framework/trade/core/dto/TradeAfterSaleLogDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.trade.core.dto;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +import lombok.experimental.Accessors;
  7 +
  8 +@Data
  9 +@NoArgsConstructor
  10 +@AllArgsConstructor
  11 +@Accessors(chain = true)
  12 +public class TradeAfterSaleLogDTO {
  13 +
  14 + /**
  15 + * 编号
  16 + */
  17 + private Long id;
  18 + /**
  19 + * 用户编号
  20 + *
  21 + * 关联 1:AdminUserDO 的 id 字段
  22 + * 关联 2:MemberUserDO 的 id 字段
  23 + */
  24 + private Long userId;
  25 + /**
  26 + * 用户类型
  27 + */
  28 + private Integer userType;
  29 + /**
  30 + * 售后编号
  31 + */
  32 + private Long afterSaleId;
  33 + /**
  34 + * 操作类型
  35 + */
  36 + private String operateType;
  37 + /**
  38 + * 操作明细
  39 + */
  40 + private String content;
  41 +
  42 +}
yudao-framework/yudao-spring-boot-starter-biz-trade/src/main/java/cn/iocoder/yudao/framework/trade/core/enums/AfterSaleStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.trade.core.enums;
  2 +
  3 +/**
  4 + * 售后状态
  5 + *
  6 + * @author 陈賝
  7 + * @date 2023/6/13 13:53
  8 + */
  9 +public enum AfterSaleStatusEnum {
  10 +
  11 + /**
  12 + * 申请中
  13 + */
  14 + APPLY("申请中");
  15 +
  16 + private final String description;
  17 +
  18 + AfterSaleStatusEnum(String description) {
  19 + this.description = description;
  20 + }
  21 +
  22 + public String description() {
  23 + return description;
  24 + }
  25 +
  26 +
  27 +}
yudao-framework/yudao-spring-boot-starter-biz-trade/src/main/java/cn/iocoder/yudao/framework/trade/core/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.trade.core;
yudao-framework/yudao-spring-boot-starter-biz-trade/src/main/java/cn/iocoder/yudao/framework/trade/core/service/AfterSaleLogService.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.trade.core.service;
  2 +
  3 +import cn.iocoder.yudao.framework.trade.core.dto.TradeAfterSaleLogDTO;
  4 +import org.springframework.scheduling.annotation.Async;
  5 +
  6 +public interface AfterSaleLogService {
  7 +
  8 + /**
  9 + * 日志记录
  10 + *
  11 + * @param logDTO 日志记录
  12 + * @author 陈賝
  13 + * @date 2023/6/12 14:18
  14 + */
  15 + void insert(TradeAfterSaleLogDTO logDTO);
  16 +}
yudao-framework/yudao-spring-boot-starter-biz-trade/src/main/java/cn/iocoder/yudao/framework/trade/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.trade;
yudao-framework/yudao-spring-boot-starter-biz-trade/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 0 → 100644
  1 +cn.iocoder.yudao.framework.trade.config.YudaoAfterSaleLogAutoConfiguration
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleStatusEnum.java
@@ -19,23 +19,38 @@ import static cn.hutool.core.util.ArrayUtil.firstMatch; @@ -19,23 +19,38 @@ import static cn.hutool.core.util.ArrayUtil.firstMatch;
19 @Getter 19 @Getter
20 public enum TradeAfterSaleStatusEnum implements IntArrayValuable { 20 public enum TradeAfterSaleStatusEnum implements IntArrayValuable {
21 21
22 - APPLY(10,"申请中", // 【申请售后】  
23 - "会员申请退款"),  
24 - SELLER_AGREE(20, "卖家通过", // 卖家通过售后;【商品待退货】  
25 - "商家同意退款"),  
26 - BUYER_DELIVERY(30,"待卖家收货", // 买家已退货,等待卖家收货;【商家待收货】  
27 - "会员填写退货物流信息"),  
28 - WAIT_REFUND(40, "等待平台退款", // 卖家已收货,等待平台退款;等待退款【等待退款】  
29 - "商家收货"),  
30 - COMPLETE(50, "完成", // 完成退款【退款成功】  
31 - "商家确认退款"),  
32 -  
33 - BUYER_CANCEL(61, "买家取消售后", // 【买家取消】  
34 - "会员取消退款"),  
35 - SELLER_DISAGREE(62,"卖家拒绝", // 卖家拒绝售后;商家拒绝【商家拒绝】  
36 - "商家拒绝退款"),  
37 - SELLER_REFUSE(63,"卖家拒绝收货", // 卖家拒绝收货,终止售后;【商家拒收货】  
38 - "商家拒绝收货"), 22 + /**
  23 + * 【申请售后】
  24 + */
  25 + APPLY(10,"申请中", "会员申请退款"),
  26 + /**
  27 + * 卖家通过售后;【商品待退货】
  28 + */
  29 + SELLER_AGREE(20, "卖家通过", "商家同意退款"),
  30 + /**
  31 + * 买家已退货,等待卖家收货;【商家待收货】
  32 + */
  33 + BUYER_DELIVERY(30,"待卖家收货", "会员填写退货物流信息"),
  34 + /**
  35 + * 卖家已收货,等待平台退款;等待退款【等待退款】
  36 + */
  37 + WAIT_REFUND(40, "等待平台退款", "商家收货"),
  38 + /**
  39 + * 完成退款【退款成功】
  40 + */
  41 + COMPLETE(50, "完成", "商家确认退款"),
  42 + /**
  43 + * 【买家取消】
  44 + */
  45 + BUYER_CANCEL(61, "买家取消售后", "会员取消退款"),
  46 + /**
  47 + * 卖家拒绝售后;商家拒绝【商家拒绝】
  48 + */
  49 + SELLER_DISAGREE(62,"卖家拒绝", "商家拒绝退款"),
  50 + /**
  51 + * 卖家拒绝收货,终止售后;【商家拒收货】
  52 + */
  53 + SELLER_REFUSE(63,"卖家拒绝收货", "商家拒绝收货"),
39 ; 54 ;
40 55
41 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleStatusEnum::getStatus).toArray(); 56 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleStatusEnum::getStatus).toArray();
yudao-module-mall/yudao-module-trade-biz/pom.xml
@@ -58,6 +58,10 @@ @@ -58,6 +58,10 @@
58 <groupId>cn.iocoder.boot</groupId> 58 <groupId>cn.iocoder.boot</groupId>
59 <artifactId>yudao-spring-boot-starter-biz-ip</artifactId> 59 <artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
60 </dependency> 60 </dependency>
  61 + <dependency>
  62 + <groupId>cn.iocoder.boot</groupId>
  63 + <artifactId>yudao-spring-boot-starter-biz-trade</artifactId>
  64 + </dependency>
61 65
62 <!-- Web 相关 --> 66 <!-- Web 相关 -->
63 <dependency> 67 <dependency>
@@ -93,6 +97,7 @@ @@ -93,6 +97,7 @@
93 <groupId>cn.iocoder.boot</groupId> 97 <groupId>cn.iocoder.boot</groupId>
94 <artifactId>yudao-spring-boot-starter-excel</artifactId> 98 <artifactId>yudao-spring-boot-starter-excel</artifactId>
95 </dependency> 99 </dependency>
  100 +
96 </dependencies> 101 </dependencies>
97 102
98 </project> 103 </project>
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.admin.aftersale; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.admin.aftersale;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.trade.core.annotations.AfterSaleLog;
6 import cn.iocoder.yudao.module.member.api.user.MemberUserApi; 7 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
7 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 8 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
8 import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi; 9 import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi;
@@ -11,6 +12,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSal @@ -11,6 +12,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSal
11 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; 12 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO;
12 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO; 13 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO;
13 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespPageItemVO; 14 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespPageItemVO;
  15 +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO;
14 import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; 16 import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert;
15 import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; 17 import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
16 import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; 18 import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService;
@@ -110,4 +112,20 @@ public class TradeAfterSaleController { @@ -110,4 +112,20 @@ public class TradeAfterSaleController {
110 return success(true); 112 return success(true);
111 } 113 }
112 114
  115 +
  116 + /**
  117 + * 售后日志测试
  118 + *
  119 + * @param createReqVO
  120 + * @return cn.iocoder.yudao.framework.common.pojo.CommonResult<java.lang.Long>
  121 + * @author 陈賝
  122 + * @date 2023/6/14 21:39
  123 + */
  124 + @PostMapping(value = "/create")
  125 + @AfterSaleLog(id = "#createReqVO.orderItemId", content = "'申请售后:售后编号['+#createReqVO.orderItemId+'] , '", operateType = "#createReqVO.operateType")
  126 + public CommonResult<Long> createAfterSale(@RequestBody AppTradeAfterSaleCreateReqVO createReqVO) {
  127 + return success(1L);
  128 +// return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO));
  129 + }
  130 +
113 } 131 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleCreateReqVO.java
1 package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo; 1 package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo;
2 2
3 import cn.iocoder.yudao.framework.common.validation.InEnum; 3 import cn.iocoder.yudao.framework.common.validation.InEnum;
  4 +import cn.iocoder.yudao.framework.trade.core.enums.AfterSaleStatusEnum;
4 import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; 5 import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum;
5 import io.swagger.v3.oas.annotations.media.Schema; 6 import io.swagger.v3.oas.annotations.media.Schema;
6 import lombok.Data; 7 import lombok.Data;
@@ -31,6 +32,13 @@ public class AppTradeAfterSaleCreateReqVO { @@ -31,6 +32,13 @@ public class AppTradeAfterSaleCreateReqVO {
31 @NotNull(message = "申请原因不能为空") 32 @NotNull(message = "申请原因不能为空")
32 private String applyReason; 33 private String applyReason;
33 34
  35 + /**
  36 + * @see AfterSaleStatusEnum
  37 + */
  38 + @Schema(description = "操作类型", required = true, example = "1")
  39 + @NotNull(message = "操作类型不能为空")
  40 + private String operateType;
  41 +
34 @Schema(description = "补充描述", example = "商品质量不好") 42 @Schema(description = "补充描述", example = "商品质量不好")
35 private String applyDescription; 43 private String applyDescription;
36 44
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java
@@ -52,29 +52,9 @@ public class TradeAfterSaleLogDO extends BaseDO { @@ -52,29 +52,9 @@ public class TradeAfterSaleLogDO extends BaseDO {
52 */ 52 */
53 private Long afterSaleId; 53 private Long afterSaleId;
54 /** 54 /**
55 - * 订单编号  
56 - *  
57 - * 关联 {@link TradeOrderDO#getId()}  
58 - */  
59 - private Long orderId;  
60 - /**  
61 - * 订单项编号  
62 - *  
63 - * 关联 {@link TradeOrderItemDO#getId()}  
64 - */  
65 - private Long orderItemId;  
66 - /**  
67 - * 售后状态(之前)  
68 - *  
69 - * 枚举 {@link TradeAfterSaleStatusEnum}  
70 - */  
71 - private Integer beforeStatus;  
72 - /**  
73 - * 售后状态(之后)  
74 - *  
75 - * 枚举 {@link TradeAfterSaleStatusEnum} 55 + * 操作类型 {@link TradeAfterSaleStatusEnum}
76 */ 56 */
77 - private Integer afterStatus; 57 + private String operateType;
78 /** 58 /**
79 * 操作明细 59 * 操作明细
80 */ 60 */
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java
@@ -5,6 +5,8 @@ import cn.hutool.core.util.RandomUtil; @@ -5,6 +5,8 @@ import cn.hutool.core.util.RandomUtil;
5 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 5 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 7 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  8 +import cn.iocoder.yudao.framework.trade.core.dto.TradeAfterSaleLogDTO;
  9 +import cn.iocoder.yudao.framework.trade.core.service.AfterSaleLogService;
8 import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; 10 import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
9 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; 11 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
10 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; 12 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO;
@@ -26,6 +28,8 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEn @@ -26,6 +28,8 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEn
26 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; 28 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
27 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; 29 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
28 import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; 30 import cn.iocoder.yudao.module.trade.service.order.TradeOrderService;
  31 +import lombok.extern.slf4j.Slf4j;
  32 +import org.springframework.scheduling.annotation.Async;
29 import org.springframework.stereotype.Service; 33 import org.springframework.stereotype.Service;
30 import org.springframework.transaction.annotation.Transactional; 34 import org.springframework.transaction.annotation.Transactional;
31 import org.springframework.transaction.support.TransactionSynchronization; 35 import org.springframework.transaction.support.TransactionSynchronization;
@@ -43,9 +47,10 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; @@ -43,9 +47,10 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
43 * 47 *
44 * @author 芋道源码 48 * @author 芋道源码
45 */ 49 */
  50 +@Slf4j
46 @Service 51 @Service
47 @Validated 52 @Validated
48 -public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { 53 +public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSaleLogService {
49 54
50 @Resource 55 @Resource
51 private TradeOrderService tradeOrderService; 56 private TradeOrderService tradeOrderService;
@@ -80,7 +85,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { @@ -80,7 +85,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
80 /** 85 /**
81 * 校验交易订单项是否可以申请售后 86 * 校验交易订单项是否可以申请售后
82 * 87 *
83 - * @param userId 用户编号 88 + * @param userId 用户编号
84 * @param createReqVO 售后创建信息 89 * @param createReqVO 售后创建信息
85 * @return 交易订单项 90 * @return 交易订单项
86 */ 91 */
@@ -117,7 +122,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { @@ -117,7 +122,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
117 } 122 }
118 // 如果是【退货退款】的情况,需要额外校验是否发货 123 // 如果是【退货退款】的情况,需要额外校验是否发货
119 if (createReqVO.getWay().equals(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay()) 124 if (createReqVO.getWay().equals(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay())
120 - && !TradeOrderStatusEnum.haveDelivered(order.getStatus())) { 125 + && !TradeOrderStatusEnum.haveDelivered(order.getStatus())) {
121 throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED); 126 throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED);
122 } 127 }
123 return orderItem; 128 return orderItem;
@@ -133,7 +138,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { @@ -133,7 +138,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
133 TradeOrderDO order = tradeOrderService.getOrder(orderItem.getUserId(), orderItem.getOrderId()); 138 TradeOrderDO order = tradeOrderService.getOrder(orderItem.getUserId(), orderItem.getOrderId());
134 afterSale.setOrderNo(order.getNo()); // 记录 orderNo 订单流水,方便后续检索 139 afterSale.setOrderNo(order.getNo()); // 记录 orderNo 订单流水,方便后续检索
135 afterSale.setType(TradeOrderStatusEnum.isCompleted(order.getStatus()) 140 afterSale.setType(TradeOrderStatusEnum.isCompleted(order.getStatus())
136 - ? TradeAfterSaleTypeEnum.AFTER_SALE.getType() : TradeAfterSaleTypeEnum.IN_SALE.getType()); 141 + ? TradeAfterSaleTypeEnum.AFTER_SALE.getType() : TradeAfterSaleTypeEnum.IN_SALE.getType());
137 // TODO 退还积分 142 // TODO 退还积分
138 tradeAfterSaleMapper.insert(afterSale); 143 tradeAfterSaleMapper.insert(afterSale);
139 144
@@ -380,13 +385,38 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { @@ -380,13 +385,38 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService {
380 TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null); 385 TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null);
381 } 386 }
382 387
  388 + @Deprecated
383 private void createAfterSaleLog(Long userId, Integer userType, TradeAfterSaleDO afterSale, 389 private void createAfterSaleLog(Long userId, Integer userType, TradeAfterSaleDO afterSale,
384 Integer beforeStatus, Integer afterStatus) { 390 Integer beforeStatus, Integer afterStatus) {
385 - TradeAfterSaleLogDO afterSaleLog = new TradeAfterSaleLogDO().setUserId(userId).setUserType(userType)  
386 - .setAfterSaleId(afterSale.getId()).setOrderId(afterSale.getOrderId())  
387 - .setOrderItemId(afterSale.getOrderItemId()).setBeforeStatus(beforeStatus).setAfterStatus(afterStatus)  
388 - .setContent(TradeAfterSaleStatusEnum.valueOf(afterStatus).getContent());  
389 - tradeAfterSaleLogMapper.insert(afterSaleLog); 391 + TradeAfterSaleLogDTO logDTO = new TradeAfterSaleLogDTO()
  392 + .setUserId(userId)
  393 + .setUserType(userType)
  394 + .setAfterSaleId(afterSale.getId())
  395 + .setOperateType(afterStatus.toString());
  396 + // TODO 废弃,待删除
  397 + this.insert(logDTO);
390 } 398 }
391 399
  400 + /**
  401 + * 日志记录
  402 + *
  403 + * @param logDTO 日志记录
  404 + * @author 陈賝
  405 + * @date 2023/6/12 14:18
  406 + */
  407 + @Override
  408 + @Async
  409 + public void insert(TradeAfterSaleLogDTO logDTO) {
  410 + try {
  411 + TradeAfterSaleLogDO afterSaleLog = new TradeAfterSaleLogDO()
  412 + .setUserId(logDTO.getUserId())
  413 + .setUserType(logDTO.getUserType())
  414 + .setAfterSaleId(logDTO.getAfterSaleId())
  415 + .setOperateType(logDTO.getOperateType())
  416 + .setContent(logDTO.getContent());
  417 + tradeAfterSaleLogMapper.insert(afterSaleLog);
  418 + }catch (Exception exception){
  419 + log.error("日志记录错误", exception);
  420 + }
  421 + }
392 } 422 }
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java
@@ -66,6 +66,7 @@ public class TradeAfterSaleServiceTest extends BaseDbUnitTest { @@ -66,6 +66,7 @@ public class TradeAfterSaleServiceTest extends BaseDbUnitTest {
66 AppTradeAfterSaleCreateReqVO createReqVO = new AppTradeAfterSaleCreateReqVO() 66 AppTradeAfterSaleCreateReqVO createReqVO = new AppTradeAfterSaleCreateReqVO()
67 .setOrderItemId(1L).setRefundPrice(100).setWay(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay()) 67 .setOrderItemId(1L).setRefundPrice(100).setWay(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay())
68 .setApplyReason("退钱").setApplyDescription("快退") 68 .setApplyReason("退钱").setApplyDescription("快退")
  69 + .setOperateType("APPLY")
69 .setApplyPicUrls(asList("https://www.baidu.com/1.png", "https://www.baidu.com/2.png")); 70 .setApplyPicUrls(asList("https://www.baidu.com/1.png", "https://www.baidu.com/2.png"));
70 // mock 方法(交易订单项) 71 // mock 方法(交易订单项)
71 TradeOrderItemDO orderItem = randomPojo(TradeOrderItemDO.class, o -> { 72 TradeOrderItemDO orderItem = randomPojo(TradeOrderItemDO.class, o -> {
@@ -102,8 +103,8 @@ public class TradeAfterSaleServiceTest extends BaseDbUnitTest { @@ -102,8 +103,8 @@ public class TradeAfterSaleServiceTest extends BaseDbUnitTest {
102 assertEquals(afterSaleLog.getUserType(), UserTypeEnum.MEMBER.getValue()); 103 assertEquals(afterSaleLog.getUserType(), UserTypeEnum.MEMBER.getValue());
103 assertEquals(afterSaleLog.getAfterSaleId(), afterSaleId); 104 assertEquals(afterSaleLog.getAfterSaleId(), afterSaleId);
104 assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime"); 105 assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime");
105 - assertNull(afterSaleLog.getBeforeStatus());  
106 - assertEquals(afterSaleLog.getAfterStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus()); 106 +// assertNull(afterSaleLog.getBeforeStatus());
  107 +// assertEquals(afterSaleLog.getAfterStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus());
107 assertEquals(afterSaleLog.getContent(), TradeAfterSaleStatusEnum.APPLY.getContent()); 108 assertEquals(afterSaleLog.getContent(), TradeAfterSaleStatusEnum.APPLY.getContent());
108 } 109 }
109 110