Commit 787de1be94f21d945d55c2de28ad4c0db6692fdb

Authored by YunaiV
2 parents f9e64a9f 497d826a

Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/mall_product

# Conflicts:
#	sql/mysql/mall.sql
#	sql/mysql/ruoyi-vue-pro.sql
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/recharge/AppPayWalletRechargeCreateReqVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java
Showing 189 changed files with 1533 additions and 2012 deletions
README.md
@@ -256,7 +256,7 @@ _鍓嶇鍩轰簬 crmeb uniapp 缁忚繃鎺堟潈閲嶆瀯锛屼紭鍖栦唬鐮佸疄鐜帮紝鎺ュ叆鑺嬮 @@ -256,7 +256,7 @@ _鍓嶇鍩轰簬 crmeb uniapp 缁忚繃鎺堟潈閲嶆瀯锛屼紭鍖栦唬鐮佸疄鐜帮紝鎺ュ叆鑺嬮
256 256
257 | 妗嗘灦 | 璇存槑 | 鐗堟湰 | 瀛︿範鎸囧崡 | 257 | 妗嗘灦 | 璇存槑 | 鐗堟湰 | 瀛︿範鎸囧崡 |
258 |---------------------------------------------------------------------------------------------|------------------|----------------|----------------------------------------------------------------| 258 |---------------------------------------------------------------------------------------------|------------------|----------------|----------------------------------------------------------------|
259 -| [Spring Boot](https://spring.io/projects/spring-boot) | 搴旂敤寮鍙戞鏋 | 2.7.16 | [鏂囨。](https://github.com/YunaiV/SpringBoot-Labs) | 259 +| [Spring Boot](https://spring.io/projects/spring-boot) | 搴旂敤寮鍙戞鏋 | 2.7.17 | [鏂囨。](https://github.com/YunaiV/SpringBoot-Labs) |
260 | [MySQL](https://www.mysql.com/cn/) | 鏁版嵁搴撴湇鍔″櫒 | 5.7 / 8.0+ | | 260 | [MySQL](https://www.mysql.com/cn/) | 鏁版嵁搴撴湇鍔″櫒 | 5.7 / 8.0+ | |
261 | [Druid](https://github.com/alibaba/druid) | JDBC 杩炴帴姹犮佺洃鎺х粍浠 | 1.2.19 | [鏂囨。](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | 261 | [Druid](https://github.com/alibaba/druid) | JDBC 杩炴帴姹犮佺洃鎺х粍浠 | 1.2.19 | [鏂囨。](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
262 | [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 澧炲己宸ュ叿鍖 | 3.5.3.2 | [鏂囨。](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | 262 | [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 澧炲己宸ュ叿鍖 | 3.5.3.2 | [鏂囨。](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
@@ -13,16 +13,16 @@ @@ -13,16 +13,16 @@
13 <!-- Server 主项目 --> 13 <!-- Server 主项目 -->
14 <module>yudao-server</module> 14 <module>yudao-server</module>
15 <!-- 各种 module 拓展 --> 15 <!-- 各种 module 拓展 -->
16 - <module>yudao-module-member</module>  
17 <module>yudao-module-system</module> 16 <module>yudao-module-system</module>
18 <module>yudao-module-infra</module> 17 <module>yudao-module-infra</module>
19 - <!-- <module>yudao-module-bpm</module>--> 18 +<!-- <module>yudao-module-member</module>-->
  19 +<!-- <module>yudao-module-bpm</module>-->
20 <!-- <module>yudao-module-report</module>--> 20 <!-- <module>yudao-module-report</module>-->
21 <!-- <module>yudao-module-mp</module>--> 21 <!-- <module>yudao-module-mp</module>-->
22 - <module>yudao-module-pay</module>  
23 - <module>yudao-module-mall</module> 22 +<!-- <module>yudao-module-pay</module>-->
  23 +<!-- <module>yudao-module-mall</module>-->
24 <!-- 示例项目 --> 24 <!-- 示例项目 -->
25 - <module>yudao-example</module> 25 +<!-- <module>yudao-example</module>-->
26 </modules> 26 </modules>
27 27
28 <name>${project.artifactId}</name> 28 <name>${project.artifactId}</name>
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 30 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
31 31
32 <properties> 32 <properties>
33 - <revision>1.8.2-snapshot</revision> 33 + <revision>1.8.3-snapshot</revision>
34 <!-- Maven 相关 --> 34 <!-- Maven 相关 -->
35 <java.version>1.8</java.version> 35 <java.version>1.8</java.version>
36 <maven.compiler.source>${java.version}</maven.compiler.source> 36 <maven.compiler.source>${java.version}</maven.compiler.source>
@@ -40,7 +40,7 @@ @@ -40,7 +40,7 @@
40 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version> 40 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
41 <!-- 看看咋放到 bom 里 --> 41 <!-- 看看咋放到 bom 里 -->
42 <lombok.version>1.18.30</lombok.version> 42 <lombok.version>1.18.30</lombok.version>
43 - <spring.boot.version>2.7.16</spring.boot.version> 43 + <spring.boot.version>2.7.17</spring.boot.version>
44 <mapstruct.version>1.5.5.Final</mapstruct.version> 44 <mapstruct.version>1.5.5.Final</mapstruct.version>
45 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 45 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
46 </properties> 46 </properties>
yudao-dependencies/pom.xml
@@ -14,28 +14,30 @@ @@ -14,28 +14,30 @@
14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
15 15
16 <properties> 16 <properties>
17 - <revision>1.8.2-snapshot</revision> 17 + <revision>1.8.3-snapshot</revision>
18 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version> 18 <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
19 <!-- 统一依赖管理 --> 19 <!-- 统一依赖管理 -->
20 - <spring.boot.version>2.7.16</spring.boot.version> 20 + <spring.boot.version>2.7.17</spring.boot.version>
21 <!-- Web 相关 --> 21 <!-- Web 相关 -->
22 <springdoc.version>1.6.15</springdoc.version> 22 <springdoc.version>1.6.15</springdoc.version>
23 <knife4j.version>4.3.0</knife4j.version> 23 <knife4j.version>4.3.0</knife4j.version>
24 <servlet.versoin>2.5</servlet.versoin> 24 <servlet.versoin>2.5</servlet.versoin>
25 <!-- DB 相关 --> 25 <!-- DB 相关 -->
26 - <druid.version>1.2.19</druid.version>  
27 - <mybatis-plus.version>3.5.3.2</mybatis-plus.version>  
28 - <mybatis-plus-generator.version>3.5.3.2</mybatis-plus-generator.version> 26 + <druid.version>1.2.20</druid.version>
  27 + <mybatis-plus.version>3.5.4</mybatis-plus.version>
  28 + <mybatis-plus-generator.version>3.5.4</mybatis-plus-generator.version>
29 <dynamic-datasource.version>3.6.1</dynamic-datasource.version> 29 <dynamic-datasource.version>3.6.1</dynamic-datasource.version>
30 - <mybatis-plus-join.version>1.4.6</mybatis-plus-join.version> 30 + <mybatis-plus-join.version>1.4.7</mybatis-plus-join.version>
31 <redisson.version>3.18.0</redisson.version> 31 <redisson.version>3.18.0</redisson.version>
32 - <dm8.jdbc.version>8.1.2.141</dm8.jdbc.version> 32 + <dm8.jdbc.version>8.1.3.62</dm8.jdbc.version>
  33 + <!-- 消息队列 -->
  34 + <rocketmq-spring.version>2.2.3</rocketmq-spring.version>
33 <!-- 服务保障相关 --> 35 <!-- 服务保障相关 -->
34 - <lock4j.version>2.2.3</lock4j.version> 36 + <lock4j.version>2.2.5</lock4j.version>
35 <resilience4j.version>1.7.1</resilience4j.version> 37 <resilience4j.version>1.7.1</resilience4j.version>
36 <!-- 监控相关 --> 38 <!-- 监控相关 -->
37 <skywalking.version>8.12.0</skywalking.version> 39 <skywalking.version>8.12.0</skywalking.version>
38 - <spring-boot-admin.version>2.7.10</spring-boot-admin.version> 40 + <spring-boot-admin.version>2.7.11</spring-boot-admin.version>
39 <opentracing.version>0.33.0</opentracing.version> 41 <opentracing.version>0.33.0</opentracing.version>
40 <!-- Test 测试相关 --> 42 <!-- Test 测试相关 -->
41 <podam.version>7.2.11.RELEASE</podam.version> 43 <podam.version>7.2.11.RELEASE</podam.version>
@@ -44,8 +46,8 @@ @@ -44,8 +46,8 @@
44 <!-- Bpm 工作流相关 --> 46 <!-- Bpm 工作流相关 -->
45 <flowable.version>6.8.0</flowable.version> 47 <flowable.version>6.8.0</flowable.version>
46 <!-- 工具类相关 --> 48 <!-- 工具类相关 -->
47 - <captcha-plus.version>1.0.8</captcha-plus.version>  
48 - <jsoup.version>1.16.1</jsoup.version> 49 + <captcha-plus.version>1.0.10</captcha-plus.version>
  50 + <jsoup.version>1.16.2</jsoup.version>
49 <lombok.version>1.18.30</lombok.version> 51 <lombok.version>1.18.30</lombok.version>
50 <mapstruct.version>1.5.5.Final</mapstruct.version> 52 <mapstruct.version>1.5.5.Final</mapstruct.version>
51 <hutool.version>5.8.22</hutool.version> 53 <hutool.version>5.8.22</hutool.version>
@@ -53,10 +55,10 @@ @@ -53,10 +55,10 @@
53 <velocity.version>2.3</velocity.version> 55 <velocity.version>2.3</velocity.version>
54 <screw.version>1.0.5</screw.version> 56 <screw.version>1.0.5</screw.version>
55 <fastjson.version>1.2.83</fastjson.version> 57 <fastjson.version>1.2.83</fastjson.version>
56 - <guava.version>32.1.2-jre</guava.version> 58 + <guava.version>32.1.3-jre</guava.version>
57 <guice.version>5.1.0</guice.version> 59 <guice.version>5.1.0</guice.version>
58 <transmittable-thread-local.version>2.14.2</transmittable-thread-local.version> 60 <transmittable-thread-local.version>2.14.2</transmittable-thread-local.version>
59 - <commons-net.version>3.9.0</commons-net.version> 61 + <commons-net.version>3.10.0</commons-net.version>
60 <jsch.version>0.1.55</jsch.version> 62 <jsch.version>0.1.55</jsch.version>
61 <tika-core.version>2.7.0</tika-core.version> 63 <tika-core.version>2.7.0</tika-core.version>
62 <ip2region.version>2.7.0</ip2region.version> 64 <ip2region.version>2.7.0</ip2region.version>
@@ -67,8 +69,8 @@ @@ -67,8 +69,8 @@
67 <minio.version>8.5.6</minio.version> 69 <minio.version>8.5.6</minio.version>
68 <aliyun-java-sdk-core.version>4.6.4</aliyun-java-sdk-core.version> 70 <aliyun-java-sdk-core.version>4.6.4</aliyun-java-sdk-core.version>
69 <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version> 71 <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
70 - <tencentcloud-sdk-java.version>3.1.853</tencentcloud-sdk-java.version>  
71 - <justauth.version>1.0.5</justauth.version> 72 + <tencentcloud-sdk-java.version>3.1.880</tencentcloud-sdk-java.version>
  73 + <justauth.version>1.0.7</justauth.version>
72 <jimureport.version>1.6.1</jimureport.version> 74 <jimureport.version>1.6.1</jimureport.version>
73 <xercesImpl.version>2.12.2</xercesImpl.version> 75 <xercesImpl.version>2.12.2</xercesImpl.version>
74 <weixin-java.version>4.5.0</weixin-java.version> 76 <weixin-java.version>4.5.0</weixin-java.version>
@@ -98,11 +100,6 @@ @@ -98,11 +100,6 @@
98 </dependency> 100 </dependency>
99 <dependency> 101 <dependency>
100 <groupId>cn.iocoder.boot</groupId> 102 <groupId>cn.iocoder.boot</groupId>
101 - <artifactId>yudao-spring-boot-starter-biz-trade</artifactId>  
102 - <version>${revision}</version>  
103 - </dependency>  
104 - <dependency>  
105 - <groupId>cn.iocoder.boot</groupId>  
106 <artifactId>yudao-spring-boot-starter-biz-dict</artifactId> 103 <artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
107 <version>${revision}</version> 104 <version>${revision}</version>
108 </dependency> 105 </dependency>
@@ -260,6 +257,12 @@ @@ -260,6 +257,12 @@
260 <version>${revision}</version> 257 <version>${revision}</version>
261 </dependency> 258 </dependency>
262 259
  260 + <dependency>
  261 + <groupId>org.apache.rocketmq</groupId>
  262 + <artifactId>rocketmq-spring-boot-starter</artifactId>
  263 + <version>${rocketmq-spring.version}</version>
  264 + </dependency>
  265 +
263 <!-- 服务保障相关 --> 266 <!-- 服务保障相关 -->
264 <dependency> 267 <dependency>
265 <groupId>cn.iocoder.boot</groupId> 268 <groupId>cn.iocoder.boot</groupId>
yudao-example/yudao-sso-demo-by-code/pom.xml
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 <maven.compiler.target>8</maven.compiler.target> 21 <maven.compiler.target>8</maven.compiler.target>
22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23 <!-- 统一依赖管理 --> 23 <!-- 统一依赖管理 -->
24 - <spring.boot.version>2.7.16</spring.boot.version> 24 + <spring.boot.version>2.7.17</spring.boot.version>
25 </properties> 25 </properties>
26 26
27 <dependencyManagement> 27 <dependencyManagement>
yudao-example/yudao-sso-demo-by-password/pom.xml
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 <maven.compiler.target>8</maven.compiler.target> 21 <maven.compiler.target>8</maven.compiler.target>
22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23 <!-- 统一依赖管理 --> 23 <!-- 统一依赖管理 -->
24 - <spring.boot.version>2.7.16</spring.boot.version> 24 + <spring.boot.version>2.7.17</spring.boot.version>
25 </properties> 25 </properties>
26 26
27 <dependencyManagement> 27 <dependencyManagement>
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/core/KeyValue.java
@@ -4,6 +4,8 @@ import lombok.AllArgsConstructor; @@ -4,6 +4,8 @@ import lombok.AllArgsConstructor;
4 import lombok.Data; 4 import lombok.Data;
5 import lombok.NoArgsConstructor; 5 import lombok.NoArgsConstructor;
6 6
  7 +import java.io.Serializable;
  8 +
7 /** 9 /**
8 * Key Value 的键值对 10 * Key Value 的键值对
9 * 11 *
@@ -12,7 +14,7 @@ import lombok.NoArgsConstructor; @@ -12,7 +14,7 @@ import lombok.NoArgsConstructor;
12 @Data 14 @Data
13 @NoArgsConstructor 15 @NoArgsConstructor
14 @AllArgsConstructor 16 @AllArgsConstructor
15 -public class KeyValue<K, V> { 17 +public class KeyValue<K, V> implements Serializable {
16 18
17 private K key; 19 private K key;
18 private V value; 20 private V value;
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
@@ -8,6 +8,7 @@ import com.google.common.collect.ImmutableMap; @@ -8,6 +8,7 @@ import com.google.common.collect.ImmutableMap;
8 import java.util.*; 8 import java.util.*;
9 import java.util.function.*; 9 import java.util.function.*;
10 import java.util.stream.Collectors; 10 import java.util.stream.Collectors;
  11 +import java.util.stream.Stream;
11 12
12 import static java.util.Arrays.asList; 13 import static java.util.Arrays.asList;
13 14
@@ -271,4 +272,20 @@ public class CollectionUtils { @@ -271,4 +272,20 @@ public class CollectionUtils {
271 return deptId == null ? Collections.emptyList() : Collections.singleton(deptId); 272 return deptId == null ? Collections.emptyList() : Collections.singleton(deptId);
272 } 273 }
273 274
  275 + public static <T, U> List<U> convertListByFlatMap(Collection<T> from,
  276 + Function<T, ? extends Stream<? extends U>> func) {
  277 + if (CollUtil.isEmpty(from)) {
  278 + return new ArrayList<>();
  279 + }
  280 + return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
  281 + }
  282 +
  283 + public static <T, U> Set<U> convertSetByFlatMap(Collection<T> from,
  284 + Function<T, ? extends Stream<? extends U>> func) {
  285 + if (CollUtil.isEmpty(from)) {
  286 + return new HashSet<>();
  287 + }
  288 + return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
  289 + }
  290 +
274 } 291 }
yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeConfiguration.java renamed to yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeAutoConfiguration.java
@@ -21,7 +21,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; @@ -21,7 +21,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
21 @ConditionalOnProperty(prefix = "yudao.error-code", value = "enable", matchIfMissing = true) // 允许使用 yudao.error-code.enable=false 禁用访问日志 21 @ConditionalOnProperty(prefix = "yudao.error-code", value = "enable", matchIfMissing = true) // 允许使用 yudao.error-code.enable=false 禁用访问日志
22 @EnableConfigurationProperties(ErrorCodeProperties.class) 22 @EnableConfigurationProperties(ErrorCodeProperties.class)
23 @EnableScheduling // 开启调度任务的功能,因为 ErrorCodeRemoteLoader 通过定时刷新错误码 23 @EnableScheduling // 开启调度任务的功能,因为 ErrorCodeRemoteLoader 通过定时刷新错误码
24 -public class YudaoErrorCodeConfiguration { 24 +public class YudaoErrorCodeAutoConfiguration {
25 25
26 @Bean 26 @Bean
27 public ErrorCodeAutoGenerator errorCodeAutoGenerator(@Value("${spring.application.name}") String applicationName, 27 public ErrorCodeAutoGenerator errorCodeAutoGenerator(@Value("${spring.application.name}") String applicationName,
yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
1 -cn.iocoder.yudao.framework.errorcode.config.YudaoErrorCodeConfiguration  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +cn.iocoder.yudao.framework.errorcode.config.YudaoErrorCodeAutoConfiguration
yudao-framework/yudao-spring-boot-starter-biz-tenant/pom.xml
@@ -48,6 +48,22 @@ @@ -48,6 +48,22 @@
48 <dependency> 48 <dependency>
49 <groupId>cn.iocoder.boot</groupId> 49 <groupId>cn.iocoder.boot</groupId>
50 <artifactId>yudao-spring-boot-starter-mq</artifactId> 50 <artifactId>yudao-spring-boot-starter-mq</artifactId>
  51 + <optional>true</optional>
  52 + </dependency>
  53 + <dependency>
  54 + <groupId>org.springframework.kafka</groupId>
  55 + <artifactId>spring-kafka</artifactId>
  56 + <optional>true</optional>
  57 + </dependency>
  58 + <dependency>
  59 + <groupId>org.springframework.amqp</groupId>
  60 + <artifactId>spring-rabbit</artifactId>
  61 + <optional>true</optional>
  62 + </dependency>
  63 + <dependency>
  64 + <groupId>org.apache.rocketmq</groupId>
  65 + <artifactId>rocketmq-spring-boot-starter</artifactId>
  66 + <optional>true</optional>
51 </dependency> 67 </dependency>
52 68
53 <!-- Test 测试相关 --> 69 <!-- Test 测试相关 -->
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java
@@ -6,7 +6,9 @@ import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties; @@ -6,7 +6,9 @@ import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties;
6 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect; 6 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect;
7 import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor; 7 import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor;
8 import cn.iocoder.yudao.framework.tenant.core.job.TenantJobAspect; 8 import cn.iocoder.yudao.framework.tenant.core.job.TenantJobAspect;
9 -import cn.iocoder.yudao.framework.tenant.core.mq.TenantRedisMessageInterceptor; 9 +import cn.iocoder.yudao.framework.tenant.core.mq.rabbitmq.TenantRabbitMQInitializer;
  10 +import cn.iocoder.yudao.framework.tenant.core.mq.redis.TenantRedisMessageInterceptor;
  11 +import cn.iocoder.yudao.framework.tenant.core.mq.rocketmq.TenantRocketMQInitializer;
10 import cn.iocoder.yudao.framework.tenant.core.redis.TenantRedisCacheManager; 12 import cn.iocoder.yudao.framework.tenant.core.redis.TenantRedisCacheManager;
11 import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter; 13 import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter;
12 import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; 14 import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
@@ -18,6 +20,7 @@ import cn.iocoder.yudao.module.system.api.tenant.TenantApi; @@ -18,6 +20,7 @@ import cn.iocoder.yudao.module.system.api.tenant.TenantApi;
18 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 20 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
19 import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; 21 import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
20 import org.springframework.boot.autoconfigure.AutoConfiguration; 22 import org.springframework.boot.autoconfigure.AutoConfiguration;
  23 +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
21 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 24 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
22 import org.springframework.boot.context.properties.EnableConfigurationProperties; 25 import org.springframework.boot.context.properties.EnableConfigurationProperties;
23 import org.springframework.boot.web.servlet.FilterRegistrationBean; 26 import org.springframework.boot.web.servlet.FilterRegistrationBean;
@@ -92,6 +95,18 @@ public class YudaoTenantAutoConfiguration { @@ -92,6 +95,18 @@ public class YudaoTenantAutoConfiguration {
92 return new TenantRedisMessageInterceptor(); 95 return new TenantRedisMessageInterceptor();
93 } 96 }
94 97
  98 + @Bean
  99 + @ConditionalOnClass(name = "org.springframework.amqp.rabbit.core.RabbitTemplate")
  100 + public TenantRabbitMQInitializer tenantRabbitMQInitializer() {
  101 + return new TenantRabbitMQInitializer();
  102 + }
  103 +
  104 + @Bean
  105 + @ConditionalOnClass(name = "org.apache.rocketmq.spring.core.RocketMQTemplate")
  106 + public TenantRocketMQInitializer tenantRocketMQInitializer() {
  107 + return new TenantRocketMQInitializer();
  108 + }
  109 +
95 // ========== Job ========== 110 // ========== Job ==========
96 111
97 @Bean 112 @Bean
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/kafka/TenantKafkaEnvironmentPostProcessor.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.kafka;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.boot.SpringApplication;
  6 +import org.springframework.boot.env.EnvironmentPostProcessor;
  7 +import org.springframework.core.env.ConfigurableEnvironment;
  8 +
  9 +/**
  10 + * 多租户的 Kafka 的 {@link EnvironmentPostProcessor} 实现类
  11 + *
  12 + * Kafka Producer 发送消息时,增加 {@link TenantKafkaProducerInterceptor} 拦截器
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@Slf4j
  17 +public class TenantKafkaEnvironmentPostProcessor implements EnvironmentPostProcessor {
  18 +
  19 + private static final String PROPERTY_KEY_INTERCEPTOR_CLASSES = "spring.kafka.producer.properties.interceptor.classes";
  20 +
  21 + @Override
  22 + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
  23 + // 添加 TenantKafkaProducerInterceptor 拦截器
  24 + try {
  25 + String value = environment.getProperty(PROPERTY_KEY_INTERCEPTOR_CLASSES);
  26 + if (StrUtil.isEmpty(value)) {
  27 + value = TenantKafkaProducerInterceptor.class.getName();
  28 + } else {
  29 + value += "," + TenantKafkaProducerInterceptor.class.getName();
  30 + }
  31 + environment.getSystemProperties().put(PROPERTY_KEY_INTERCEPTOR_CLASSES, value);
  32 + } catch (NoClassDefFoundError ignore) {
  33 + // 如果触发 NoClassDefFoundError 异常,说明 TenantKafkaProducerInterceptor 类不存在,即没引入 kafka-spring 依赖
  34 + }
  35 + }
  36 +
  37 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/kafka/TenantKafkaProducerInterceptor.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.kafka;
  2 +
  3 +import cn.hutool.core.util.ReflectUtil;
  4 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  5 +import org.apache.kafka.clients.producer.ProducerInterceptor;
  6 +import org.apache.kafka.clients.producer.ProducerRecord;
  7 +import org.apache.kafka.clients.producer.RecordMetadata;
  8 +import org.apache.kafka.common.header.Headers;
  9 +import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
  10 +
  11 +import java.util.Map;
  12 +
  13 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  14 +
  15 +/**
  16 + * Kafka 消息队列的多租户 {@link ProducerInterceptor} 实现类
  17 + *
  18 + * 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
  19 + * 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
  20 + *
  21 + * @author 芋道源码
  22 + */
  23 +public class TenantKafkaProducerInterceptor implements ProducerInterceptor<Object, Object> {
  24 +
  25 + @Override
  26 + public ProducerRecord<Object, Object> onSend(ProducerRecord<Object, Object> record) {
  27 + Long tenantId = TenantContextHolder.getTenantId();
  28 + if (tenantId != null) {
  29 + Headers headers = (Headers) ReflectUtil.getFieldValue(record, "headers"); // private 属性,没有 get 方法,智能反射
  30 + headers.add(HEADER_TENANT_ID, tenantId.toString().getBytes());
  31 + }
  32 + return record;
  33 + }
  34 +
  35 + @Override
  36 + public void onAcknowledgement(RecordMetadata metadata, Exception exception) {
  37 + }
  38 +
  39 + @Override
  40 + public void close() {
  41 + }
  42 +
  43 + @Override
  44 + public void configure(Map<String, ?> configs) {
  45 + }
  46 +
  47 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/rabbitmq/TenantRabbitMQInitializer.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.rabbitmq;
  2 +
  3 +import org.springframework.amqp.rabbit.core.RabbitTemplate;
  4 +import org.springframework.beans.BeansException;
  5 +import org.springframework.beans.factory.config.BeanPostProcessor;
  6 +
  7 +/**
  8 + * 多租户的 RabbitMQ 初始化器
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +public class TenantRabbitMQInitializer implements BeanPostProcessor {
  13 +
  14 + @Override
  15 + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  16 + if (bean instanceof RabbitTemplate) {
  17 + RabbitTemplate rabbitTemplate = (RabbitTemplate) bean;
  18 + rabbitTemplate.addBeforePublishPostProcessors(new TenantRabbitMQMessagePostProcessor());
  19 + }
  20 + return bean;
  21 + }
  22 +
  23 +}
0 \ No newline at end of file 24 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/rabbitmq/TenantRabbitMQMessagePostProcessor.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.rabbitmq;
  2 +
  3 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  4 +import org.apache.kafka.clients.producer.ProducerInterceptor;
  5 +import org.springframework.amqp.AmqpException;
  6 +import org.springframework.amqp.core.Message;
  7 +import org.springframework.amqp.core.MessagePostProcessor;
  8 +import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
  9 +
  10 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  11 +
  12 +/**
  13 + * RabbitMQ 消息队列的多租户 {@link ProducerInterceptor} 实现类
  14 + *
  15 + * 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
  16 + * 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
  17 + *
  18 + * @author 芋道源码
  19 + */
  20 +public class TenantRabbitMQMessagePostProcessor implements MessagePostProcessor {
  21 +
  22 + @Override
  23 + public Message postProcessMessage(Message message) throws AmqpException {
  24 + Long tenantId = TenantContextHolder.getTenantId();
  25 + if (tenantId != null) {
  26 + message.getMessageProperties().getHeaders().put(HEADER_TENANT_ID, tenantId);
  27 + }
  28 + return message;
  29 + }
  30 +
  31 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/TenantRedisMessageInterceptor.java renamed to yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/redis/TenantRedisMessageInterceptor.java
1 -package cn.iocoder.yudao.framework.tenant.core.mq; 1 +package cn.iocoder.yudao.framework.tenant.core.mq.redis;
2 2
3 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
4 -import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;  
5 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 4 +import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
  5 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
6 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; 6 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
7 7
8 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; 8 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/rocketmq/TenantRocketMQConsumeMessageHook.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.rocketmq;
  2 +
  3 +import cn.hutool.core.lang.Assert;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  6 +import org.apache.rocketmq.client.hook.ConsumeMessageContext;
  7 +import org.apache.rocketmq.client.hook.ConsumeMessageHook;
  8 +import org.apache.rocketmq.common.message.MessageExt;
  9 +import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
  10 +
  11 +import java.util.List;
  12 +
  13 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  14 +
  15 +/**
  16 + * RocketMQ 消息队列的多租户 {@link ConsumeMessageHook} 实现类
  17 + *
  18 + * Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +public class TenantRocketMQConsumeMessageHook implements ConsumeMessageHook {
  23 +
  24 + @Override
  25 + public String hookName() {
  26 + return getClass().getSimpleName();
  27 + }
  28 +
  29 + @Override
  30 + public void consumeMessageBefore(ConsumeMessageContext context) {
  31 + // 校验,消息必须是单条,不然设置租户可能不正确
  32 + List<MessageExt> messages = context.getMsgList();
  33 + Assert.isTrue(messages.size() == 1, "消息条数({})不正确", messages.size());
  34 + // 设置租户编号
  35 + String tenantId = messages.get(0).getUserProperty(HEADER_TENANT_ID);
  36 + if (StrUtil.isNotEmpty(tenantId)) {
  37 + TenantContextHolder.setTenantId(Long.parseLong(tenantId));
  38 + }
  39 + }
  40 +
  41 + @Override
  42 + public void consumeMessageAfter(ConsumeMessageContext context) {
  43 + TenantContextHolder.clear();
  44 + }
  45 +
  46 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/rocketmq/TenantRocketMQInitializer.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.rocketmq;
  2 +
  3 +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
  4 +import org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl;
  5 +import org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl;
  6 +import org.apache.rocketmq.client.producer.DefaultMQProducer;
  7 +import org.apache.rocketmq.spring.core.RocketMQTemplate;
  8 +import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer;
  9 +import org.springframework.beans.BeansException;
  10 +import org.springframework.beans.factory.config.BeanPostProcessor;
  11 +
  12 +/**
  13 + * 多租户的 RocketMQ 初始化器
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +public class TenantRocketMQInitializer implements BeanPostProcessor {
  18 +
  19 + @Override
  20 + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  21 + if (bean instanceof DefaultRocketMQListenerContainer) {
  22 + DefaultRocketMQListenerContainer container = (DefaultRocketMQListenerContainer) bean;
  23 + initTenantConsumer(container.getConsumer());
  24 + } else if (bean instanceof RocketMQTemplate) {
  25 + RocketMQTemplate template = (RocketMQTemplate) bean;
  26 + initTenantProducer(template.getProducer());
  27 + }
  28 + return bean;
  29 + }
  30 +
  31 + private void initTenantProducer(DefaultMQProducer producer) {
  32 + if (producer == null) {
  33 + return;
  34 + }
  35 + DefaultMQProducerImpl producerImpl = producer.getDefaultMQProducerImpl();
  36 + if (producerImpl == null) {
  37 + return;
  38 + }
  39 + producerImpl.registerSendMessageHook(new TenantRocketMQSendMessageHook());
  40 + }
  41 +
  42 + private void initTenantConsumer(DefaultMQPushConsumer consumer) {
  43 + if (consumer == null) {
  44 + return;
  45 + }
  46 + DefaultMQPushConsumerImpl consumerImpl = consumer.getDefaultMQPushConsumerImpl();
  47 + if (consumerImpl == null) {
  48 + return;
  49 + }
  50 + consumerImpl.registerConsumeMessageHook(new TenantRocketMQConsumeMessageHook());
  51 + }
  52 +
  53 +}
0 \ No newline at end of file 54 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/mq/rocketmq/TenantRocketMQSendMessageHook.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.tenant.core.mq.rocketmq;
  2 +
  3 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  4 +import org.apache.rocketmq.client.hook.SendMessageContext;
  5 +import org.apache.rocketmq.client.hook.SendMessageHook;
  6 +
  7 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  8 +
  9 +/**
  10 + * RocketMQ 消息队列的多租户 {@link SendMessageHook} 实现类
  11 + *
  12 + * Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +public class TenantRocketMQSendMessageHook implements SendMessageHook {
  17 +
  18 + @Override
  19 + public String hookName() {
  20 + return getClass().getSimpleName();
  21 + }
  22 +
  23 + @Override
  24 + public void sendMessageBefore(SendMessageContext sendMessageContext) {
  25 + Long tenantId = TenantContextHolder.getTenantId();
  26 + if (tenantId == null) {
  27 + return;
  28 + }
  29 + sendMessageContext.getMessage().putUserProperty(HEADER_TENANT_ID, tenantId.toString());
  30 + }
  31 +
  32 + @Override
  33 + public void sendMessageAfter(SendMessageContext sendMessageContext) {
  34 + }
  35 +
  36 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java 0 → 100644
  1 +/*
  2 + * Copyright 2002-2021 the original author or authors.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * https://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +
  17 +package org.springframework.messaging.handler.invocation;
  18 +
  19 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  20 +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
  21 +import org.springframework.core.DefaultParameterNameDiscoverer;
  22 +import org.springframework.core.MethodParameter;
  23 +import org.springframework.core.ParameterNameDiscoverer;
  24 +import org.springframework.core.ResolvableType;
  25 +import org.springframework.lang.Nullable;
  26 +import org.springframework.messaging.Message;
  27 +import org.springframework.messaging.handler.HandlerMethod;
  28 +import org.springframework.util.ObjectUtils;
  29 +
  30 +import java.lang.reflect.InvocationTargetException;
  31 +import java.lang.reflect.Method;
  32 +import java.lang.reflect.Type;
  33 +import java.util.Arrays;
  34 +
  35 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  36 +
  37 +/**
  38 + * Extension of {@link HandlerMethod} that invokes the underlying method with
  39 + * argument values resolved from the current HTTP request through a list of
  40 + * {@link HandlerMethodArgumentResolver}.
  41 + *
  42 + * 针对 rabbitmq-spring 和 kafka-spring,不存在合适的拓展点,可以实现 Consumer 消费前,读取 Header 中的 tenant-id 设置到 {@link TenantContextHolder} 中
  43 + * TODO 芋艿:持续跟进,看看有没新的拓展点
  44 + *
  45 + * @author Rossen Stoyanchev
  46 + * @author Juergen Hoeller
  47 + * @since 4.0
  48 + */
  49 +public class InvocableHandlerMethod extends HandlerMethod {
  50 +
  51 + private static final Object[] EMPTY_ARGS = new Object[0];
  52 +
  53 + private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
  54 +
  55 + private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
  56 +
  57 + /**
  58 + * Create an instance from a {@code HandlerMethod}.
  59 + */
  60 + public InvocableHandlerMethod(HandlerMethod handlerMethod) {
  61 + super(handlerMethod);
  62 + }
  63 +
  64 + /**
  65 + * Create an instance from a bean instance and a method.
  66 + */
  67 + public InvocableHandlerMethod(Object bean, Method method) {
  68 + super(bean, method);
  69 + }
  70 +
  71 + /**
  72 + * Construct a new handler method with the given bean instance, method name and parameters.
  73 + * @param bean the object bean
  74 + * @param methodName the method name
  75 + * @param parameterTypes the method parameter types
  76 + * @throws NoSuchMethodException when the method cannot be found
  77 + */
  78 + public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)
  79 + throws NoSuchMethodException {
  80 +
  81 + super(bean, methodName, parameterTypes);
  82 + }
  83 +
  84 + /**
  85 + * Set {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} to use for resolving method argument values.
  86 + */
  87 + public void setMessageMethodArgumentResolvers(HandlerMethodArgumentResolverComposite argumentResolvers) {
  88 + this.resolvers = argumentResolvers;
  89 + }
  90 +
  91 + /**
  92 + * Set the ParameterNameDiscoverer for resolving parameter names when needed
  93 + * (e.g. default request attribute name).
  94 + * <p>Default is a {@link DefaultParameterNameDiscoverer}.
  95 + */
  96 + public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
  97 + this.parameterNameDiscoverer = parameterNameDiscoverer;
  98 + }
  99 +
  100 + /**
  101 + * Invoke the method after resolving its argument values in the context of the given message.
  102 + * <p>Argument values are commonly resolved through
  103 + * {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}.
  104 + * The {@code providedArgs} parameter however may supply argument values to be used directly,
  105 + * i.e. without argument resolution.
  106 + * <p>Delegates to {@link #getMethodArgumentValues} and calls {@link #doInvoke} with the
  107 + * resolved arguments.
  108 + * @param message the current message being processed
  109 + * @param providedArgs "given" arguments matched by type, not resolved
  110 + * @return the raw value returned by the invoked method
  111 + * @throws Exception raised if no suitable argument resolver can be found,
  112 + * or if the method raised an exception
  113 + * @see #getMethodArgumentValues
  114 + * @see #doInvoke
  115 + */
  116 + @Nullable
  117 + public Object invoke(Message<?> message, Object... providedArgs) throws Exception {
  118 + Object[] args = getMethodArgumentValues(message, providedArgs);
  119 + if (logger.isTraceEnabled()) {
  120 + logger.trace("Arguments: " + Arrays.toString(args));
  121 + }
  122 + // 注意:如下是本类的改动点!!!
  123 + // 情况一:无租户编号的情况
  124 + Long tenantId= parseTenantId(message);
  125 + if (tenantId == null) {
  126 + return doInvoke(args);
  127 + }
  128 + // 情况二:有租户的情况下
  129 + return TenantUtils.execute(tenantId, () -> doInvoke(args));
  130 + }
  131 +
  132 + private Long parseTenantId(Message<?> message) {
  133 + Object tenantId = message.getHeaders().get(HEADER_TENANT_ID);
  134 + if (tenantId == null) {
  135 + return null;
  136 + }
  137 + if (tenantId instanceof Long) {
  138 + return (Long) tenantId;
  139 + }
  140 + if (tenantId instanceof Number) {
  141 + return ((Number) tenantId).longValue();
  142 + }
  143 + if (tenantId instanceof String) {
  144 + return Long.parseLong((String) tenantId);
  145 + }
  146 + if (tenantId instanceof byte[]) {
  147 + return Long.parseLong(new String((byte[]) tenantId));
  148 + }
  149 + throw new IllegalArgumentException("未知的数据类型:" + tenantId);
  150 + }
  151 +
  152 + /**
  153 + * Get the method argument values for the current message, checking the provided
  154 + * argument values and falling back to the configured argument resolvers.
  155 + * <p>The resulting array will be passed into {@link #doInvoke}.
  156 + * @since 5.1.2
  157 + */
  158 + protected Object[] getMethodArgumentValues(Message<?> message, Object... providedArgs) throws Exception {
  159 + MethodParameter[] parameters = getMethodParameters();
  160 + if (ObjectUtils.isEmpty(parameters)) {
  161 + return EMPTY_ARGS;
  162 + }
  163 +
  164 + Object[] args = new Object[parameters.length];
  165 + for (int i = 0; i < parameters.length; i++) {
  166 + MethodParameter parameter = parameters[i];
  167 + parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
  168 + args[i] = findProvidedArgument(parameter, providedArgs);
  169 + if (args[i] != null) {
  170 + continue;
  171 + }
  172 + if (!this.resolvers.supportsParameter(parameter)) {
  173 + throw new MethodArgumentResolutionException(
  174 + message, parameter, formatArgumentError(parameter, "No suitable resolver"));
  175 + }
  176 + try {
  177 + args[i] = this.resolvers.resolveArgument(parameter, message);
  178 + }
  179 + catch (Exception ex) {
  180 + // Leave stack trace for later, exception may actually be resolved and handled...
  181 + if (logger.isDebugEnabled()) {
  182 + String exMsg = ex.getMessage();
  183 + if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
  184 + logger.debug(formatArgumentError(parameter, exMsg));
  185 + }
  186 + }
  187 + throw ex;
  188 + }
  189 + }
  190 + return args;
  191 + }
  192 +
  193 + /**
  194 + * Invoke the handler method with the given argument values.
  195 + */
  196 + @Nullable
  197 + protected Object doInvoke(Object... args) throws Exception {
  198 + try {
  199 + return getBridgedMethod().invoke(getBean(), args);
  200 + }
  201 + catch (IllegalArgumentException ex) {
  202 + assertTargetBean(getBridgedMethod(), getBean(), args);
  203 + String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
  204 + throw new IllegalStateException(formatInvokeError(text, args), ex);
  205 + }
  206 + catch (InvocationTargetException ex) {
  207 + // Unwrap for HandlerExceptionResolvers ...
  208 + Throwable targetException = ex.getTargetException();
  209 + if (targetException instanceof RuntimeException) {
  210 + throw (RuntimeException) targetException;
  211 + }
  212 + else if (targetException instanceof Error) {
  213 + throw (Error) targetException;
  214 + }
  215 + else if (targetException instanceof Exception) {
  216 + throw (Exception) targetException;
  217 + }
  218 + else {
  219 + throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
  220 + }
  221 + }
  222 + }
  223 +
  224 + MethodParameter getAsyncReturnValueType(@Nullable Object returnValue) {
  225 + return new AsyncResultMethodParameter(returnValue);
  226 + }
  227 +
  228 + private class AsyncResultMethodParameter extends HandlerMethodParameter {
  229 +
  230 + @Nullable
  231 + private final Object returnValue;
  232 +
  233 + private final ResolvableType returnType;
  234 +
  235 + public AsyncResultMethodParameter(@Nullable Object returnValue) {
  236 + super(-1);
  237 + this.returnValue = returnValue;
  238 + this.returnType = ResolvableType.forType(super.getGenericParameterType()).getGeneric();
  239 + }
  240 +
  241 + protected AsyncResultMethodParameter(AsyncResultMethodParameter original) {
  242 + super(original);
  243 + this.returnValue = original.returnValue;
  244 + this.returnType = original.returnType;
  245 + }
  246 +
  247 + @Override
  248 + public Class<?> getParameterType() {
  249 + if (this.returnValue != null) {
  250 + return this.returnValue.getClass();
  251 + }
  252 + if (!ResolvableType.NONE.equals(this.returnType)) {
  253 + return this.returnType.toClass();
  254 + }
  255 + return super.getParameterType();
  256 + }
  257 +
  258 + @Override
  259 + public Type getGenericParameterType() {
  260 + return this.returnType.getType();
  261 + }
  262 +
  263 + @Override
  264 + public AsyncResultMethodParameter clone() {
  265 + return new AsyncResultMethodParameter(this);
  266 + }
  267 + }
  268 +
  269 +}
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring.factories 0 → 100644
  1 +org.springframework.boot.env.EnvironmentPostProcessor=\
  2 + cn.iocoder.yudao.framework.tenant.core.mq.kafka.TenantKafkaEnvironmentPostProcessor
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/test/java/cn/iocoder/yudao/framework/tenant/core/job/TestJob.java deleted
1 -package cn.iocoder.yudao.framework.tenant.core.job;  
2 -  
3 -import cn.hutool.core.collection.CollUtil;  
4 -import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;  
5 -import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;  
6 -import org.springframework.stereotype.Component;  
7 -  
8 -import java.util.List;  
9 -import java.util.concurrent.CopyOnWriteArrayList;  
10 -  
11 -@Component  
12 -public class TestJob implements JobHandler {  
13 -  
14 - private final List<Long> tenantIds = new CopyOnWriteArrayList<>();  
15 -  
16 - @Override  
17 - @TenantJob // 标记多租户  
18 - public String execute(String param) throws Exception {  
19 - tenantIds.add(TenantContextHolder.getTenantId());  
20 - return "success";  
21 - }  
22 -  
23 - public List<Long> getTenantIds() {  
24 - CollUtil.sort(tenantIds, Long::compareTo);  
25 - return tenantIds;  
26 - }  
27 -  
28 -}  
yudao-framework/yudao-spring-boot-starter-mq/pom.xml
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 <packaging>jar</packaging> 12 <packaging>jar</packaging>
13 13
14 <name>${project.artifactId}</name> 14 <name>${project.artifactId}</name>
15 - <description>消息队列,基于 Redis Pub/Sub 实现广播消费,基于 Stream 实现集群消费</description> 15 + <description>消息队列,支持 Redis、RocketMQ、RabbitMQ、Kafka 四种</description>
16 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 16 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
17 17
18 <dependencies> 18 <dependencies>
@@ -21,6 +21,23 @@ @@ -21,6 +21,23 @@
21 <groupId>cn.iocoder.boot</groupId> 21 <groupId>cn.iocoder.boot</groupId>
22 <artifactId>yudao-spring-boot-starter-redis</artifactId> 22 <artifactId>yudao-spring-boot-starter-redis</artifactId>
23 </dependency> 23 </dependency>
  24 +
  25 + <!-- 消息队列相关 -->
  26 + <dependency>
  27 + <groupId>org.springframework.kafka</groupId>
  28 + <artifactId>spring-kafka</artifactId>
  29 + <optional>true</optional>
  30 + </dependency>
  31 + <dependency>
  32 + <groupId>org.springframework.amqp</groupId>
  33 + <artifactId>spring-rabbit</artifactId>
  34 + <optional>true</optional>
  35 + </dependency>
  36 + <dependency>
  37 + <groupId>org.apache.rocketmq</groupId>
  38 + <artifactId>rocketmq-spring-boot-starter</artifactId>
  39 + <optional>true</optional>
  40 + </dependency>
24 </dependencies> 41 </dependencies>
25 42
26 -</project> 43 -</project>
  44 +</project>
27 \ No newline at end of file 45 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/package-info.java
1 /** 1 /**
2 - * 消息队列,基于 Redis 提供:  
3 - * 1. 基于 Pub/Sub 实现广播消费  
4 - * 2. 基于 Stream 实现集群消费 2 + * 消息队列,支持 Redis、RocketMQ、RabbitMQ、Kafka 四种
5 */ 3 */
6 package cn.iocoder.yudao.framework.mq; 4 package cn.iocoder.yudao.framework.mq;
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/rabbitmq/config/YudaoRabbitMQAutoConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.mq.rabbitmq.config;
  2 +
  3 +import cn.hutool.core.util.ReflectUtil;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.amqp.utils.SerializationUtils;
  6 +import org.springframework.boot.autoconfigure.AutoConfiguration;
  7 +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  8 +
  9 +import java.lang.reflect.Field;
  10 +
  11 +/**
  12 + * RabbitMQ 消息队列配置类
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@AutoConfiguration
  17 +@Slf4j
  18 +@ConditionalOnClass(name = "org.springframework.amqp.rabbit.core.RabbitTemplate")
  19 +public class YudaoRabbitMQAutoConfiguration {
  20 +
  21 + static {
  22 + // 强制设置 SerializationUtils 的 TRUST_ALL 为 true,避免 RabbitMQ Consumer 反序列化消息报错
  23 + // 为什么不通过设置 spring.amqp.deserialization.trust.all 呢?因为可能在 SerializationUtils static 初始化后
  24 + Field trustAllField = ReflectUtil.getField(SerializationUtils.class, "TRUST_ALL");
  25 + ReflectUtil.removeFinalModify(trustAllField);
  26 + ReflectUtil.setFieldValue(SerializationUtils.class, trustAllField, true);
  27 + }
  28 +
  29 +}
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/rabbitmq/core/package-info.java 0 → 100644
  1 +/**
  2 + * 占位符,无特殊逻辑
  3 + */
  4 +package cn.iocoder.yudao.framework.mq.rabbitmq.core;
0 \ No newline at end of file 5 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/rabbitmq/package-info.java 0 → 100644
  1 +/**
  2 + * 消息队列,基于 RabbitMQ 提供
  3 + */
  4 +package cn.iocoder.yudao.framework.mq.rabbitmq;
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQAutoConfiguration.java
1 -package cn.iocoder.yudao.framework.mq.config; 1 +package cn.iocoder.yudao.framework.mq.redis.config;
2 2
3 import cn.hutool.core.map.MapUtil; 3 import cn.hutool.core.map.MapUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 import cn.hutool.system.SystemUtil; 5 import cn.hutool.system.SystemUtil;
6 import cn.iocoder.yudao.framework.common.enums.DocumentEnum; 6 import cn.iocoder.yudao.framework.common.enums.DocumentEnum;
7 -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;  
8 -import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;  
9 -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener;  
10 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;  
11 -import cn.iocoder.yudao.framework.mq.job.RedisPendingMessageResendJob; 7 +import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
  8 +import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
  9 +import cn.iocoder.yudao.framework.mq.redis.core.job.RedisPendingMessageResendJob;
  10 +import cn.iocoder.yudao.framework.mq.redis.core.pubsub.AbstractRedisChannelMessageListener;
  11 +import cn.iocoder.yudao.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
12 import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; 12 import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
13 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
14 import org.redisson.api.RedissonClient; 14 import org.redisson.api.RedissonClient;
15 import org.springframework.beans.factory.annotation.Value; 15 import org.springframework.beans.factory.annotation.Value;
16 import org.springframework.boot.autoconfigure.AutoConfiguration; 16 import org.springframework.boot.autoconfigure.AutoConfiguration;
17 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 17 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
18 -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;  
19 import org.springframework.context.annotation.Bean; 18 import org.springframework.context.annotation.Bean;
20 import org.springframework.data.redis.connection.RedisServerCommands; 19 import org.springframework.data.redis.connection.RedisServerCommands;
21 import org.springframework.data.redis.connection.stream.Consumer; 20 import org.springframework.data.redis.connection.stream.Consumer;
@@ -27,7 +26,6 @@ import org.springframework.data.redis.core.RedisTemplate; @@ -27,7 +26,6 @@ import org.springframework.data.redis.core.RedisTemplate;
27 import org.springframework.data.redis.core.StringRedisTemplate; 26 import org.springframework.data.redis.core.StringRedisTemplate;
28 import org.springframework.data.redis.listener.ChannelTopic; 27 import org.springframework.data.redis.listener.ChannelTopic;
29 import org.springframework.data.redis.listener.RedisMessageListenerContainer; 28 import org.springframework.data.redis.listener.RedisMessageListenerContainer;
30 -import org.springframework.data.redis.stream.DefaultStreamMessageListenerContainerX;  
31 import org.springframework.data.redis.stream.StreamMessageListenerContainer; 29 import org.springframework.data.redis.stream.StreamMessageListenerContainer;
32 import org.springframework.scheduling.annotation.EnableScheduling; 30 import org.springframework.scheduling.annotation.EnableScheduling;
33 31
@@ -42,7 +40,7 @@ import java.util.Properties; @@ -42,7 +40,7 @@ import java.util.Properties;
42 @Slf4j 40 @Slf4j
43 @EnableScheduling // 启用定时任务,用于 RedisPendingMessageResendJob 重发消息 41 @EnableScheduling // 启用定时任务,用于 RedisPendingMessageResendJob 重发消息
44 @AutoConfiguration(after = YudaoRedisAutoConfiguration.class) 42 @AutoConfiguration(after = YudaoRedisAutoConfiguration.class)
45 -public class YudaoMQAutoConfiguration { 43 +public class YudaoRedisMQAutoConfiguration {
46 44
47 @Bean 45 @Bean
48 public RedisMQTemplate redisMQTemplate(StringRedisTemplate redisTemplate, 46 public RedisMQTemplate redisMQTemplate(StringRedisTemplate redisTemplate,
@@ -59,10 +57,9 @@ public class YudaoMQAutoConfiguration { @@ -59,10 +57,9 @@ public class YudaoMQAutoConfiguration {
59 * 创建 Redis Pub/Sub 广播消费的容器 57 * 创建 Redis Pub/Sub 广播消费的容器
60 */ 58 */
61 @Bean(initMethod = "start", destroyMethod = "stop") 59 @Bean(initMethod = "start", destroyMethod = "stop")
62 - @ConditionalOnBean(AbstractChannelMessageListener.class) // 只有 AbstractChannelMessageListener 存在的时候,才需要注册 Redis pubsub 监听  
63 - @ConditionalOnProperty(prefix = "yudao.mq.redis.pubsub", value = "enable", matchIfMissing = true) // 允许使用 yudao.mq.redis.pubsub.enable=false 禁用多租户 60 + @ConditionalOnBean(AbstractRedisChannelMessageListener.class) // 只有 AbstractChannelMessageListener 存在的时候,才需要注册 Redis pubsub 监听
64 public RedisMessageListenerContainer redisMessageListenerContainer( 61 public RedisMessageListenerContainer redisMessageListenerContainer(
65 - RedisMQTemplate redisMQTemplate, List<AbstractChannelMessageListener<?>> listeners) { 62 + RedisMQTemplate redisMQTemplate, List<AbstractRedisChannelMessageListener<?>> listeners) {
66 // 创建 RedisMessageListenerContainer 对象 63 // 创建 RedisMessageListenerContainer 对象
67 RedisMessageListenerContainer container = new RedisMessageListenerContainer(); 64 RedisMessageListenerContainer container = new RedisMessageListenerContainer();
68 // 设置 RedisConnection 工厂。 65 // 设置 RedisConnection 工厂。
@@ -81,9 +78,8 @@ public class YudaoMQAutoConfiguration { @@ -81,9 +78,8 @@ public class YudaoMQAutoConfiguration {
81 * 创建 Redis Stream 重新消费的任务 78 * 创建 Redis Stream 重新消费的任务
82 */ 79 */
83 @Bean 80 @Bean
84 - @ConditionalOnBean(AbstractStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听  
85 - @ConditionalOnProperty(prefix = "yudao.mq.redis.stream", value = "enable", matchIfMissing = true) // 允许使用 yudao.mq.redis.stream.enable=false 禁用多租户  
86 - public RedisPendingMessageResendJob redisPendingMessageResendJob(List<AbstractStreamMessageListener<?>> listeners, 81 + @ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听
  82 + public RedisPendingMessageResendJob redisPendingMessageResendJob(List<AbstractRedisStreamMessageListener<?>> listeners,
87 RedisMQTemplate redisTemplate, 83 RedisMQTemplate redisTemplate,
88 @Value("${spring.application.name}") String groupName, 84 @Value("${spring.application.name}") String groupName,
89 RedissonClient redissonClient) { 85 RedissonClient redissonClient) {
@@ -92,14 +88,13 @@ public class YudaoMQAutoConfiguration { @@ -92,14 +88,13 @@ public class YudaoMQAutoConfiguration {
92 88
93 /** 89 /**
94 * 创建 Redis Stream 集群消费的容器 90 * 创建 Redis Stream 集群消费的容器
95 - * <p>  
96 - * Redis Stream 的 xreadgroup 命令:https://www.geek-book.com/src/docs/redis/redis/redis.io/commands/xreadgroup.html 91 + *
  92 + * 基础知识:<a href="https://www.geek-book.com/src/docs/redis/redis/redis.io/commands/xreadgroup.html">Redis Stream 的 xreadgroup 命令</a>
97 */ 93 */
98 @Bean(initMethod = "start", destroyMethod = "stop") 94 @Bean(initMethod = "start", destroyMethod = "stop")
99 - @ConditionalOnBean(AbstractStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听  
100 - @ConditionalOnProperty(prefix = "yudao.mq.redis.stream", value = "enable", matchIfMissing = true) // 允许使用 yudao.mq.redis.stream.enable=false 禁用多租户 95 + @ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听
101 public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer( 96 public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer(
102 - RedisMQTemplate redisMQTemplate, List<AbstractStreamMessageListener<?>> listeners) { 97 + RedisMQTemplate redisMQTemplate, List<AbstractRedisStreamMessageListener<?>> listeners) {
103 RedisTemplate<String, ?> redisTemplate = redisMQTemplate.getRedisTemplate(); 98 RedisTemplate<String, ?> redisTemplate = redisMQTemplate.getRedisTemplate();
104 checkRedisVersion(redisTemplate); 99 checkRedisVersion(redisTemplate);
105 // 第一步,创建 StreamMessageListenerContainer 容器 100 // 第一步,创建 StreamMessageListenerContainer 容器
@@ -111,8 +106,7 @@ public class YudaoMQAutoConfiguration { @@ -111,8 +106,7 @@ public class YudaoMQAutoConfiguration {
111 .build(); 106 .build();
112 // 创建 container 对象 107 // 创建 container 对象
113 StreamMessageListenerContainer<String, ObjectRecord<String, String>> container = 108 StreamMessageListenerContainer<String, ObjectRecord<String, String>> container =
114 -// StreamMessageListenerContainer.create(redisTemplate.getRequiredConnectionFactory(), containerOptions);  
115 - DefaultStreamMessageListenerContainerX.create(redisMQTemplate.getRedisTemplate().getRequiredConnectionFactory(), containerOptions); 109 + StreamMessageListenerContainer.create(redisMQTemplate.getRedisTemplate().getRequiredConnectionFactory(), containerOptions);
116 110
117 // 第二步,注册监听器,消费对应的 Stream 主题 111 // 第二步,注册监听器,消费对应的 Stream 主题
118 String consumerName = buildConsumerName(); 112 String consumerName = buildConsumerName();
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/RedisMQTemplate.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/RedisMQTemplate.java
1 -package cn.iocoder.yudao.framework.mq.core; 1 +package cn.iocoder.yudao.framework.mq.redis.core;
2 2
3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
4 -import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;  
5 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage;  
6 -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;  
7 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage; 4 +import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
  5 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
  6 +import cn.iocoder.yudao.framework.mq.redis.core.pubsub.AbstractRedisChannelMessage;
  7 +import cn.iocoder.yudao.framework.mq.redis.core.stream.AbstractRedisStreamMessage;
8 import lombok.AllArgsConstructor; 8 import lombok.AllArgsConstructor;
9 import lombok.Getter; 9 import lombok.Getter;
10 import org.springframework.data.redis.connection.stream.RecordId; 10 import org.springframework.data.redis.connection.stream.RecordId;
@@ -35,7 +35,7 @@ public class RedisMQTemplate { @@ -35,7 +35,7 @@ public class RedisMQTemplate {
35 * 35 *
36 * @param message 消息 36 * @param message 消息
37 */ 37 */
38 - public <T extends AbstractChannelMessage> void send(T message) { 38 + public <T extends AbstractRedisChannelMessage> void send(T message) {
39 try { 39 try {
40 sendMessageBefore(message); 40 sendMessageBefore(message);
41 // 发送消息 41 // 发送消息
@@ -51,7 +51,7 @@ public class RedisMQTemplate { @@ -51,7 +51,7 @@ public class RedisMQTemplate {
51 * @param message 消息 51 * @param message 消息
52 * @return 消息记录的编号对象 52 * @return 消息记录的编号对象
53 */ 53 */
54 - public <T extends AbstractStreamMessage> RecordId send(T message) { 54 + public <T extends AbstractRedisStreamMessage> RecordId send(T message) {
55 try { 55 try {
56 sendMessageBefore(message); 56 sendMessageBefore(message);
57 // 发送消息 57 // 发送消息
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/interceptor/RedisMessageInterceptor.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/interceptor/RedisMessageInterceptor.java
1 -package cn.iocoder.yudao.framework.mq.core.interceptor; 1 +package cn.iocoder.yudao.framework.mq.redis.core.interceptor;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 3 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
4 4
5 /** 5 /**
6 * {@link AbstractRedisMessage} 消息拦截器 6 * {@link AbstractRedisMessage} 消息拦截器
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/job/RedisPendingMessageResendJob.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/job/RedisPendingMessageResendJob.java
1 -package cn.iocoder.yudao.framework.mq.job; 1 +package cn.iocoder.yudao.framework.mq.redis.core.job;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;  
5 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; 4 +import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
  5 +import cn.iocoder.yudao.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
6 import lombok.AllArgsConstructor; 6 import lombok.AllArgsConstructor;
7 import lombok.extern.slf4j.Slf4j; 7 import lombok.extern.slf4j.Slf4j;
8 import org.redisson.api.RLock; 8 import org.redisson.api.RLock;
@@ -33,7 +33,7 @@ public class RedisPendingMessageResendJob { @@ -33,7 +33,7 @@ public class RedisPendingMessageResendJob {
33 */ 33 */
34 private static final int EXPIRE_TIME = 5 * 60; 34 private static final int EXPIRE_TIME = 5 * 60;
35 35
36 - private final List<AbstractStreamMessageListener<?>> listeners; 36 + private final List<AbstractRedisStreamMessageListener<?>> listeners;
37 private final RedisMQTemplate redisTemplate; 37 private final RedisMQTemplate redisTemplate;
38 private final String groupName; 38 private final String groupName;
39 private final RedissonClient redissonClient; 39 private final RedissonClient redissonClient;
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/message/AbstractRedisMessage.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/message/AbstractRedisMessage.java
1 -package cn.iocoder.yudao.framework.mq.core.message; 1 +package cn.iocoder.yudao.framework.mq.redis.core.message;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 4
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessage.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/pubsub/AbstractRedisChannelMessage.java
1 -package cn.iocoder.yudao.framework.mq.core.pubsub; 1 +package cn.iocoder.yudao.framework.mq.redis.core.pubsub;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 3 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
4 import com.fasterxml.jackson.annotation.JsonIgnore; 4 import com.fasterxml.jackson.annotation.JsonIgnore;
5 5
6 /** 6 /**
@@ -8,14 +8,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore; @@ -8,14 +8,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
8 * 8 *
9 * @author 芋道源码 9 * @author 芋道源码
10 */ 10 */
11 -public abstract class AbstractChannelMessage extends AbstractRedisMessage { 11 +public abstract class AbstractRedisChannelMessage extends AbstractRedisMessage {
12 12
13 /** 13 /**
14 - * 获得 Redis Channel 14 + * 获得 Redis Channel,默认使用类名
15 * 15 *
16 * @return Channel 16 * @return Channel
17 */ 17 */
18 @JsonIgnore // 避免序列化。原因是,Redis 发布 Channel 消息的时候,已经会指定。 18 @JsonIgnore // 避免序列化。原因是,Redis 发布 Channel 消息的时候,已经会指定。
19 - public abstract String getChannel(); 19 + public String getChannel() {
  20 + return getClass().getSimpleName();
  21 + }
20 22
21 } 23 }
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessageListener.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/pubsub/AbstractRedisChannelMessageListener.java
1 -package cn.iocoder.yudao.framework.mq.core.pubsub; 1 +package cn.iocoder.yudao.framework.mq.redis.core.pubsub;
2 2
3 import cn.hutool.core.util.TypeUtil; 3 import cn.hutool.core.util.TypeUtil;
4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5 -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;  
6 -import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;  
7 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 5 +import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
  6 +import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
  7 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
8 import lombok.Setter; 8 import lombok.Setter;
9 import lombok.SneakyThrows; 9 import lombok.SneakyThrows;
10 import org.springframework.data.redis.connection.Message; 10 import org.springframework.data.redis.connection.Message;
@@ -20,7 +20,7 @@ import java.util.List; @@ -20,7 +20,7 @@ import java.util.List;
20 * 20 *
21 * @author 芋道源码 21 * @author 芋道源码
22 */ 22 */
23 -public abstract class AbstractChannelMessageListener<T extends AbstractChannelMessage> implements MessageListener { 23 +public abstract class AbstractRedisChannelMessageListener<T extends AbstractRedisChannelMessage> implements MessageListener {
24 24
25 /** 25 /**
26 * 消息类型 26 * 消息类型
@@ -37,7 +37,7 @@ public abstract class AbstractChannelMessageListener&lt;T extends AbstractChannelMe @@ -37,7 +37,7 @@ public abstract class AbstractChannelMessageListener&lt;T extends AbstractChannelMe
37 private RedisMQTemplate redisMQTemplate; 37 private RedisMQTemplate redisMQTemplate;
38 38
39 @SneakyThrows 39 @SneakyThrows
40 - protected AbstractChannelMessageListener() { 40 + protected AbstractRedisChannelMessageListener() {
41 this.messageType = getMessageClass(); 41 this.messageType = getMessageClass();
42 this.channel = messageType.getDeclaredConstructor().newInstance().getChannel(); 42 this.channel = messageType.getDeclaredConstructor().newInstance().getChannel();
43 } 43 }
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/stream/AbstractStreamMessage.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/stream/AbstractRedisStreamMessage.java
1 -package cn.iocoder.yudao.framework.mq.core.stream; 1 +package cn.iocoder.yudao.framework.mq.redis.core.stream;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 3 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
4 import com.fasterxml.jackson.annotation.JsonIgnore; 4 import com.fasterxml.jackson.annotation.JsonIgnore;
5 5
6 /** 6 /**
@@ -8,14 +8,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore; @@ -8,14 +8,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
8 * 8 *
9 * @author 芋道源码 9 * @author 芋道源码
10 */ 10 */
11 -public abstract class AbstractStreamMessage extends AbstractRedisMessage { 11 +public abstract class AbstractRedisStreamMessage extends AbstractRedisMessage {
12 12
13 /** 13 /**
14 - * 获得 Redis Stream Key 14 + * 获得 Redis Stream Key,默认使用类名
15 * 15 *
16 * @return Channel 16 * @return Channel
17 */ 17 */
18 @JsonIgnore // 避免序列化 18 @JsonIgnore // 避免序列化
19 - public abstract String getStreamKey(); 19 + public String getStreamKey() {
  20 + return getClass().getSimpleName();
  21 + }
20 22
21 } 23 }
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/stream/AbstractStreamMessageListener.java renamed to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/stream/AbstractRedisStreamMessageListener.java
1 -package cn.iocoder.yudao.framework.mq.core.stream; 1 +package cn.iocoder.yudao.framework.mq.redis.core.stream;
2 2
3 import cn.hutool.core.util.TypeUtil; 3 import cn.hutool.core.util.TypeUtil;
4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5 -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;  
6 -import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;  
7 -import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage; 5 +import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
  6 +import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
  7 +import cn.iocoder.yudao.framework.mq.redis.core.message.AbstractRedisMessage;
8 import lombok.Getter; 8 import lombok.Getter;
9 import lombok.Setter; 9 import lombok.Setter;
10 import lombok.SneakyThrows; 10 import lombok.SneakyThrows;
@@ -22,7 +22,7 @@ import java.util.List; @@ -22,7 +22,7 @@ import java.util.List;
22 * 22 *
23 * @author 芋道源码 23 * @author 芋道源码
24 */ 24 */
25 -public abstract class AbstractStreamMessageListener<T extends AbstractStreamMessage> 25 +public abstract class AbstractRedisStreamMessageListener<T extends AbstractRedisStreamMessage>
26 implements StreamListener<String, ObjectRecord<String, String>> { 26 implements StreamListener<String, ObjectRecord<String, String>> {
27 27
28 /** 28 /**
@@ -48,7 +48,7 @@ public abstract class AbstractStreamMessageListener&lt;T extends AbstractStreamMess @@ -48,7 +48,7 @@ public abstract class AbstractStreamMessageListener&lt;T extends AbstractStreamMess
48 private RedisMQTemplate redisMQTemplate; 48 private RedisMQTemplate redisMQTemplate;
49 49
50 @SneakyThrows 50 @SneakyThrows
51 - protected AbstractStreamMessageListener() { 51 + protected AbstractRedisStreamMessageListener() {
52 this.messageType = getMessageClass(); 52 this.messageType = getMessageClass();
53 this.streamKey = messageType.getDeclaredConstructor().newInstance().getStreamKey(); 53 this.streamKey = messageType.getDeclaredConstructor().newInstance().getStreamKey();
54 } 54 }
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/package-info.java 0 → 100644
  1 +/**
  2 + * 消息队列,基于 Redis 提供:
  3 + * 1. 基于 Pub/Sub 实现广播消费
  4 + * 2. 基于 Stream 实现集群消费
  5 + */
  6 +package cn.iocoder.yudao.framework.mq.redis;
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/org/springframework/data/redis/stream/DefaultStreamMessageListenerContainerX.java deleted
1 -package org.springframework.data.redis.stream;  
2 -  
3 -import cn.hutool.core.util.ReflectUtil;  
4 -import org.springframework.data.redis.connection.RedisConnectionFactory;  
5 -import org.springframework.data.redis.connection.stream.ByteRecord;  
6 -import org.springframework.data.redis.connection.stream.ReadOffset;  
7 -import org.springframework.data.redis.connection.stream.Record;  
8 -import org.springframework.util.Assert;  
9 -  
10 -import java.util.Collections;  
11 -import java.util.List;  
12 -import java.util.function.Function;  
13 -  
14 -/**  
15 - * 拓展 DefaultStreamMessageListenerContainer 实现,解决 Spring Data Redis + Redisson 结合使用时,Redisson 在 Stream 获得不到数据时,返回 null 而不是空 List,导致 NPE 异常。  
16 - * 对应 issue:https://github.com/spring-projects/spring-data-redis/issues/2147 和 https://github.com/redisson/redisson/issues/4006  
17 - * 目前看下来 Spring Data Redis 不肯加 null 判断,Redisson 暂时也没改返回 null 到空 List 的打算,所以暂时只能自己改,哽咽!  
18 - *  
19 - * @author 芋道源码  
20 - */  
21 -public class DefaultStreamMessageListenerContainerX<K, V extends Record<K, ?>> extends DefaultStreamMessageListenerContainer<K, V> {  
22 -  
23 - /**  
24 - * 参考 {@link StreamMessageListenerContainer#create(RedisConnectionFactory, StreamMessageListenerContainerOptions)} 的实现  
25 - */  
26 - public static <K, V extends Record<K, ?>> StreamMessageListenerContainer<K, V> create(RedisConnectionFactory connectionFactory, StreamMessageListenerContainer.StreamMessageListenerContainerOptions<K, V> options) {  
27 - Assert.notNull(connectionFactory, "RedisConnectionFactory must not be null!");  
28 - Assert.notNull(options, "StreamMessageListenerContainerOptions must not be null!");  
29 - return new DefaultStreamMessageListenerContainerX<>(connectionFactory, options);  
30 - }  
31 -  
32 - public DefaultStreamMessageListenerContainerX(RedisConnectionFactory connectionFactory, StreamMessageListenerContainerOptions<K, V> containerOptions) {  
33 - super(connectionFactory, containerOptions);  
34 - }  
35 -  
36 - /**  
37 - * 参考 {@link DefaultStreamMessageListenerContainer#register(StreamReadRequest, StreamListener)} 的实现  
38 - */  
39 - @Override  
40 - public Subscription register(StreamReadRequest<K> streamRequest, StreamListener<K, V> listener) {  
41 - return this.doRegisterX(getReadTaskX(streamRequest, listener));  
42 - }  
43 -  
44 - @SuppressWarnings("unchecked")  
45 - private StreamPollTask<K, V> getReadTaskX(StreamReadRequest<K> streamRequest, StreamListener<K, V> listener) {  
46 - StreamPollTask<K, V> task = ReflectUtil.invoke(this, "getReadTask", streamRequest, listener);  
47 - // 修改 readFunction 方法  
48 - Function<ReadOffset, List<ByteRecord>> readFunction = (Function<ReadOffset, List<ByteRecord>>) ReflectUtil.getFieldValue(task, "readFunction");  
49 - ReflectUtil.setFieldValue(task, "readFunction", (Function<ReadOffset, List<ByteRecord>>) readOffset -> {  
50 - List<ByteRecord> records = readFunction.apply(readOffset);  
51 - //【重点】保证 records 不是空,避免 NPE 的问题!!!  
52 - return records != null ? records : Collections.emptyList();  
53 - });  
54 - return task;  
55 - }  
56 -  
57 - private Subscription doRegisterX(Task task) {  
58 - return ReflectUtil.invoke(this, "doRegister", task);  
59 - }  
60 -  
61 -}  
62 -  
yudao-framework/yudao-spring-boot-starter-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
1 -cn.iocoder.yudao.framework.mq.config.YudaoMQAutoConfiguration  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQAutoConfiguration
  3 +cn.iocoder.yudao.framework.mq.rabbitmq.config.YudaoRabbitMQAutoConfiguration
3 \ No newline at end of file 4 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-mq/《芋道 Spring Boot 事件机制 Event 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/RocketMQ/?yudao>
yudao-framework/yudao-spring-boot-starter-mq/《芋道 Spring Boot 消息队列 Kafka 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/Kafka/?yudao>
yudao-framework/yudao-spring-boot-starter-mq/《芋道 Spring Boot 消息队列 RabbitMQ 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/RabbitMQ/?yudao>
yudao-framework/yudao-spring-boot-starter-mq/《芋道 Spring Boot 消息队列 RocketMQ 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/RocketMQ/?yudao>
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLog.java
@@ -5,7 +5,6 @@ import lombok.Data; @@ -5,7 +5,6 @@ import lombok.Data;
5 import javax.validation.constraints.NotNull; 5 import javax.validation.constraints.NotNull;
6 import java.time.LocalDateTime; 6 import java.time.LocalDateTime;
7 7
8 -// TODO @小吉祥:搞个 job,清理 14 天外的访问日志;  
9 /** 8 /**
10 * API 访问日志 9 * API 访问日志
11 * 10 *
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLog.java
@@ -5,7 +5,6 @@ import lombok.Data; @@ -5,7 +5,6 @@ import lombok.Data;
5 import javax.validation.constraints.NotNull; 5 import javax.validation.constraints.NotNull;
6 import java.time.LocalDateTime; 6 import java.time.LocalDateTime;
7 7
8 -// TODO @小吉祥:搞个 job,清理 14 天外的异常日志;  
9 /** 8 /**
10 * API 错误日志 9 * API 错误日志
11 * 10 *
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmCommentTypeEnum.java
@@ -20,16 +20,16 @@ public enum BpmCommentTypeEnum { @@ -20,16 +20,16 @@ public enum BpmCommentTypeEnum {
20 ; 20 ;
21 21
22 /** 22 /**
23 - * 结果 23 + * 操作类型
24 */ 24 */
25 private final Integer type; 25 private final Integer type;
26 /** 26 /**
27 - * 描述 27 + * 操作名字
28 */ 28 */
29 - private final String desc; 29 + private final String name;
30 /** 30 /**
31 - * 模板信息 31 + * 操作描述
32 */ 32 */
33 - private final String templateComment; 33 + private final String comment;
34 34
35 } 35 }
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceResultEnum.java
@@ -30,13 +30,13 @@ public enum BpmProcessInstanceResultEnum { @@ -30,13 +30,13 @@ public enum BpmProcessInstanceResultEnum {
30 * 相当于是 通过 APPROVE 的特殊状态 30 * 相当于是 通过 APPROVE 的特殊状态
31 * 例如:A审批, A 后加签了 B,并且审批通过了任务,但是 B 还未审批,则当前任务状态为“待后加签任务完成” 31 * 例如:A审批, A 后加签了 B,并且审批通过了任务,但是 B 还未审批,则当前任务状态为“待后加签任务完成”
32 */ 32 */
33 - ADD_SIGN_AFTER(7, "待后加签任务完成"), 33 + SIGN_AFTER(7, "待后加签任务完成"),
34 /** 34 /**
35 * 【加签】源任务未审批,但是向前加签了,所以源任务状态变为“待前加签任务完成” 35 * 【加签】源任务未审批,但是向前加签了,所以源任务状态变为“待前加签任务完成”
36 * 相当于是 处理中 PROCESS 的特殊状态 36 * 相当于是 处理中 PROCESS 的特殊状态
37 * 例如:A 审批, A 前加签了 B,B 还未审核 37 * 例如:A 审批, A 前加签了 B,B 还未审核
38 */ 38 */
39 - ADD_SIGN_BEFORE(8, "待前加签任务完成"), 39 + SIGN_BEFORE(8, "待前加签任务完成"),
40 /** 40 /**
41 * 【加签】后加签任务被创建时的初始状态 41 * 【加签】后加签任务被创建时的初始状态
42 * 相当于是 处理中 PROCESS 的特殊状态 42 * 相当于是 处理中 PROCESS 的特殊状态
@@ -71,7 +71,7 @@ public enum BpmProcessInstanceResultEnum { @@ -71,7 +71,7 @@ public enum BpmProcessInstanceResultEnum {
71 public static boolean isEndResult(Integer result) { 71 public static boolean isEndResult(Integer result) {
72 return ObjectUtils.equalsAny(result, APPROVE.getResult(), REJECT.getResult(), 72 return ObjectUtils.equalsAny(result, APPROVE.getResult(), REJECT.getResult(),
73 CANCEL.getResult(), BACK.getResult(), 73 CANCEL.getResult(), BACK.getResult(),
74 - ADD_SIGN_AFTER.getResult()); 74 + SIGN_AFTER.getResult());
75 } 75 }
76 76
77 } 77 }
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskAddSignTypeEnum.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.bpm.enums.task; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.bpm.enums.task;
3 import lombok.AllArgsConstructor; 3 import lombok.AllArgsConstructor;
4 import lombok.Getter; 4 import lombok.Getter;
5 5
6 -  
7 /** 6 /**
8 * 流程任务 -- 加签类型枚举类型 7 * 流程任务 -- 加签类型枚举类型
9 */ 8 */
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
@@ -74,7 +74,7 @@ public class BpmTaskController { @@ -74,7 +74,7 @@ public class BpmTaskController {
74 return success(true); 74 return success(true);
75 } 75 }
76 76
77 - @GetMapping("/get-return-list") 77 + @GetMapping("/return-list")
78 @Operation(summary = "获取所有可回退的节点", description = "用于【流程详情】的【回退】按钮") 78 @Operation(summary = "获取所有可回退的节点", description = "用于【流程详情】的【回退】按钮")
79 @Parameter(name = "taskId", description = "当前任务ID", required = true) 79 @Parameter(name = "taskId", description = "当前任务ID", required = true)
80 @PreAuthorize("@ss.hasPermission('bpm:task:update')") 80 @PreAuthorize("@ss.hasPermission('bpm:task:update')")
@@ -98,27 +98,28 @@ public class BpmTaskController { @@ -98,27 +98,28 @@ public class BpmTaskController {
98 return success(true); 98 return success(true);
99 } 99 }
100 100
101 - @PutMapping("/add-sign") 101 + @PutMapping("/create-sign")
102 @Operation(summary = "加签", description = "before 前加签,after 后加签") 102 @Operation(summary = "加签", description = "before 前加签,after 后加签")
103 @PreAuthorize("@ss.hasPermission('bpm:task:update')") 103 @PreAuthorize("@ss.hasPermission('bpm:task:update')")
104 - public CommonResult<Boolean> addSignTask(@Valid @RequestBody BpmTaskAddSignReqVO reqVO) {  
105 - taskService.addSignTask(getLoginUserId(), reqVO); 104 + public CommonResult<Boolean> createSignTask(@Valid @RequestBody BpmTaskAddSignReqVO reqVO) {
  105 + taskService.createSignTask(getLoginUserId(), reqVO);
106 return success(true); 106 return success(true);
107 } 107 }
108 108
109 - @PutMapping("/sub-sign") 109 + @DeleteMapping("/delete-sign")
110 @Operation(summary = "减签") 110 @Operation(summary = "减签")
111 @PreAuthorize("@ss.hasPermission('bpm:task:update')") 111 @PreAuthorize("@ss.hasPermission('bpm:task:update')")
112 - public CommonResult<Boolean> subSignTask(@Valid @RequestBody BpmTaskSubSignReqVO reqVO) {  
113 - taskService.subSignTask(getLoginUserId(), reqVO); 112 + public CommonResult<Boolean> deleteSignTask(@Valid @RequestBody BpmTaskSubSignReqVO reqVO) {
  113 + taskService.deleteSignTask(getLoginUserId(), reqVO);
114 return success(true); 114 return success(true);
115 } 115 }
116 116
117 - @GetMapping("/get-children-task-list") 117 + @GetMapping("children-list")
118 @Operation(summary = "获取能被减签的任务") 118 @Operation(summary = "获取能被减签的任务")
  119 + @Parameter(name = "parentId", description = "父级任务 ID", required = true)
119 @PreAuthorize("@ss.hasPermission('bpm:task:update')") 120 @PreAuthorize("@ss.hasPermission('bpm:task:update')")
120 - public CommonResult<List<BpmTaskSubSignRespVO>> getChildrenTaskList(@RequestParam("taskId") String taskId) {  
121 - return success(taskService.getChildrenTaskList(taskId)); 121 + public CommonResult<List<BpmTaskSubSignRespVO>> getChildrenTaskList(@RequestParam("parentId") String parentId) {
  122 + return success(taskService.getChildrenTaskList(parentId));
122 } 123 }
123 124
124 } 125 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskAddSignReqVO.java
@@ -6,6 +6,7 @@ import lombok.Data; @@ -6,6 +6,7 @@ import lombok.Data;
6 import javax.validation.constraints.NotEmpty; 6 import javax.validation.constraints.NotEmpty;
7 import java.util.Set; 7 import java.util.Set;
8 8
  9 +// TODO @海洋:类名,应该是 create 哈
9 @Schema(description = "管理后台 - 加签流程任务的 Request VO") 10 @Schema(description = "管理后台 - 加签流程任务的 Request VO")
10 @Data 11 @Data
11 public class BpmTaskAddSignReqVO { 12 public class BpmTaskAddSignReqVO {
@@ -26,4 +27,4 @@ public class BpmTaskAddSignReqVO { @@ -26,4 +27,4 @@ public class BpmTaskAddSignReqVO {
26 @NotEmpty(message = "加签原因不能为空") 27 @NotEmpty(message = "加签原因不能为空")
27 private String reason; 28 private String reason;
28 29
29 -}  
30 \ No newline at end of file 30 \ No newline at end of file
  31 +}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSubSignReqVO.java
@@ -5,6 +5,7 @@ import lombok.Data; @@ -5,6 +5,7 @@ import lombok.Data;
5 5
6 import javax.validation.constraints.NotEmpty; 6 import javax.validation.constraints.NotEmpty;
7 7
  8 +// TODO @海洋:类名,应该是 delete 哈
8 @Schema(description = "管理后台 - 减签流程任务的 Request VO") 9 @Schema(description = "管理后台 - 减签流程任务的 Request VO")
9 @Data 10 @Data
10 public class BpmTaskSubSignReqVO { 11 public class BpmTaskSubSignReqVO {
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
1 package cn.iocoder.yudao.module.bpm.convert.task; 1 package cn.iocoder.yudao.module.bpm.convert.task;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.hutool.core.date.LocalDateTimeUtil; 3 import cn.hutool.core.date.LocalDateTimeUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  7 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
7 import cn.iocoder.yudao.framework.common.util.date.DateUtils; 8 import cn.iocoder.yudao.framework.common.util.date.DateUtils;
8 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 9 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
9 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; 10 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
@@ -25,6 +26,9 @@ import java.util.Date; @@ -25,6 +26,9 @@ import java.util.Date;
25 import java.util.List; 26 import java.util.List;
26 import java.util.Map; 27 import java.util.Map;
27 28
  29 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
  30 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
  31 +
28 /** 32 /**
29 * Bpm 任务 Convert 33 * Bpm 任务 Convert
30 * 34 *
@@ -167,32 +171,31 @@ public interface BpmTaskConvert { @@ -167,32 +171,31 @@ public interface BpmTaskConvert {
167 default List<BpmTaskSubSignRespVO> convertList(List<BpmTaskExtDO> bpmTaskExtDOList, 171 default List<BpmTaskSubSignRespVO> convertList(List<BpmTaskExtDO> bpmTaskExtDOList,
168 Map<Long, AdminUserRespDTO> userMap, 172 Map<Long, AdminUserRespDTO> userMap,
169 Map<String, Task> idTaskMap){ 173 Map<String, Task> idTaskMap){
170 - return CollectionUtils.convertList(bpmTaskExtDOList, task->{  
171 - BpmTaskSubSignRespVO bpmTaskSubSignRespVO = new BpmTaskSubSignRespVO();  
172 - bpmTaskSubSignRespVO.setName(task.getName());  
173 - bpmTaskSubSignRespVO.setId(task.getTaskId());  
174 - Task sourceTask = idTaskMap.get(task.getTaskId()); 174 + return CollectionUtils.convertList(bpmTaskExtDOList, task -> {
  175 + BpmTaskSubSignRespVO bpmTaskSubSignRespVO = new BpmTaskSubSignRespVO()
  176 + .setId(task.getTaskId()).setName(task.getName());
175 // 后加签任务不会直接设置 assignee ,所以不存在 assignee 的情况,则去取 owner 177 // 后加签任务不会直接设置 assignee ,所以不存在 assignee 的情况,则去取 owner
176 - String assignee = StrUtil.isNotEmpty(sourceTask.getAssignee()) ? sourceTask.getAssignee() : sourceTask.getOwner();  
177 - AdminUserRespDTO assignUser = userMap.get(NumberUtils.parseLong(assignee));  
178 - if (assignUser != null) {  
179 - bpmTaskSubSignRespVO.setAssigneeUser(convert3(assignUser));  
180 - } 178 + Task sourceTask = idTaskMap.get(task.getTaskId());
  179 + String assignee = ObjectUtil.defaultIfBlank(sourceTask.getOwner(),sourceTask.getAssignee());
  180 + MapUtils.findAndThen(userMap,NumberUtils.parseLong(assignee),
  181 + assignUser-> bpmTaskSubSignRespVO.setAssigneeUser(convert3(assignUser)));
181 return bpmTaskSubSignRespVO; 182 return bpmTaskSubSignRespVO;
182 }); 183 });
183 } 184 }
184 185
185 /** 186 /**
186 * 转换任务为父子级 187 * 转换任务为父子级
  188 + *
187 * @param sourceList 原始数据 189 * @param sourceList 原始数据
188 * @return 转换后的父子级数组 190 * @return 转换后的父子级数组
189 */ 191 */
190 - default List<BpmTaskRespVO> convertChildrenList(List<BpmTaskRespVO> sourceList){  
191 - List<BpmTaskRespVO> childrenTaskList = CollectionUtils.filterList(sourceList, r -> StrUtil.isNotEmpty(r.getParentTaskId()));  
192 - Map<String, List<BpmTaskRespVO>> parentChildrenTaskListMap = CollectionUtils.convertMultiMap(childrenTaskList, BpmTaskRespVO::getParentTaskId); 192 + default List<BpmTaskRespVO> convertChildrenList(List<BpmTaskRespVO> sourceList) {
  193 + List<BpmTaskRespVO> childrenTaskList = filterList(sourceList, r -> StrUtil.isNotEmpty(r.getParentTaskId()));
  194 + Map<String, List<BpmTaskRespVO>> parentChildrenTaskListMap = convertMultiMap(childrenTaskList, BpmTaskRespVO::getParentTaskId);
193 for (BpmTaskRespVO bpmTaskRespVO : sourceList) { 195 for (BpmTaskRespVO bpmTaskRespVO : sourceList) {
194 bpmTaskRespVO.setChildren(parentChildrenTaskListMap.get(bpmTaskRespVO.getId())); 196 bpmTaskRespVO.setChildren(parentChildrenTaskListMap.get(bpmTaskRespVO.getId()));
195 } 197 }
196 - return CollectionUtils.filterList(sourceList, r -> StrUtil.isEmpty(r.getParentTaskId())); 198 + return filterList(sourceList, r -> StrUtil.isEmpty(r.getParentTaskId()));
197 } 199 }
  200 +
198 } 201 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java
@@ -21,13 +21,13 @@ public interface BpmTaskExtMapper extends BaseMapperX&lt;BpmTaskExtDO&gt; { @@ -21,13 +21,13 @@ public interface BpmTaskExtMapper extends BaseMapperX&lt;BpmTaskExtDO&gt; {
21 return selectList(BpmTaskExtDO::getTaskId, taskIds); 21 return selectList(BpmTaskExtDO::getTaskId, taskIds);
22 } 22 }
23 23
  24 + // TODO @海:BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST) 应该作为条件,mapper 不要有业务
24 default List<BpmTaskExtDO> selectProcessListByTaskIds(Collection<String> taskIds) { 25 default List<BpmTaskExtDO> selectProcessListByTaskIds(Collection<String> taskIds) {
25 return selectList(new LambdaQueryWrapperX<BpmTaskExtDO>() 26 return selectList(new LambdaQueryWrapperX<BpmTaskExtDO>()
26 .in(BpmTaskExtDO::getTaskId, taskIds) 27 .in(BpmTaskExtDO::getTaskId, taskIds)
27 .in(BpmTaskExtDO::getResult, BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST)); 28 .in(BpmTaskExtDO::getResult, BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST));
28 } 29 }
29 30
30 -  
31 default BpmTaskExtDO selectByTaskId(String taskId) { 31 default BpmTaskExtDO selectByTaskId(String taskId) {
32 return selectOne(BpmTaskExtDO::getTaskId, taskId); 32 return selectOne(BpmTaskExtDO::getTaskId, taskId);
33 } 33 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmSecurityConfiguration.java deleted
1 -package cn.iocoder.yudao.module.bpm.framework.bpm.config;  
2 -  
3 -import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;  
4 -import org.springframework.context.annotation.Bean;  
5 -import org.springframework.context.annotation.Configuration;  
6 -import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
7 -import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;  
8 -  
9 -/**  
10 - * @author kemengkai  
11 - * @create 2022-05-07 08:15  
12 - */  
13 -@Configuration("bpmSecurityConfiguration")  
14 -public class BpmSecurityConfiguration {  
15 -  
16 - @Bean("bpmAuthorizeRequestsCustomizer")  
17 - public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {  
18 - return new AuthorizeRequestsCustomizer() {  
19 -  
20 - @Override  
21 - public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {  
22 - // 任务回退接口  
23 - registry.antMatchers(buildAdminApi("/bpm/task/back")).permitAll();  
24 - }  
25 -  
26 - };  
27 - }  
28 -}  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
@@ -12,6 +12,7 @@ import javax.validation.Valid; @@ -12,6 +12,7 @@ import javax.validation.Valid;
12 * @author yunlongn 12 * @author yunlongn
13 */ 13 */
14 public interface BpmModelService { 14 public interface BpmModelService {
  15 +
15 /** 16 /**
16 * 获得流程模型分页 17 * 获得流程模型分页
17 * 18 *
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
@@ -288,5 +288,4 @@ public class BpmModelServiceImpl implements BpmModelService { @@ -288,5 +288,4 @@ public class BpmModelServiceImpl implements BpmModelService {
288 processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode()); 288 processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode());
289 } 289 }
290 290
291 -  
292 } 291 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
@@ -163,7 +163,7 @@ public interface BpmTaskService { @@ -163,7 +163,7 @@ public interface BpmTaskService {
163 * @param userId 被加签的用户和任务 ID,加签类型 163 * @param userId 被加签的用户和任务 ID,加签类型
164 * @param reqVO 当前用户 ID 164 * @param reqVO 当前用户 ID
165 */ 165 */
166 - void addSignTask(Long userId, BpmTaskAddSignReqVO reqVO); 166 + void createSignTask(Long userId, BpmTaskAddSignReqVO reqVO);
167 167
168 /** 168 /**
169 * 任务减签名 169 * 任务减签名
@@ -171,14 +171,14 @@ public interface BpmTaskService { @@ -171,14 +171,14 @@ public interface BpmTaskService {
171 * @param userId 当前用户ID 171 * @param userId 当前用户ID
172 * @param reqVO 被减签的任务 ID,理由 172 * @param reqVO 被减签的任务 ID,理由
173 */ 173 */
174 - void subSignTask(Long userId, BpmTaskSubSignReqVO reqVO); 174 + void deleteSignTask(Long userId, BpmTaskSubSignReqVO reqVO);
175 175
176 /** 176 /**
177 * 获取指定任务的子任务和审批人信息 177 * 获取指定任务的子任务和审批人信息
178 * 178 *
179 - * @param taskId 指定任务ID 179 + * @param parentId 指定任务ID
180 * @return 子任务列表 180 * @return 子任务列表
181 */ 181 */
182 - List<BpmTaskSubSignRespVO> getChildrenTaskList(String taskId); 182 + List<BpmTaskSubSignRespVO> getChildrenTaskList(String parentId);
183 183
184 } 184 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
@@ -53,7 +53,6 @@ import javax.annotation.Resource; @@ -53,7 +53,6 @@ import javax.annotation.Resource;
53 import javax.validation.Valid; 53 import javax.validation.Valid;
54 import java.time.LocalDateTime; 54 import java.time.LocalDateTime;
55 import java.util.*; 55 import java.util.*;
56 -import java.util.stream.Collectors;  
57 import java.util.stream.Stream; 56 import java.util.stream.Stream;
58 57
59 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 58 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -240,10 +239,11 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -240,10 +239,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
240 handleParentTask(task); 239 handleParentTask(task);
241 } 240 }
242 241
  242 +
243 /** 243 /**
244 * 审批通过存在“后加签”的任务。 244 * 审批通过存在“后加签”的任务。
245 * <p> 245 * <p>
246 - * 注意:该任务不能马上完成,需要一个中间状态(ADD_SIGN_AFTER),并激活剩余所有子任务(PROCESS)为可审批处理 246 + * 注意:该任务不能马上完成,需要一个中间状态(SIGN_AFTER),并激活剩余所有子任务(PROCESS)为可审批处理
247 * 247 *
248 * @param task 当前任务 248 * @param task 当前任务
249 * @param reqVO 前端请求参数 249 * @param reqVO 前端请求参数
@@ -251,7 +251,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -251,7 +251,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
251 private void approveAfterSignTask(Task task, BpmTaskApproveReqVO reqVO) { 251 private void approveAfterSignTask(Task task, BpmTaskApproveReqVO reqVO) {
252 // 1. 有向后加签,则该任务状态临时设置为 ADD_SIGN_AFTER 状态 252 // 1. 有向后加签,则该任务状态临时设置为 ADD_SIGN_AFTER 状态
253 taskExtMapper.updateByTaskId( 253 taskExtMapper.updateByTaskId(
254 - new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.ADD_SIGN_AFTER.getResult()) 254 + new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.SIGN_AFTER.getResult())
255 .setReason(reqVO.getReason()).setEndTime(LocalDateTime.now())); 255 .setReason(reqVO.getReason()).setEndTime(LocalDateTime.now()));
256 256
257 // 2. 激活子任务 257 // 2. 激活子任务
@@ -265,7 +265,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -265,7 +265,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
265 } 265 }
266 266
267 /** 267 /**
268 - * 处理当前任务的父任务 268 + * 处理当前任务的父任务,主要处理“加签”的情况
269 * 269 *
270 * @param task 当前任务 270 * @param task 当前任务
271 */ 271 */
@@ -274,76 +274,79 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -274,76 +274,79 @@ public class BpmTaskServiceImpl implements BpmTaskService {
274 if (StrUtil.isBlank(parentTaskId)) { 274 if (StrUtil.isBlank(parentTaskId)) {
275 return; 275 return;
276 } 276 }
277 - if (StrUtil.isNotBlank(parentTaskId)) {  
278 - // 1. 判断当前任务的父任务是否还有子任务  
279 - Long childrenTaskCount = getChildrenTaskCount(parentTaskId);  
280 - if (childrenTaskCount > 0) {  
281 - return;  
282 - }  
283 - // 2. 获取父任务  
284 - Task parentTask = validateTaskExist(parentTaskId);  
285 -  
286 - // 3. 情况一:处理向前加签  
287 - String scopeType = parentTask.getScopeType();  
288 - if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(scopeType)) {  
289 - // 3.1 如果是向前加签的任务,则调用 resolveTask 指派父任务,将 owner 重新赋值给父任务的 assignee  
290 - taskService.resolveTask(parentTaskId);  
291 - // 3.2 更新任务拓展表为处理中  
292 - taskExtMapper.updateByTaskId(  
293 - new BpmTaskExtDO().setTaskId(parentTask.getId()).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()));  
294 - } else if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(scopeType)) {  
295 - // 3. 情况二:处理向后加签  
296 - handleAfterSign(parentTask);  
297 - } 277 + // 1. 判断当前任务的父任务是否还有子任务
  278 + Long childrenTaskCount = getChildrenTaskCount(parentTaskId);
  279 + if (childrenTaskCount > 0) {
  280 + return;
  281 + }
  282 + // 2. 获取父任务
  283 + Task parentTask = validateTaskExist(parentTaskId);
298 284
299 - // 4. 子任务已处理完成,清空 scopeType 字段,修改 parentTask 信息,方便后续可以继续向前后向后加签  
300 - // 再查询一次的原因是避免报错:Task was updated by another transaction concurrently  
301 - // 因为前面处理后可能会导致 parentTask rev 字段被修改,需要重新获取最新的  
302 - parentTask = getTask(parentTaskId);  
303 - if (parentTask == null) {  
304 - // 为空的情况是:已经通过 handleAfterSign 方法将任务完成了,所以 ru_task 表会查不到数据  
305 - return;  
306 - }  
307 - clearTaskScopeTypeAndSave(parentTask); 285 + // 3. 处理加签情况
  286 + String scopeType = parentTask.getScopeType();
  287 + if(!validateSignType(scopeType)){
  288 + return;
308 } 289 }
  290 + // 3.1 情况一:处理向前加签
  291 + if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(scopeType)) {
  292 + // 3.1.1 如果是向前加签的任务,则调用 resolveTask 指派父任务,将 owner 重新赋值给父任务的 assignee,这样它就可以被审批
  293 + taskService.resolveTask(parentTaskId);
  294 + // 3.1.2 更新任务拓展表为处理中
  295 + taskExtMapper.updateByTaskId(
  296 + new BpmTaskExtDO().setTaskId(parentTask.getId()).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()));
  297 + } else if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(scopeType)) {
  298 + // 3.2 情况二:处理向后加签
  299 + handleParentTaskForAfterSign(parentTask);
  300 + }
  301 +
  302 + // 4. 子任务已处理完成,清空 scopeType 字段,修改 parentTask 信息,方便后续可以继续向前后向后加签
  303 + // 再查询一次的原因是避免报错:Task was updated by another transaction concurrently
  304 + // 因为前面处理后可能会导致 parentTask rev 字段被修改,需要重新获取最新的
  305 + parentTask = getTask(parentTaskId);
  306 + if (parentTask == null) {
  307 + // 为空的情况是:已经通过 handleAfterSign 方法将任务完成了,所以 ru_task 表会查不到数据
  308 + return;
  309 + }
  310 + clearTaskScopeTypeAndSave(parentTask);
309 } 311 }
310 312
  313 +
311 /** 314 /**
312 * 处理后加签任务 315 * 处理后加签任务
313 * 316 *
314 * @param parentTask 当前审批任务的父任务 317 * @param parentTask 当前审批任务的父任务
315 */ 318 */
316 - private void handleAfterSign(Task parentTask) { 319 + // TODO @海:这个逻辑,怎么感觉可以是 parentTask 的 parent,再去调用 handleParentTask 方法;可以微信聊下;
  320 + private void handleParentTaskForAfterSign(Task parentTask) {
317 String parentTaskId = parentTask.getId(); 321 String parentTaskId = parentTask.getId();
318 - //1. 更新 parentTask 的任务拓展表为通过,并调用 complete 完成自己 322 + // 1. 更新 parentTask 的任务拓展表为通过,并调用 complete 完成自己
319 BpmTaskExtDO currentTaskExt = taskExtMapper.selectByTaskId(parentTask.getId()); 323 BpmTaskExtDO currentTaskExt = taskExtMapper.selectByTaskId(parentTask.getId());
320 - BpmTaskExtDO currentTaskUpdateEntity = new BpmTaskExtDO().setTaskId(parentTask.getId()) 324 + BpmTaskExtDO currentTaskExtUpdateObj = new BpmTaskExtDO().setTaskId(parentTask.getId())
321 .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); 325 .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult());
322 if (currentTaskExt.getEndTime() == null) { 326 if (currentTaskExt.getEndTime() == null) {
323 // 1.1 有这个判断是因为,以前没设置过结束时间,才去设置 327 // 1.1 有这个判断是因为,以前没设置过结束时间,才去设置
324 - currentTaskUpdateEntity.setEndTime(LocalDateTime.now()); 328 + currentTaskExtUpdateObj.setEndTime(LocalDateTime.now());
325 } 329 }
326 - // 1.2 完成自己  
327 - taskExtMapper.updateByTaskId(currentTaskUpdateEntity); 330 + taskExtMapper.updateByTaskId(currentTaskExtUpdateObj);
  331 + // 1.2 完成自己(因为它已经没有子任务,所以也可以完成)
328 taskService.complete(parentTaskId); 332 taskService.complete(parentTaskId);
329 333
330 // 2. 如果有父级,递归查询上级任务是否都已经完成 334 // 2. 如果有父级,递归查询上级任务是否都已经完成
331 if (StrUtil.isEmpty(parentTask.getParentTaskId())) { 335 if (StrUtil.isEmpty(parentTask.getParentTaskId())) {
332 return; 336 return;
333 } 337 }
334 - // TODO @海:这块待讨论,脑子略乱;感觉 handleAfterSign 的后半段,和 handleParentTask 有点重叠???  
335 // 2.1 判断整条链路的任务是否完成 338 // 2.1 判断整条链路的任务是否完成
336 // 例如从 A 任务加签了一个 B 任务,B 任务又加签了一个 C 任务,C 任务加签了 D 任务 339 // 例如从 A 任务加签了一个 B 任务,B 任务又加签了一个 C 任务,C 任务加签了 D 任务
337 // 此时,D 任务完成,要一直往上找到祖先任务 A调用 complete 方法完成 A 任务 340 // 此时,D 任务完成,要一直往上找到祖先任务 A调用 complete 方法完成 A 任务
338 boolean allChildrenTaskFinish = true; 341 boolean allChildrenTaskFinish = true;
339 while (StrUtil.isNotBlank(parentTask.getParentTaskId())) { 342 while (StrUtil.isNotBlank(parentTask.getParentTaskId())) {
340 parentTask = validateTaskExist(parentTask.getParentTaskId()); 343 parentTask = validateTaskExist(parentTask.getParentTaskId());
341 - BpmTaskExtDO bpmTaskExtDO = taskExtMapper.selectByTaskId(parentTask.getId());  
342 - if (bpmTaskExtDO == null) { 344 + BpmTaskExtDO parentTaskExt = taskExtMapper.selectByTaskId(parentTask.getId());
  345 + if (parentTaskExt == null) {
343 break; 346 break;
344 } 347 }
345 - boolean currentTaskFinish = BpmProcessInstanceResultEnum.isEndResult(bpmTaskExtDO.getResult());  
346 - // 2.2 如果 allChildrenTaskFinish 已经被赋值为 false ,则不会再赋值为 true,因为整个链路没有完成 348 + boolean currentTaskFinish = BpmProcessInstanceResultEnum.isEndResult(parentTaskExt.getResult());
  349 + // 2.2 如果 allChildrenTaskFinish 已经被赋值为 false,则不会再赋值为 true,因为整个链路没有完成
347 if (allChildrenTaskFinish) { 350 if (allChildrenTaskFinish) {
348 allChildrenTaskFinish = currentTaskFinish; 351 allChildrenTaskFinish = currentTaskFinish;
349 } 352 }
@@ -354,19 +357,19 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -354,19 +357,19 @@ public class BpmTaskServiceImpl implements BpmTaskService {
354 357
355 // 3 处理非完成状态的任务 358 // 3 处理非完成状态的任务
356 // 3.1 判断当前任务的父任务是否还有子任务 359 // 3.1 判断当前任务的父任务是否还有子任务
357 - Long childrenTaskCount = getChildrenTaskCount(bpmTaskExtDO.getTaskId()); 360 + Long childrenTaskCount = getChildrenTaskCount(parentTaskExt.getTaskId());
358 if (childrenTaskCount > 0) { 361 if (childrenTaskCount > 0) {
359 continue; 362 continue;
360 } 363 }
361 // 3.2 没有子任务,判断当前任务状态是否为 ADD_SIGN_BEFORE 待前加签任务完成 364 // 3.2 没有子任务,判断当前任务状态是否为 ADD_SIGN_BEFORE 待前加签任务完成
362 - if (BpmProcessInstanceResultEnum.ADD_SIGN_BEFORE.getResult().equals(bpmTaskExtDO.getResult())) { 365 + if (BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult().equals(parentTaskExt.getResult())) {
363 // 3.3 需要修改该任务状态为处理中 366 // 3.3 需要修改该任务状态为处理中
364 - taskService.resolveTask(bpmTaskExtDO.getTaskId());  
365 - bpmTaskExtDO.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());  
366 - taskExtMapper.updateByTaskId(bpmTaskExtDO); 367 + taskService.resolveTask(parentTaskExt.getTaskId());
  368 + parentTaskExt.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
  369 + taskExtMapper.updateByTaskId(parentTaskExt);
367 } 370 }
368 // 3.4 清空 scopeType 字段,用于任务没有子任务时使用该方法,方便任务可以再次被不同的方式加签 371 // 3.4 清空 scopeType 字段,用于任务没有子任务时使用该方法,方便任务可以再次被不同的方式加签
369 - parentTask = validateTaskExist(bpmTaskExtDO.getTaskId()); 372 + parentTask = validateTaskExist(parentTaskExt.getTaskId());
370 clearTaskScopeTypeAndSave(parentTask); 373 clearTaskScopeTypeAndSave(parentTask);
371 } 374 }
372 375
@@ -387,7 +390,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -387,7 +390,6 @@ public class BpmTaskServiceImpl implements BpmTaskService {
387 taskService.saveTask(task); 390 taskService.saveTask(task);
388 } 391 }
389 392
390 -  
391 /** 393 /**
392 * 获取子任务个数 394 * 获取子任务个数
393 * 395 *
@@ -709,7 +711,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -709,7 +711,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
709 711
710 @Override 712 @Override
711 @Transactional(rollbackFor = Exception.class) 713 @Transactional(rollbackFor = Exception.class)
712 - public void addSignTask(Long userId, BpmTaskAddSignReqVO reqVO) { 714 + public void createSignTask(Long userId, BpmTaskAddSignReqVO reqVO) {
713 // 1. 获取和校验任务 715 // 1. 获取和校验任务
714 TaskEntityImpl taskEntity = validateAddSign(userId, reqVO); 716 TaskEntityImpl taskEntity = validateAddSign(userId, reqVO);
715 List<AdminUserRespDTO> userList = adminUserApi.getUserList(reqVO.getUserIdList()); 717 List<AdminUserRespDTO> userList = adminUserApi.getUserList(reqVO.getUserIdList());
@@ -728,7 +730,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -728,7 +730,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
728 // 2.3 更新扩展表状态 730 // 2.3 更新扩展表状态
729 taskExtMapper.updateByTaskId( 731 taskExtMapper.updateByTaskId(
730 new BpmTaskExtDO().setTaskId(taskEntity.getId()) 732 new BpmTaskExtDO().setTaskId(taskEntity.getId())
731 - .setResult(BpmProcessInstanceResultEnum.ADD_SIGN_BEFORE.getResult()) 733 + .setResult(BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult())
732 .setReason(reqVO.getReason())); 734 .setReason(reqVO.getReason()));
733 } 735 }
734 // 2.4 记录加签方式,完成任务时需要用到判断 736 // 2.4 记录加签方式,完成任务时需要用到判断
@@ -737,12 +739,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -737,12 +739,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
737 taskService.saveTask(taskEntity); 739 taskService.saveTask(taskEntity);
738 740
739 // 3. 创建加签任务 741 // 3. 创建加签任务
740 - createAddSignChildrenTasks(convertList(reqVO.getUserIdList(), String::valueOf), taskEntity); 742 + createSignTask(convertList(reqVO.getUserIdList(), String::valueOf), taskEntity);
741 743
742 // 4. 记录加签 comment,拼接结果为: [当前用户]向前加签/向后加签给了[多个用户],理由为:reason 744 // 4. 记录加签 comment,拼接结果为: [当前用户]向前加签/向后加签给了[多个用户],理由为:reason
743 AdminUserRespDTO currentUser = adminUserApi.getUser(userId); 745 AdminUserRespDTO currentUser = adminUserApi.getUser(userId);
744 - String comment = StrUtil.format(BpmCommentTypeEnum.ADD_SIGN.getTemplateComment(), currentUser.getNickname(), BpmTaskAddSignTypeEnum.formatDesc(reqVO.getType()),  
745 - String.join(",", convertList(userList, AdminUserRespDTO::getNickname)), reqVO.getReason()); 746 + String comment = StrUtil.format(BpmCommentTypeEnum.ADD_SIGN.getComment(), currentUser.getNickname(),
  747 + BpmTaskAddSignTypeEnum.formatDesc(reqVO.getType()), String.join(",", convertList(userList, AdminUserRespDTO::getNickname)), reqVO.getReason());
746 taskService.addComment(reqVO.getId(), taskEntity.getProcessInstanceId(), 748 taskService.addComment(reqVO.getId(), taskEntity.getProcessInstanceId(),
747 BpmCommentTypeEnum.ADD_SIGN.getType().toString(), comment); 749 BpmCommentTypeEnum.ADD_SIGN.getType().toString(), comment);
748 } 750 }
@@ -786,7 +788,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -786,7 +788,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
786 * @param addSingUserIdList 被加签的用户 ID 788 * @param addSingUserIdList 被加签的用户 ID
787 * @param taskEntity 被加签的任务 789 * @param taskEntity 被加签的任务
788 */ 790 */
789 - private void createAddSignChildrenTasks(List<String> addSingUserIdList, TaskEntityImpl taskEntity) { 791 + private void createSignTask(List<String> addSingUserIdList, TaskEntityImpl taskEntity) {
790 if (CollUtil.isEmpty(addSingUserIdList)) { 792 if (CollUtil.isEmpty(addSingUserIdList)) {
791 return; 793 return;
792 } 794 }
@@ -795,23 +797,22 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -795,23 +797,22 @@ public class BpmTaskServiceImpl implements BpmTaskService {
795 if (StrUtil.isBlank(addSignId)) { 797 if (StrUtil.isBlank(addSignId)) {
796 continue; 798 continue;
797 } 799 }
798 - createChildrenTask(taskEntity, addSignId); 800 + createSignTask(taskEntity, addSignId);
799 } 801 }
800 } 802 }
801 803
802 /** 804 /**
803 - * 创建子任务 805 + * 创建加签子任务
804 * 806 *
805 * @param parentTask 父任务 807 * @param parentTask 父任务
806 * @param assignee 子任务的执行人 808 * @param assignee 子任务的执行人
807 - * @return  
808 */ 809 */
809 - private void createChildrenTask(TaskEntityImpl parentTask, String assignee) { 810 + private void createSignTask(TaskEntityImpl parentTask, String assignee) {
810 // 1. 生成子任务 811 // 1. 生成子任务
811 TaskEntityImpl task = (TaskEntityImpl) taskService.newTask(IdUtil.fastSimpleUUID()); 812 TaskEntityImpl task = (TaskEntityImpl) taskService.newTask(IdUtil.fastSimpleUUID());
812 task = BpmTaskConvert.INSTANCE.convert(task, parentTask); 813 task = BpmTaskConvert.INSTANCE.convert(task, parentTask);
813 if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(parentTask.getScopeType())) { 814 if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(parentTask.getScopeType())) {
814 - // 2.1 前加签,才设置审批人,否则设置 owner 815 + // 2.1 前加签,设置审批人
815 task.setAssignee(assignee); 816 task.setAssignee(assignee);
816 } else { 817 } else {
817 // 2.2.1 设置 owner 不设置 assignee 是因为不能同时审批,需要等父任务完成 818 // 2.2.1 设置 owner 不设置 assignee 是因为不能同时审批,需要等父任务完成
@@ -825,9 +826,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -825,9 +826,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
825 826
826 @Override 827 @Override
827 @Transactional(rollbackFor = Exception.class) 828 @Transactional(rollbackFor = Exception.class)
828 - public void subSignTask(Long userId, BpmTaskSubSignReqVO reqVO) { 829 + public void deleteSignTask(Long userId, BpmTaskSubSignReqVO reqVO) {
  830 + // 1.1 校验 task 可以被减签
829 Task task = validateSubSign(reqVO.getId()); 831 Task task = validateSubSign(reqVO.getId());
830 - AdminUserRespDTO user = adminUserApi.getUser(userId); 832 + // 1.2 校验取消人存在
831 AdminUserRespDTO cancelUser = null; 833 AdminUserRespDTO cancelUser = null;
832 if (StrUtil.isNotBlank(task.getAssignee())) { 834 if (StrUtil.isNotBlank(task.getAssignee())) {
833 cancelUser = adminUserApi.getUser(NumberUtils.parseLong(task.getAssignee())); 835 cancelUser = adminUserApi.getUser(NumberUtils.parseLong(task.getAssignee()));
@@ -836,20 +838,24 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -836,20 +838,24 @@ public class BpmTaskServiceImpl implements BpmTaskService {
836 cancelUser = adminUserApi.getUser(NumberUtils.parseLong(task.getOwner())); 838 cancelUser = adminUserApi.getUser(NumberUtils.parseLong(task.getOwner()));
837 } 839 }
838 Assert.notNull(cancelUser, "任务中没有所有者和审批人,数据错误"); 840 Assert.notNull(cancelUser, "任务中没有所有者和审批人,数据错误");
839 - //1. 获取所有需要删除的任务 ID ,包含当前任务和所有子任务 841 +
  842 + // 2. 删除任务和对应子任务
  843 + // 2.1 获取所有需要删除的任务 ID ,包含当前任务和所有子任务
840 List<String> allTaskIdList = getAllChildTaskIds(task.getId()); 844 List<String> allTaskIdList = getAllChildTaskIds(task.getId());
841 - //2. 删除任务和所有子任务 845 + // 2.2 删除任务和所有子任务
842 taskService.deleteTasks(allTaskIdList); 846 taskService.deleteTasks(allTaskIdList);
843 - //3. 修改扩展表状态为取消 847 + // 2.3 修改扩展表状态为取消
  848 + AdminUserRespDTO user = adminUserApi.getUser(userId);
844 taskExtMapper.updateBatchByTaskIdList(allTaskIdList, new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()) 849 taskExtMapper.updateBatchByTaskIdList(allTaskIdList, new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.CANCEL.getResult())
845 .setReason(StrUtil.format("由于{}操作[减签],任务被取消", user.getNickname()))); 850 .setReason(StrUtil.format("由于{}操作[减签],任务被取消", user.getNickname())));
846 - //4.记录日志到父任务中 先记录日志是因为,通过 handleParentTask 方法之后,任务可能被完成了,并且不存在了,会报异常,所以先记录  
847 - String comment = StrUtil.format(BpmCommentTypeEnum.SUB_SIGN.getTemplateComment(), user.getNickname(), cancelUser.getNickname()); 851 +
  852 + // 3. 记录日志到父任务中。先记录日志是因为,通过 handleParentTask 方法之后,任务可能被完成了,并且不存在了,会报异常,所以先记录
  853 + String comment = StrUtil.format(BpmCommentTypeEnum.SUB_SIGN.getComment(), user.getNickname(), cancelUser.getNickname());
848 taskService.addComment(task.getParentTaskId(), task.getProcessInstanceId(), 854 taskService.addComment(task.getParentTaskId(), task.getProcessInstanceId(),
849 BpmCommentTypeEnum.SUB_SIGN.getType().toString(), comment); 855 BpmCommentTypeEnum.SUB_SIGN.getType().toString(), comment);
850 - //5. 处理当前任务的父任务  
851 - this.handleParentTask(task);  
852 856
  857 + // 4. 处理当前任务的父任务
  858 + handleParentTask(task);
853 } 859 }
854 860
855 /** 861 /**
@@ -860,14 +866,29 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -860,14 +866,29 @@ public class BpmTaskServiceImpl implements BpmTaskService {
860 */ 866 */
861 private Task validateSubSign(String id) { 867 private Task validateSubSign(String id) {
862 Task task = validateTaskExist(id); 868 Task task = validateTaskExist(id);
863 - //必须有parentId  
864 - if (StrUtil.isEmpty(task.getParentTaskId())) { 869 +
  870 + // 必须有 scopeType
  871 + String scopeType = task.getScopeType();
  872 + if (StrUtil.isEmpty(scopeType)) {
  873 + throw exception(TASK_SUB_SIGN_NO_PARENT);
  874 + }
  875 + // 并且值为 向前和向后加签
  876 + if (!validateSignType(scopeType)) {
865 throw exception(TASK_SUB_SIGN_NO_PARENT); 877 throw exception(TASK_SUB_SIGN_NO_PARENT);
866 } 878 }
867 return task; 879 return task;
868 } 880 }
869 881
870 /** 882 /**
  883 + * 判断当前类型是否为加签
  884 + * @param scopeType 任务的 scopeType
  885 + * @return 当前 scopeType 为加签则返回 true
  886 + */
  887 + private boolean validateSignType(String scopeType){
  888 + return StrUtil.equalsAny(scopeType,BpmTaskAddSignTypeEnum.BEFORE.getType(),scopeType, BpmTaskAddSignTypeEnum.AFTER.getType());
  889 + }
  890 +
  891 + /**
871 * 获取所有要被取消的删除的任务 ID 集合 892 * 获取所有要被取消的删除的任务 ID 集合
872 * 893 *
873 * @param parentTaskId 父级任务ID 894 * @param parentTaskId 父级任务ID
@@ -875,25 +896,40 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -875,25 +896,40 @@ public class BpmTaskServiceImpl implements BpmTaskService {
875 */ 896 */
876 public List<String> getAllChildTaskIds(String parentTaskId) { 897 public List<String> getAllChildTaskIds(String parentTaskId) {
877 List<String> allChildTaskIds = new ArrayList<>(); 898 List<String> allChildTaskIds = new ArrayList<>();
878 - //1. 先将自己放入  
879 - allChildTaskIds.add(parentTaskId);  
880 - //2. 递归获取子级  
881 - recursiveGetChildTaskIds(parentTaskId, allChildTaskIds); 899 + // 1. 递归获取子级
  900 + Stack<String> stack = new Stack<>();
  901 + // 1.1 将根任务ID入栈
  902 + stack.push(parentTaskId);
  903 + //控制遍历的次数不超过 Byte.MAX_VALUE,避免脏数据造成死循环
  904 + int count = 0;
  905 + // TODO @海:< 的前后空格,要注意哈;
  906 + while (!stack.isEmpty() && count<Byte.MAX_VALUE) {
  907 + // 1.2 弹出栈顶任务ID
  908 + String taskId = stack.pop();
  909 + // 1.3 将任务ID添加到结果集合中
  910 + allChildTaskIds.add(taskId);
  911 + // 1.4 获取该任务的子任务列表
  912 + // TODO @海:有个更高效的写法;一次性去 in 一层;不然每个节点,都去查询一次 db, 太浪费了;每次 in,最终就是 O(h) 查询,而不是 O(n) 查询;
  913 + List<String> childrenTaskIdList = getChildrenTaskIdList(taskId);
  914 + if (CollUtil.isNotEmpty(childrenTaskIdList)) {
  915 + for (String childTaskId : childrenTaskIdList) {
  916 + // 1.5 将子任务ID入栈,以便后续处理
  917 + stack.push(childTaskId);
  918 + }
  919 + }
  920 + count++;
  921 + }
882 return allChildTaskIds; 922 return allChildTaskIds;
883 } 923 }
884 924
885 /** 925 /**
886 - * 递归处理子级任务 926 + * 获取指定父级任务的所有子任务 ID 集合
887 * 927 *
888 - * @param taskId 当前任务ID  
889 - * @param taskIds 结果 928 + * @param parentTaskId 父任务 ID
  929 + * @return 所有子任务的 ID 集合
890 */ 930 */
891 - private void recursiveGetChildTaskIds(String taskId, List<String> taskIds) {  
892 - List<String> childrenTaskIdList = getChildrenTaskIdList(taskId);  
893 - for (String childTaskId : childrenTaskIdList) {  
894 - taskIds.add(childTaskId); // 将子任务的ID添加到集合中  
895 - recursiveGetChildTaskIds(childTaskId, taskIds); // 递归获取子任务的子任务  
896 - } 931 + private List<String> getChildrenTaskIdList(String parentTaskId) {
  932 + return convertList(getChildrenTaskList0(parentTaskId), Task::getId);
897 } 933 }
898 934
899 /** 935 /**
@@ -902,33 +938,32 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -902,33 +938,32 @@ public class BpmTaskServiceImpl implements BpmTaskService {
902 * @param parentTaskId 父任务 ID 938 * @param parentTaskId 父任务 ID
903 * @return 所有子任务的 ID 集合 939 * @return 所有子任务的 ID 集合
904 */ 940 */
905 - private List<String> getChildrenTaskIdList(String parentTaskId) { 941 + private List<Task> getChildrenTaskList0(String parentTaskId) {
906 String tableName = managementService.getTableName(TaskEntity.class); 942 String tableName = managementService.getTableName(TaskEntity.class);
907 - String sql = "select ID_ from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}";  
908 - List<Task> childrenTaskList = taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).list();  
909 - return convertList(childrenTaskList, Task::getId); 943 + // taskService.createTaskQuery() 没有 parentId 参数,所以写 sql 查询
  944 + String sql = "select ID_,OWNER_,ASSIGNEE_ from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}";
  945 + return taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).list();
910 } 946 }
911 947
  948 +
912 @Override 949 @Override
913 - public List<BpmTaskSubSignRespVO> getChildrenTaskList(String taskId) {  
914 - List<String> childrenTaskIdList = getChildrenTaskIdList(taskId);  
915 - if (CollUtil.isEmpty(childrenTaskIdList)) { 950 + public List<BpmTaskSubSignRespVO> getChildrenTaskList(String parentId) {
  951 + // 1. 只查询进行中的任务 后加签的任务,可能不存在 assignee,所以还需要查询 owner
  952 + List<Task> taskList = getChildrenTaskList0(parentId);
  953 + if (CollUtil.isEmpty(taskList)) {
916 return Collections.emptyList(); 954 return Collections.emptyList();
917 } 955 }
918 - //1. 只查询进行中的任务  
919 - List<BpmTaskExtDO> bpmTaskExtDOList = taskExtMapper.selectProcessListByTaskIds(childrenTaskIdList);  
920 - //2. 后加签的任务,可能不存在 assignee,所以还需要查询 owner  
921 - List<Task> taskList = taskService.createTaskQuery().taskIds(childrenTaskIdList).list();  
922 - Map<String, Task> idTaskMap = convertMap(taskList, TaskInfo::getId);  
923 - //3. 将 owner 和 assignee 统一到一个集合中  
924 - List<Long> userIds = taskList.stream()  
925 - .flatMap(control ->  
926 - Stream.of(control.getAssignee(), control.getOwner())  
927 - .filter(Objects::nonNull))  
928 - .distinct()  
929 - .map(NumberUtils::parseLong)  
930 - .collect(Collectors.toList()); 956 + List<String> childrenTaskIdList = convertList(taskList, Task::getId);
  957 +
  958 + // 2.1 将 owner 和 assignee 统一到一个集合中
  959 + List<Long> userIds = convertListByFlatMap(taskList, control ->
  960 + Stream.of(NumberUtils.parseLong(control.getAssignee()), NumberUtils.parseLong(control.getOwner()))
  961 + .filter(Objects::nonNull));
  962 + // 2.2 组装数据
931 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); 963 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
932 - return BpmTaskConvert.INSTANCE.convertList(bpmTaskExtDOList, userMap, idTaskMap); 964 + List<BpmTaskExtDO> taskExtList = taskExtMapper.selectProcessListByTaskIds(childrenTaskIdList);
  965 + Map<String, Task> idTaskMap = convertMap(taskList, TaskInfo::getId);
  966 + return BpmTaskConvert.INSTANCE.convertList(taskExtList, userMap, idTaskMap);
933 } 967 }
  968 +
934 } 969 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java
@@ -147,7 +147,7 @@ public class DatabaseDocController { @@ -147,7 +147,7 @@ public class DatabaseDocController {
147 */ 147 */
148 private static ProcessConfig buildProcessConfig() { 148 private static ProcessConfig buildProcessConfig() {
149 return ProcessConfig.builder() 149 return ProcessConfig.builder()
150 - .ignoreTablePrefix(Arrays.asList("QRTZ_", "ACT_")) // 忽略表前缀 150 + .ignoreTablePrefix(Arrays.asList("QRTZ_", "ACT_", "FLW_")) // 忽略表前缀
151 .build(); 151 .build();
152 } 152 }
153 153
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/security/config/SecurityConfiguration.java
@@ -29,8 +29,6 @@ public class SecurityConfiguration { @@ -29,8 +29,6 @@ public class SecurityConfiguration {
29 .antMatchers("/swagger-resources/**").anonymous() 29 .antMatchers("/swagger-resources/**").anonymous()
30 .antMatchers("/webjars/**").anonymous() 30 .antMatchers("/webjars/**").anonymous()
31 .antMatchers("/*/api-docs").anonymous(); 31 .antMatchers("/*/api-docs").anonymous();
32 - // 积木报表  
33 - registry.antMatchers("/jmreport/**").permitAll();  
34 // Spring Boot Actuator 的安全配置 32 // Spring Boot Actuator 的安全配置
35 registry.antMatchers("/actuator").anonymous() 33 registry.antMatchers("/actuator").anonymous()
36 .antMatchers("/actuator/**").anonymous(); 34 .antMatchers("/actuator/**").anonymous();
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/logger/JobLogCleanJob.java renamed to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/job/JobLogCleanJob.java
1 -package cn.iocoder.yudao.module.infra.job.logger; 1 +package cn.iocoder.yudao.module.infra.job.job;
2 2
3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; 3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
@@ -33,7 +33,7 @@ public class JobLogCleanJob implements JobHandler { @@ -33,7 +33,7 @@ public class JobLogCleanJob implements JobHandler {
33 @TenantIgnore 33 @TenantIgnore
34 public String execute(String param) { 34 public String execute(String param) {
35 Integer count = jobLogService.cleanJobLog(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT); 35 Integer count = jobLogService.cleanJobLog(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT);
36 - log.info("[count][定时执行清理定时任务日志数量 ({}) 个]", count); 36 + log.info("[execute][定时执行清理定时任务日志数量 ({}) 个]", count);
37 return String.format("定时执行清理定时任务日志数量 %s 个", count); 37 return String.format("定时执行清理定时任务日志数量 %s 个", count);
38 } 38 }
39 39
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/job/AccessLogCleanJob.java renamed to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/logger/AccessLogCleanJob.java
1 -package cn.iocoder.yudao.module.infra.job.job; 1 +package cn.iocoder.yudao.module.infra.job.logger;
2 2
3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; 3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
@@ -34,7 +34,7 @@ public class AccessLogCleanJob implements JobHandler { @@ -34,7 +34,7 @@ public class AccessLogCleanJob implements JobHandler {
34 @TenantIgnore 34 @TenantIgnore
35 public String execute(String param) { 35 public String execute(String param) {
36 Integer count = apiAccessLogService.cleanAccessLog(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT); 36 Integer count = apiAccessLogService.cleanAccessLog(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT);
37 - log.info("[count][定时执行清理访问日志数量 ({}) 个]", count); 37 + log.info("[execute][定时执行清理访问日志数量 ({}) 个]", count);
38 return String.format("定时执行清理错误日志数量 %s 个", count); 38 return String.format("定时执行清理错误日志数量 %s 个", count);
39 } 39 }
40 40
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/job/ErrorLogCleanJob.java renamed to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/logger/ErrorLogCleanJob.java
1 -package cn.iocoder.yudao.module.infra.job.job; 1 +package cn.iocoder.yudao.module.infra.job.logger;
2 2
3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; 3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 4 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
@@ -34,7 +34,7 @@ public class ErrorLogCleanJob implements JobHandler { @@ -34,7 +34,7 @@ public class ErrorLogCleanJob implements JobHandler {
34 @TenantIgnore 34 @TenantIgnore
35 public String execute(String param) { 35 public String execute(String param) {
36 Integer count = apiErrorLogService.cleanErrorLog(JOB_CLEAN_RETAIN_DAY,DELETE_LIMIT); 36 Integer count = apiErrorLogService.cleanErrorLog(JOB_CLEAN_RETAIN_DAY,DELETE_LIMIT);
37 - log.info("[count][定时执行清理错误日志数量 ({}) 个]", count); 37 + log.info("[execute][定时执行清理错误日志数量 ({}) 个]", count);
38 return String.format("定时执行清理错误日志数量 %s 个", count); 38 return String.format("定时执行清理错误日志数量 %s 个", count);
39 } 39 }
40 40
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java
@@ -58,9 +58,9 @@ public class FileConfigServiceImpl implements FileConfigService { @@ -58,9 +58,9 @@ public class FileConfigServiceImpl implements FileConfigService {
58 FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ? 58 FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ?
59 fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id); 59 fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id);
60 if (config != null) { 60 if (config != null) {
61 - fileClientFactory.createOrUpdateFileClient(id, config.getStorage(), config.getConfig()); 61 + fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());
62 } 62 }
63 - return fileClientFactory.getFileClient(id); 63 + return fileClientFactory.getFileClient(null == config ? id : config.getId());
64 } 64 }
65 65
66 }); 66 });
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/api/api.ts.vm
@@ -28,5 +28,5 @@ export function delete${simpleClassName}(id: number) { @@ -28,5 +28,5 @@ export function delete${simpleClassName}(id: number) {
28 28
29 // 导出${table.classComment} Excel 29 // 导出${table.classComment} Excel
30 export function export${simpleClassName}(params) { 30 export function export${simpleClassName}(params) {
31 - return defHttp.download({ url: '${baseURL}/export-excel', params }, '${table.classComment}.xls') 31 + return defHttp.download({ url: '${baseURL}/export-excel', params }, '${table.classComment}.xls')
32 } 32 }
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/data.ts.vm
1 -import type { BasicColumn, FormSchema } from '@/components/Table'  
2 -import { useRender } from '@/components/Table'  
3 -import { DICT_TYPE, getDictOptions } from '@/utils/dict' 1 +import type {BasicColumn, FormSchema} from '@/components/Table'
  2 +import {useRender} from '@/components/Table'
  3 +import {DICT_TYPE, getDictOptions} from '@/utils/dict'
4 4
5 export const columns: BasicColumn[] = [ 5 export const columns: BasicColumn[] = [
6 #foreach($column in $columns) 6 #foreach($column in $columns)
@@ -50,7 +50,7 @@ export const searchFormSchema: FormSchema[] = [ @@ -50,7 +50,7 @@ export const searchFormSchema: FormSchema[] = [
50 field: '${javaField}', 50 field: '${javaField}',
51 #if ($column.htmlType == "input") 51 #if ($column.htmlType == "input")
52 component: 'Input', 52 component: 'Input',
53 - #elseif ($column.htmlType == "select" || $column.htmlType == "radio") 53 + #elseif ($column.htmlType == "select")
54 component: 'Select', 54 component: 'Select',
55 componentProps: { 55 componentProps: {
56 #if ("" != $dictType)## 设置了 dictType 数据字典的情况 56 #if ("" != $dictType)## 设置了 dictType 数据字典的情况
@@ -59,6 +59,15 @@ export const searchFormSchema: FormSchema[] = [ @@ -59,6 +59,15 @@ export const searchFormSchema: FormSchema[] = [
59 options: [], 59 options: [],
60 #end 60 #end
61 }, 61 },
  62 + #elseif ($column.htmlType == "radio")
  63 + component: 'Radio',
  64 + componentProps: {
  65 + #if ("" != $dictType)## 设置了 dictType 数据字典的情况
  66 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase()),
  67 + #else## 未设置 dictType 数据字典的情况
  68 + options: [],
  69 + #end
  70 + },
62 #elseif($column.htmlType == "datetime") 71 #elseif($column.htmlType == "datetime")
63 component: 'RangePicker', 72 component: 'RangePicker',
64 #end 73 #end
@@ -181,7 +190,8 @@ export const updateFormSchema: FormSchema[] = [ @@ -181,7 +190,8 @@ export const updateFormSchema: FormSchema[] = [
181 fileType: 'file', 190 fileType: 'file',
182 maxCount: 1, 191 maxCount: 1,
183 }, 192 },
184 - #elseif($column.htmlType == "editor")## 文本编辑器component: 'Editor', 193 + #elseif($column.htmlType == "editor")## 文本编辑器
  194 + component: 'Editor',
185 #elseif($column.htmlType == "select")## 下拉框 195 #elseif($column.htmlType == "select")## 下拉框
186 component: 'Select', 196 component: 'Select',
187 componentProps: { 197 componentProps: {
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/index.vue.vm
1 <script lang="ts" setup> 1 <script lang="ts" setup>
2 -import ${ simpleClassName }Modal from './${simpleClassName}Modal.vue' 2 +import ${simpleClassName}Modal from './${simpleClassName}Modal.vue'
3 import { columns, searchFormSchema } from './${classNameVar}.data' 3 import { columns, searchFormSchema } from './${classNameVar}.data'
4 import { useI18n } from '@/hooks/web/useI18n' 4 import { useI18n } from '@/hooks/web/useI18n'
5 import { useMessage } from '@/hooks/web/useMessage' 5 import { useMessage } from '@/hooks/web/useMessage'
6 import { useModal } from '@/components/Modal' 6 import { useModal } from '@/components/Modal'
7 -import { IconEnum } from '@/enums/appEnum'  
8 -import { BasicTable, useTable, TableAction } from '@/components/Table'  
9 -import { delete${ simpleClassName }, export${ simpleClassName }, get${ simpleClassName } Page } from '@/api/${table.moduleName}/${classNameVar}' 7 +import { useTable } from '@/components/Table'
  8 +import { delete${simpleClassName}, export${simpleClassName}, get${simpleClassName}Page } from '@/api/${table.moduleName}/${classNameVar}'
10 9
11 defineOptions({ name: '${table.className}' }) 10 defineOptions({ name: '${table.className}' })
12 11
@@ -16,7 +15,7 @@ const [registerModal, { openModal }] = useModal() @@ -16,7 +15,7 @@ const [registerModal, { openModal }] = useModal()
16 15
17 const [registerTable, { getForm, reload }] = useTable({ 16 const [registerTable, { getForm, reload }] = useTable({
18 title: '${table.classComment}列表', 17 title: '${table.classComment}列表',
19 - api: get${ simpleClassName }Page, 18 + api: get${simpleClassName}Page,
20 columns, 19 columns,
21 formConfig: { labelWidth: 120, schemas: searchFormSchema }, 20 formConfig: { labelWidth: 120, schemas: searchFormSchema },
22 useSearchForm: true, 21 useSearchForm: true,
@@ -43,14 +42,14 @@ async function handleExport() { @@ -43,14 +42,14 @@ async function handleExport() {
43 iconType: 'warning', 42 iconType: 'warning',
44 content: t('common.exportMessage'), 43 content: t('common.exportMessage'),
45 async onOk() { 44 async onOk() {
46 - await export${ simpleClassName } (getForm().getFieldsValue()) 45 + await export${simpleClassName}(getForm().getFieldsValue())
47 createMessage.success(t('common.exportSuccessText')) 46 createMessage.success(t('common.exportSuccessText'))
48 }, 47 },
49 }) 48 })
50 } 49 }
51 50
52 async function handleDelete(record: Recordable) { 51 async function handleDelete(record: Recordable) {
53 - await delete${ simpleClassName } (record.id) 52 + await delete${simpleClassName}(record.id)
54 createMessage.success(t('common.delSuccessText')) 53 createMessage.success(t('common.delSuccessText'))
55 reload() 54 reload()
56 } 55 }
@@ -62,7 +61,7 @@ async function handleDelete(record: Recordable) { @@ -62,7 +61,7 @@ async function handleDelete(record: Recordable) {
62 <a-button type="primary" v-auth="['${permissionPrefix}:create']" :preIcon="IconEnum.ADD" @click="handleCreate"> 61 <a-button type="primary" v-auth="['${permissionPrefix}:create']" :preIcon="IconEnum.ADD" @click="handleCreate">
63 {{ t('action.create') }} 62 {{ t('action.create') }}
64 </a-button> 63 </a-button>
65 - <a-button type="warning" v-auth="['${permissionPrefix}:export']" :preIcon="IconEnum.EXPORT" @click="handleExport"> 64 + <a-button v-auth="['${permissionPrefix}:export']" :preIcon="IconEnum.EXPORT" @click="handleExport">
66 {{ t('action.export') }} 65 {{ t('action.export') }}
67 </a-button> 66 </a-button>
68 </template> 67 </template>
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java
@@ -258,12 +258,12 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { @@ -258,12 +258,12 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
258 Long id = fileConfig.getId(); 258 Long id = fileConfig.getId();
259 // mock 获得 Client 259 // mock 获得 Client
260 FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig()); 260 FileClient fileClient = new LocalFileClient(id, new LocalFileClientConfig());
261 - when(fileClientFactory.getFileClient(eq(0L))).thenReturn(fileClient); 261 + when(fileClientFactory.getFileClient(eq(fileConfig.getId()))).thenReturn(fileClient);
262 262
263 // 调用,并断言 263 // 调用,并断言
264 assertSame(fileClient, fileConfigService.getMasterFileClient()); 264 assertSame(fileClient, fileConfigService.getMasterFileClient());
265 // 断言缓存 265 // 断言缓存
266 - verify(fileClientFactory).createOrUpdateFileClient(eq(0L), eq(fileConfig.getStorage()), 266 + verify(fileClientFactory).createOrUpdateFileClient(eq(fileConfig.getId()), eq(fileConfig.getStorage()),
267 eq(fileConfig.getConfig())); 267 eq(fileConfig.getConfig()));
268 } 268 }
269 269
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/comment/dto/ProductCommentCreateReqDTO.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.api.comment.dto; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.api.comment.dto;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 4
  5 +import javax.validation.constraints.NotNull;
5 import java.util.List; 6 import java.util.List;
6 7
7 /** 8 /**
@@ -15,6 +16,7 @@ public class ProductCommentCreateReqDTO { @@ -15,6 +16,7 @@ public class ProductCommentCreateReqDTO {
15 /** 16 /**
16 * 商品 SKU 编号 17 * 商品 SKU 编号
17 */ 18 */
  19 + @NotNull(message = "商品 SKU 编号不能为空")
18 private Long skuId; 20 private Long skuId;
19 /** 21 /**
20 * 订单编号 22 * 订单编号
@@ -26,20 +28,19 @@ public class ProductCommentCreateReqDTO { @@ -26,20 +28,19 @@ public class ProductCommentCreateReqDTO {
26 private Long orderItemId; 28 private Long orderItemId;
27 29
28 /** 30 /**
29 - * 评分星级 1-5 分  
30 - */  
31 - private Integer scores;  
32 - /**  
33 * 描述星级 1-5 分 31 * 描述星级 1-5 分
34 */ 32 */
  33 + @NotNull(message = "描述星级不能为空")
35 private Integer descriptionScores; 34 private Integer descriptionScores;
36 /** 35 /**
37 * 服务星级 1-5 分 36 * 服务星级 1-5 分
38 */ 37 */
  38 + @NotNull(message = "服务星级不能为空")
39 private Integer benefitScores; 39 private Integer benefitScores;
40 /** 40 /**
41 * 评论内容 41 * 评论内容
42 */ 42 */
  43 + @NotNull(message = "评论内容不能为空")
43 private String content; 44 private String content;
44 /** 45 /**
45 * 评论图片地址数组,以逗号分隔最多上传 9 张 46 * 评论图片地址数组,以逗号分隔最多上传 9 张
@@ -49,11 +50,12 @@ public class ProductCommentCreateReqDTO { @@ -49,11 +50,12 @@ public class ProductCommentCreateReqDTO {
49 /** 50 /**
50 * 是否匿名 51 * 是否匿名
51 */ 52 */
  53 + @NotNull(message = "是否匿名不能为空")
52 private Boolean anonymous; 54 private Boolean anonymous;
53 /** 55 /**
54 * 评价人 56 * 评价人
55 */ 57 */
  58 + @NotNull(message = "评价人不能为空")
56 private Long userId; 59 private Long userId;
57 60
58 -  
59 } 61 }
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java deleted
1 -package cn.iocoder.yudao.module.product.api.property;  
2 -  
3 -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;  
4 -  
5 -import java.util.Collection;  
6 -import java.util.List;  
7 -  
8 -/**  
9 - * 商品属性值 API 接口  
10 - *  
11 - * @author 芋道源码  
12 - */  
13 -public interface ProductPropertyValueApi {  
14 -  
15 - /**  
16 - * 根据编号数组,获得属性值列表  
17 - *  
18 - * @param ids 编号数组  
19 - * @return 属性值明细列表  
20 - */  
21 - List<ProductPropertyValueDetailRespDTO> getPropertyValueDetailList(Collection<Long> ids);  
22 -  
23 -}  
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
@@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.product.api.spu.dto; @@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.product.api.spu.dto;
3 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; 3 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
4 import lombok.Data; 4 import lombok.Data;
5 5
6 -import java.util.List;  
7 -  
8 // TODO @LeeYan9: ProductSpuRespDTO 6 // TODO @LeeYan9: ProductSpuRespDTO
9 /** 7 /**
10 * 商品 SPU 信息 Response DTO 8 * 商品 SPU 信息 Response DTO
@@ -27,55 +25,22 @@ public class ProductSpuRespDTO { @@ -27,55 +25,22 @@ public class ProductSpuRespDTO {
27 */ 25 */
28 private String name; 26 private String name;
29 /** 27 /**
30 - * 关键字  
31 - */  
32 - private String keyword;  
33 - /**  
34 * 单位 28 * 单位
35 * 29 *
36 * 对应 product_unit 数据字典 30 * 对应 product_unit 数据字典
37 */ 31 */
38 private Integer unit; 32 private Integer unit;
39 - /**  
40 - * 商品简介  
41 - */  
42 - private String introduction;  
43 - /**  
44 - * 商品详情  
45 - */  
46 - private String description;  
47 - // TODO @芋艿:是不是要删除  
48 - /**  
49 - * 商品条码(一维码)  
50 - */  
51 - private String barCode;  
52 33
53 /** 34 /**
54 * 商品分类编号 35 * 商品分类编号
55 */ 36 */
56 private Long categoryId; 37 private Long categoryId;
57 /** 38 /**
58 - * 商品品牌编号  
59 - */  
60 - private Long brandId;  
61 - /**  
62 * 商品封面图 39 * 商品封面图
63 */ 40 */
64 private String picUrl; 41 private String picUrl;
65 - /**  
66 - * 商品轮播图  
67 - */  
68 - private List<String> sliderPicUrls;  
69 - /**  
70 - * 商品视频  
71 - */  
72 - private String videoUrl;  
73 42
74 /** 43 /**
75 - * 排序字段  
76 - */  
77 - private Integer sort;  
78 - /**  
79 * 商品状态 44 * 商品状态
80 * <p> 45 * <p>
81 * 枚举 {@link ProductSpuStatusEnum} 46 * 枚举 {@link ProductSpuStatusEnum}
@@ -124,22 +89,6 @@ public class ProductSpuRespDTO { @@ -124,22 +89,6 @@ public class ProductSpuRespDTO {
124 */ 89 */
125 private Integer giveIntegral; 90 private Integer giveIntegral;
126 91
127 - // ========== 统计相关字段 =========  
128 -  
129 - /**  
130 - * 商品销量  
131 - */  
132 - private Integer salesCount;  
133 - /**  
134 - * 虚拟销量  
135 - */  
136 - private Integer virtualSalesCount;  
137 - /**  
138 - * 商品点击量  
139 - */  
140 - private Integer clickCount;  
141 -  
142 -  
143 // ========== 分销相关字段 ========= 92 // ========== 分销相关字段 =========
144 93
145 /** 94 /**
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/group/ProductGroupStyleEnum.java deleted
1 -package cn.iocoder.yudao.module.product.enums.group;  
2 -  
3 -import cn.iocoder.yudao.framework.common.core.IntArrayValuable;  
4 -import lombok.AllArgsConstructor;  
5 -import lombok.Getter;  
6 -  
7 -import java.util.Arrays;  
8 -  
9 -/**  
10 - * 商品分组的样式枚举  
11 - *  
12 - * @author 芋道源码  
13 - */  
14 -@Getter  
15 -@AllArgsConstructor  
16 -public enum ProductGroupStyleEnum implements IntArrayValuable {  
17 -  
18 - ONE(1, "每列一个"),  
19 - TWO(2, "每列两个"),  
20 - THREE(2, "每列三个"),;  
21 -  
22 - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductGroupStyleEnum::getStyle).toArray();  
23 -  
24 - /**  
25 - * 列表样式  
26 - */  
27 - private final Integer style;  
28 - /**  
29 - * 状态名  
30 - */  
31 - private final String name;  
32 -  
33 - @Override  
34 - public int[] array() {  
35 - return ARRAYS;  
36 - }  
37 -  
38 -}  
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java deleted
1 -package cn.iocoder.yudao.module.product.api.property;  
2 -  
3 -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;  
4 -import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert;  
5 -import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;  
6 -import org.springframework.stereotype.Service;  
7 -import org.springframework.validation.annotation.Validated;  
8 -  
9 -import javax.annotation.Resource;  
10 -import java.util.Collection;  
11 -import java.util.List;  
12 -  
13 -/**  
14 - * 商品属性值 API 实现类  
15 - *  
16 - * @author 芋道源码  
17 - */  
18 -@Service  
19 -@Validated  
20 -public class ProductPropertyValueApiImpl implements ProductPropertyValueApi {  
21 -  
22 - @Resource  
23 - private ProductPropertyValueService productPropertyValueService;  
24 -  
25 - @Override  
26 - public List<ProductPropertyValueDetailRespDTO> getPropertyValueDetailList(Collection<Long> ids) {  
27 - return ProductPropertyValueConvert.INSTANCE.convertList02(  
28 - productPropertyValueService.getPropertyValueDetailList(ids));  
29 - }  
30 -  
31 -}  
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
1 package cn.iocoder.yudao.module.product.api.sku; 1 package cn.iocoder.yudao.module.product.api.sku;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; 3 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
5 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 4 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
6 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; 5 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
@@ -11,7 +10,6 @@ import org.springframework.validation.annotation.Validated; @@ -11,7 +10,6 @@ import org.springframework.validation.annotation.Validated;
11 10
12 import javax.annotation.Resource; 11 import javax.annotation.Resource;
13 import java.util.Collection; 12 import java.util.Collection;
14 -import java.util.Collections;  
15 import java.util.List; 13 import java.util.List;
16 14
17 /** 15 /**
@@ -35,18 +33,12 @@ public class ProductSkuApiImpl implements ProductSkuApi { @@ -35,18 +33,12 @@ public class ProductSkuApiImpl implements ProductSkuApi {
35 33
36 @Override 34 @Override
37 public List<ProductSkuRespDTO> getSkuList(Collection<Long> ids) { 35 public List<ProductSkuRespDTO> getSkuList(Collection<Long> ids) {
38 - if (CollUtil.isEmpty(ids)) {  
39 - return Collections.emptyList();  
40 - }  
41 List<ProductSkuDO> skus = productSkuService.getSkuList(ids); 36 List<ProductSkuDO> skus = productSkuService.getSkuList(ids);
42 return ProductSkuConvert.INSTANCE.convertList04(skus); 37 return ProductSkuConvert.INSTANCE.convertList04(skus);
43 } 38 }
44 39
45 @Override 40 @Override
46 public List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds) { 41 public List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds) {
47 - if (CollUtil.isEmpty(spuIds)) {  
48 - return Collections.emptyList();  
49 - }  
50 List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spuIds); 42 List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spuIds);
51 return ProductSkuConvert.INSTANCE.convertList04(skus); 43 return ProductSkuConvert.INSTANCE.convertList04(skus);
52 } 44 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java
@@ -27,9 +27,6 @@ public class ProductSpuApiImpl implements ProductSpuApi { @@ -27,9 +27,6 @@ public class ProductSpuApiImpl implements ProductSpuApi {
27 27
28 @Override 28 @Override
29 public List<ProductSpuRespDTO> getSpuList(Collection<Long> ids) { 29 public List<ProductSpuRespDTO> getSpuList(Collection<Long> ids) {
30 - if (CollectionUtil.isEmpty(ids)) {  
31 - return Collections.emptyList();  
32 - }  
33 return ProductSpuConvert.INSTANCE.convertList2(spuService.getSpuList(ids)); 30 return ProductSpuConvert.INSTANCE.convertList2(spuService.getSpuList(ids));
34 } 31 }
35 32
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyValueConvert.java
1 package cn.iocoder.yudao.module.product.convert.property; 1 package cn.iocoder.yudao.module.product.convert.property;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
5 -import cn.iocoder.yudao.framework.common.util.collection.MapUtils;  
6 -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;  
7 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; 4 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
8 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; 5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
9 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
10 -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;  
11 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; 7 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
12 -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;  
13 import org.mapstruct.Mapper; 8 import org.mapstruct.Mapper;
14 import org.mapstruct.factory.Mappers; 9 import org.mapstruct.factory.Mappers;
15 10
16 import java.util.List; 11 import java.util.List;
17 -import java.util.Map;  
18 -  
19 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;  
20 12
21 /** 13 /**
22 * 属性值 Convert 14 * 属性值 Convert
@@ -38,18 +30,4 @@ public interface ProductPropertyValueConvert { @@ -38,18 +30,4 @@ public interface ProductPropertyValueConvert {
38 30
39 PageResult<ProductPropertyValueRespVO> convertPage(PageResult<ProductPropertyValueDO> page); 31 PageResult<ProductPropertyValueRespVO> convertPage(PageResult<ProductPropertyValueDO> page);
40 32
41 - default List<ProductPropertyValueDetailRespBO> convertList(List<ProductPropertyValueDO> values, List<ProductPropertyDO> keys) {  
42 - Map<Long, ProductPropertyDO> keyMap = convertMap(keys, ProductPropertyDO::getId);  
43 - return CollectionUtils.convertList(values, value -> {  
44 - ProductPropertyValueDetailRespBO valueDetail = new ProductPropertyValueDetailRespBO()  
45 - .setValueId(value.getId()).setValueName(value.getName());  
46 - // 设置属性项  
47 - MapUtils.findAndThen(keyMap, value.getPropertyId(),  
48 - key -> valueDetail.setPropertyId(key.getId()).setPropertyName(key.getName()));  
49 - return valueDetail;  
50 - });  
51 - }  
52 -  
53 - List<ProductPropertyValueDetailRespDTO> convertList02(List<ProductPropertyValueDetailRespBO> list);  
54 -  
55 } 33 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java
@@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc @@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc
5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; 5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
7 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; 7 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
8 -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;  
9 8
10 import java.util.Collection; 9 import java.util.Collection;
11 import java.util.List; 10 import java.util.List;
@@ -57,14 +56,6 @@ public interface ProductPropertyValueService { @@ -57,14 +56,6 @@ public interface ProductPropertyValueService {
57 List<ProductPropertyValueDO> getPropertyValueListByPropertyId(Collection<Long> propertyIds); 56 List<ProductPropertyValueDO> getPropertyValueListByPropertyId(Collection<Long> propertyIds);
58 57
59 /** 58 /**
60 - * 根据编号数组,获得属性值列表  
61 - *  
62 - * @param ids 编号数组  
63 - * @return 属性值明细列表  
64 - */  
65 - List<ProductPropertyValueDetailRespBO> getPropertyValueDetailList(Collection<Long> ids);  
66 -  
67 - /**  
68 * 根据属性项编号,活的属性值数量 59 * 根据属性项编号,活的属性值数量
69 * 60 *
70 * @param propertyId 属性项编号数 61 * @param propertyId 属性项编号数
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java
1 package cn.iocoder.yudao.module.product.service.property; 1 package cn.iocoder.yudao.module.product.service.property;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; 4 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; 5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
7 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
8 import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert; 7 import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert;
9 -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;  
10 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; 8 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
11 import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; 9 import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper;
12 -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;  
13 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; 10 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
14 import org.springframework.context.annotation.Lazy; 11 import org.springframework.context.annotation.Lazy;
15 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
@@ -17,11 +14,9 @@ import org.springframework.validation.annotation.Validated; @@ -17,11 +14,9 @@ import org.springframework.validation.annotation.Validated;
17 14
18 import javax.annotation.Resource; 15 import javax.annotation.Resource;
19 import java.util.Collection; 16 import java.util.Collection;
20 -import java.util.Collections;  
21 import java.util.List; 17 import java.util.List;
22 18
23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
24 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;  
25 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS; 20 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS;
26 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS; 21 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS;
27 22
@@ -100,23 +95,6 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ @@ -100,23 +95,6 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ
100 } 95 }
101 96
102 @Override 97 @Override
103 - public List<ProductPropertyValueDetailRespBO> getPropertyValueDetailList(Collection<Long> ids) {  
104 - // 获得属性值列表  
105 - if (CollUtil.isEmpty(ids)) {  
106 - return Collections.emptyList();  
107 - }  
108 - List<ProductPropertyValueDO> values = productPropertyValueMapper.selectBatchIds(ids);  
109 - if (CollUtil.isEmpty(values)) {  
110 - return Collections.emptyList();  
111 - }  
112 - // 获得属性项列表  
113 - List<ProductPropertyDO> keys = productPropertyService.getPropertyList(  
114 - convertSet(values, ProductPropertyValueDO::getPropertyId));  
115 - // 组装明细  
116 - return ProductPropertyValueConvert.INSTANCE.convertList(values, keys);  
117 - }  
118 -  
119 - @Override  
120 public Integer getPropertyValueCountByPropertyId(Long propertyId) { 98 public Integer getPropertyValueCountByPropertyId(Long propertyId) {
121 return productPropertyValueMapper.selectCountByPropertyId(propertyId); 99 return productPropertyValueMapper.selectCountByPropertyId(propertyId);
122 } 100 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/bo/ProductPropertyValueDetailRespBO.java deleted
1 -package cn.iocoder.yudao.module.product.service.property.bo;  
2 -  
3 -import lombok.Data;  
4 -  
5 -/**  
6 - * 商品属性项的明细 Response BO  
7 - *  
8 - * @author 芋道源码  
9 - */  
10 -@Data  
11 -public class ProductPropertyValueDetailRespBO {  
12 -  
13 - /**  
14 - * 属性的编号  
15 - */  
16 - private Long propertyId;  
17 -  
18 - /**  
19 - * 属性的名称  
20 - */  
21 - private String propertyName;  
22 -  
23 - /**  
24 - * 属性值的编号  
25 - */  
26 - private Long valueId;  
27 -  
28 - /**  
29 - * 属性值的名称  
30 - */  
31 - private String valueName;  
32 -  
33 -}  
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -153,6 +153,9 @@ public class ProductSkuServiceImpl implements ProductSkuService { @@ -153,6 +153,9 @@ public class ProductSkuServiceImpl implements ProductSkuService {
153 153
154 @Override 154 @Override
155 public List<ProductSkuDO> getSkuListBySpuId(Collection<Long> spuIds) { 155 public List<ProductSkuDO> getSkuListBySpuId(Collection<Long> spuIds) {
  156 + if (CollUtil.isEmpty(spuIds)) {
  157 + return Collections.emptyList();
  158 + }
156 return productSkuMapper.selectListBySpuId(spuIds); 159 return productSkuMapper.selectListBySpuId(spuIds);
157 } 160 }
158 161
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
@@ -188,6 +188,9 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -188,6 +188,9 @@ public class ProductSpuServiceImpl implements ProductSpuService {
188 188
189 @Override 189 @Override
190 public List<ProductSpuDO> getSpuList(Collection<Long> ids) { 190 public List<ProductSpuDO> getSpuList(Collection<Long> ids) {
  191 + if (CollUtil.isEmpty(ids)) {
  192 + return Collections.emptyList();
  193 + }
191 return productSpuMapper.selectBatchIds(ids); 194 return productSpuMapper.selectBatchIds(ids);
192 } 195 }
193 196
yudao-module-mall/yudao-module-promotion-api/pom.xml
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 13
14 <name>${project.artifactId}</name> 14 <name>${project.artifactId}</name>
15 <description> 15 <description>
16 - market 模块 API,暴露给其它模块调用 16 + promotion 模块 API,暴露给其它模块调用
17 </description> 17 </description>
18 18
19 <dependencies> 19 <dependencies>
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.combination;  
2 -  
3 -/**  
4 - * 拼团活动 Api 接口  
5 - *  
6 - * @author HUIHUI  
7 - */  
8 -public interface CombinationActivityApi {  
9 -  
10 -}  
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
@@ -42,14 +42,6 @@ public interface CombinationRecordApi { @@ -42,14 +42,6 @@ public interface CombinationRecordApi {
42 boolean isCombinationRecordSuccess(Long userId, Long orderId); 42 boolean isCombinationRecordSuccess(Long userId, Long orderId);
43 43
44 /** 44 /**
45 - * 更新拼团状态为【失败】  
46 - *  
47 - * @param userId 用户编号  
48 - * @param orderId 订单编号  
49 - */  
50 - void updateRecordStatusToFailed(Long userId, Long orderId);  
51 -  
52 - /**  
53 * 【下单前】校验是否满足拼团活动条件 45 * 【下单前】校验是否满足拼团活动条件
54 * 46 *
55 * 如果校验失败,则抛出业务异常 47 * 如果校验失败,则抛出业务异常
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/PriceApi.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.price;  
2 -  
3 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;  
4 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;  
5 -  
6 -/**  
7 - * 价格 API 接口  
8 - *  
9 - * @author 芋道源码  
10 - */  
11 -public interface PriceApi {  
12 -  
13 - /**  
14 - * 计算商品的价格  
15 - *  
16 - * @param calculateReqDTO 价格请求  
17 - * @return 价格相应  
18 - */  
19 - PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO);  
20 -  
21 -}  
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/CouponMeetRespDTO.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.price.dto;  
2 -  
3 -import lombok.Data;  
4 -  
5 -/**  
6 - * 优惠劵的匹配信息 Response DTO  
7 - *  
8 - * why 放在 price 包下?主要获取的时候,需要涉及到较多的价格计算逻辑,放在 price 可以更好的复用逻辑  
9 - *  
10 - * @author 芋道源码  
11 - */  
12 -@Data  
13 -public class CouponMeetRespDTO {  
14 -  
15 - /**  
16 - * 优惠劵编号  
17 - */  
18 - private Long id;  
19 -  
20 - // ========== 非优惠劵的基本信息字段 ==========  
21 - /**  
22 - * 是否匹配  
23 - */  
24 - private Boolean meet;  
25 - /**  
26 - * 不匹配的提示,即 {@link #meet} = true 才有值  
27 - *  
28 - * 例如说:  
29 - * 1. 所结算商品没有符合条件的商品  
30 - * 2. 差 XXX 元可用优惠劵  
31 - * 3. 优惠劵未到使用时间  
32 - */  
33 - private String meetTip;  
34 -  
35 -}  
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateReqDTO.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.price.dto;  
2 -  
3 -import lombok.Data;  
4 -  
5 -import javax.validation.constraints.Min;  
6 -import javax.validation.constraints.NotNull;  
7 -import java.util.List;  
8 -  
9 -/**  
10 - * 价格计算 Request DTO  
11 - *  
12 - * @author 芋道源码  
13 - */  
14 -@Data  
15 -@Deprecated  
16 -public class PriceCalculateReqDTO {  
17 -  
18 - /**  
19 - * 用户编号  
20 - *  
21 - * 对应 MemberUserDO 的 id 编号  
22 - */  
23 - private Long userId;  
24 -  
25 - /**  
26 - * 优惠劵编号  
27 - */  
28 - private Long couponId;  
29 -  
30 - /**  
31 - * 收货地址编号  
32 - */  
33 - private Long addressId;  
34 -  
35 - /**  
36 - * 商品 SKU 数组  
37 - */  
38 - @NotNull(message = "商品数组不能为空")  
39 - private List<Item> items;  
40 -  
41 - /**  
42 - * 商品 SKU  
43 - */  
44 - @Data  
45 - public static class Item {  
46 -  
47 - /**  
48 - * SKU 编号  
49 - */  
50 - @NotNull(message = "商品 SKU 编号不能为空")  
51 - private Long skuId;  
52 -  
53 - /**  
54 - * SKU 数量  
55 - */  
56 - @NotNull(message = "商品 SKU 数量不能为空")  
57 - @Min(value = 0L, message = "商品 SKU 数量必须大于等于 0") // 可传递 0 数量,用于购物车未选中的情况  
58 - private Integer count;  
59 -  
60 - }  
61 -  
62 -}  
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.price.dto;  
2 -  
3 -import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;  
4 -import lombok.Data;  
5 -  
6 -import java.util.List;  
7 -  
8 -/**  
9 - * 价格计算 Response DTO  
10 - *  
11 - * 整体设计,参考 taobao 的技术文档:  
12 - * 1. <a href="https://developer.alibaba.com/docs/doc.htm?treeId=1&articleId=1029&docType=1">订单管理</a>  
13 - * 2. <a href="https://open.taobao.com/docV3.htm?docId=108471&docType=1">常用订单金额说明</a>  
14 - *  
15 - * 举个例子:<a href="https://img.alicdn.com/top/i1/LB1mALAi4HI8KJjy1zbXXaxdpXa">订单图</a>  
16 - * 输入:  
17 - * 1. 订单实付: trade.payment = 198.00;订单邮费:5 元;  
18 - * 2. 商品级优惠 圣诞价: 省 29.00 元 和 圣诞价:省 150.00 元; 订单级优惠,圣诞 2:省 5.00 元;  
19 - * 分摊:  
20 - * 1. 商品 1:原价 108 元,优惠 29 元,子订单实付 79 元,分摊主订单优惠 1.99 元;  
21 - * 2. 商品 2:原价 269 元,优惠 150 元,子订单实付 119 元,分摊主订单优惠 3.01 元;  
22 - *  
23 - * @author 芋道源码  
24 - */  
25 -@Data  
26 -@Deprecated  
27 -public class PriceCalculateRespDTO {  
28 -  
29 - /**  
30 - * 订单  
31 - */  
32 - private Order order;  
33 -  
34 - /**  
35 - * 营销活动数组  
36 - *  
37 - * 只对应 {@link Order#items} 商品匹配的活动  
38 - */  
39 - private List<Promotion> promotions;  
40 -  
41 - // TODO @芋艿:需要改造下,主要是价格字段  
42 - /**  
43 - * 订单  
44 - */  
45 - @Data  
46 - public static class Order {  
47 -  
48 - /**  
49 - * 商品原价(总),单位:分  
50 - *  
51 - * 基于 {@link OrderItem#getOriginalPrice()} 求和  
52 - *  
53 - * 对应 taobao 的 trade.total_fee 字段  
54 - */  
55 - private Integer totalPrice;  
56 - /**  
57 - * 订单优惠(总),单位:分  
58 - *  
59 - * 订单级优惠:对主订单的优惠,常见如:订单满 200 元减 10 元;订单满 80 包邮。  
60 - *  
61 - * 对应 taobao 的 order.discount_fee 字段  
62 - */  
63 - private Integer discountPrice;  
64 - /**  
65 - * 优惠劵减免金额(总),单位:分  
66 - *  
67 - * 对应 taobao 的 trade.coupon_fee 字段  
68 - */  
69 - private Integer couponPrice;  
70 - /**  
71 - * 积分减免金额(总),单位:分  
72 - *  
73 - * 对应 taobao 的 trade.point_fee 字段  
74 - */  
75 - private Integer pointPrice;  
76 - /**  
77 - * 运费金额,单位:分  
78 - */  
79 - private Integer deliveryPrice;  
80 - /**  
81 - * 最终购买金额(总),单位:分  
82 - *  
83 - * = {@link OrderItem#getPayPrice()} 求和  
84 - * - {@link #couponPrice}  
85 - * - {@link #pointPrice}  
86 - * + {@link #deliveryPrice}  
87 - * - {@link #discountPrice}  
88 - */  
89 - private Integer payPrice;  
90 - /**  
91 - * 商品 SKU 数组  
92 - */  
93 - private List<OrderItem> items;  
94 -  
95 - // ========== 营销基本信息 ==========  
96 - /**  
97 - * 优惠劵编号  
98 - */  
99 - private Long couponId;  
100 -  
101 - }  
102 -  
103 - /**  
104 - * 订单商品 SKU  
105 - */  
106 - @Data  
107 - public static class OrderItem {  
108 -  
109 - /**  
110 - * SPU 编号  
111 - */  
112 - private Long spuId;  
113 - /**  
114 - * SKU 编号  
115 - */  
116 - private Long skuId;  
117 - /**  
118 - * 购买数量  
119 - */  
120 - private Integer count;  
121 -  
122 - /**  
123 - * 商品原价(总),单位:分  
124 - *  
125 - * = {@link #originalUnitPrice} * {@link #getCount()}  
126 - */  
127 - private Integer originalPrice;  
128 - /**  
129 - * 商品原价(单),单位:分  
130 - *  
131 - * 对应 ProductSkuDO 的 price 字段  
132 - * 对应 taobao 的 order.price 字段  
133 - */  
134 - private Integer originalUnitPrice;  
135 - /**  
136 - * 商品优惠(总),单位:分  
137 - *  
138 - * 商品级优惠:对单个商品的,常见如:商品原价的 8 折;商品原价的减 50 元  
139 - *  
140 - * 对应 taobao 的 order.discount_fee 字段  
141 - */  
142 - private Integer discountPrice;  
143 - /**  
144 - * 子订单实付金额,不算主订单分摊金额,单位:分  
145 - *  
146 - * = {@link #originalPrice}  
147 - * - {@link #discountPrice}  
148 - *  
149 - * 对应 taobao 的 order.payment 字段  
150 - */  
151 - private Integer payPrice;  
152 -  
153 - /**  
154 - * 子订单分摊金额(总),单位:分  
155 - * 需要分摊 {@link Order#discountPrice}、{@link Order#couponPrice}、{@link Order#pointPrice}  
156 - *  
157 - * 对应 taobao 的 order.part_mjz_discount 字段  
158 - * 淘宝说明:子订单分摊优惠基础逻辑:一般正常优惠券和满减优惠按照子订单的金额进行分摊,特殊情况如果优惠券是指定商品使用的,只会分摊到对应商品子订单上不分摊。  
159 - */  
160 - private Integer orderPartPrice;  
161 - /**  
162 - * 分摊后子订单实付金额(总),单位:分  
163 - *  
164 - * = {@link #payPrice}  
165 - * - {@link #orderPartPrice}  
166 - *  
167 - * 对应 taobao 的 divide_order_fee 字段  
168 - */  
169 - private Integer orderDividePrice;  
170 -  
171 - }  
172 -  
173 - /**  
174 - * 营销明细  
175 - */  
176 - @Data  
177 - @Deprecated  
178 - public static class Promotion {  
179 -  
180 - /**  
181 - * 营销编号  
182 - *  
183 - * 例如说:营销活动的编号、优惠劵的编号  
184 - */  
185 - private Long id;  
186 - /**  
187 - * 营销名字  
188 - */  
189 - private String name;  
190 - /**  
191 - * 营销类型  
192 - *  
193 - * 枚举 {@link PromotionTypeEnum}  
194 - */  
195 - private Integer type;  
196 - /**  
197 - * 营销级别  
198 - *  
199 - * 枚举 @link PromotionLevelEnum} TODO PromotionLevelEnum 没有这个枚举类  
200 - */  
201 - private Integer level;  
202 - /**  
203 - * 计算时的原价(总),单位:分  
204 - */  
205 - private Integer totalPrice;  
206 - /**  
207 - * 计算时的优惠(总),单位:分  
208 - */  
209 - private Integer discountPrice;  
210 - /**  
211 - * 匹配的商品 SKU 数组  
212 - */  
213 - private List<PromotionItem> items;  
214 -  
215 - // ========== 匹配情况 ==========  
216 -  
217 - /**  
218 - * 是否满足优惠条件  
219 - */  
220 - private Boolean match;  
221 - /**  
222 - * 满足条件的提示  
223 - *  
224 - * 如果 {@link #match} = true 满足,则提示“圣诞价:省 150.00 元”  
225 - * 如果 {@link #match} = false 不满足,则提示“购满 85 元,可减 40 元”  
226 - */  
227 - private String description;  
228 -  
229 - }  
230 -  
231 - /**  
232 - * 营销匹配的商品 SKU  
233 - */  
234 - @Data  
235 - public static class PromotionItem {  
236 -  
237 - /**  
238 - * 商品 SKU 编号  
239 - */  
240 - private Long skuId;  
241 - /**  
242 - * 计算时的原价(总),单位:分  
243 - */  
244 - private Integer originalPrice;  
245 - /**  
246 - * 计算时的优惠(总),单位:分  
247 - */  
248 - private Integer discountPrice;  
249 -  
250 - }  
251 -  
252 -}  
yudao-module-mall/yudao-module-promotion-biz/pom.xml
@@ -14,8 +14,8 @@ @@ -14,8 +14,8 @@
14 <name>${project.artifactId}</name> 14 <name>${project.artifactId}</name>
15 15
16 <description> 16 <description>
17 - market模块,主要实现营销相关功能  
18 - 例如:营销活动、banner广告、优惠券、优惠码等功能。 17 + promotion 模块,主要实现营销相关功能
  18 + 例如:营销活动、banner 广告、优惠券、优惠码等功能。
19 </description> 19 </description>
20 20
21 <dependencies> 21 <dependencies>
@@ -49,10 +49,6 @@ @@ -49,10 +49,6 @@
49 <groupId>cn.iocoder.boot</groupId> 49 <groupId>cn.iocoder.boot</groupId>
50 <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> 50 <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
51 </dependency> 51 </dependency>
52 - <dependency>  
53 - <groupId>cn.iocoder.boot</groupId>  
54 - <artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>  
55 - </dependency>  
56 52
57 <!-- Web 相关 --> 53 <!-- Web 相关 -->
58 <dependency> 54 <dependency>
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.bargain; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.bargain;
2 2
3 import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; 3 import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService;
4 import org.springframework.stereotype.Service; 4 import org.springframework.stereotype.Service;
  5 +import org.springframework.validation.annotation.Validated;
5 6
6 import javax.annotation.Resource; 7 import javax.annotation.Resource;
7 8
@@ -11,6 +12,7 @@ import javax.annotation.Resource; @@ -11,6 +12,7 @@ import javax.annotation.Resource;
11 * @author HUIHUI 12 * @author HUIHUI
12 */ 13 */
13 @Service 14 @Service
  15 +@Validated
14 public class BargainActivityApiImpl implements BargainActivityApi { 16 public class BargainActivityApiImpl implements BargainActivityApi {
15 17
16 @Resource 18 @Resource
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApiImpl.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.api.bargain; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.api.bargain;
3 import cn.iocoder.yudao.module.promotion.api.bargain.dto.BargainValidateJoinRespDTO; 3 import cn.iocoder.yudao.module.promotion.api.bargain.dto.BargainValidateJoinRespDTO;
4 import cn.iocoder.yudao.module.promotion.service.bargain.BargainRecordService; 4 import cn.iocoder.yudao.module.promotion.service.bargain.BargainRecordService;
5 import org.springframework.stereotype.Service; 5 import org.springframework.stereotype.Service;
  6 +import org.springframework.validation.annotation.Validated;
6 7
7 import javax.annotation.Resource; 8 import javax.annotation.Resource;
8 9
@@ -12,6 +13,7 @@ import javax.annotation.Resource; @@ -12,6 +13,7 @@ import javax.annotation.Resource;
12 * @author HUIHUI 13 * @author HUIHUI
13 */ 14 */
14 @Service 15 @Service
  16 +@Validated
15 public class BargainRecordApiImpl implements BargainRecordApi { 17 public class BargainRecordApiImpl implements BargainRecordApi {
16 18
17 @Resource 19 @Resource
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.combination;  
2 -  
3 -import org.springframework.stereotype.Service;  
4 -  
5 -/**  
6 - * 拼团活动 Api 接口实现类  
7 - *  
8 - * @author HUIHUI  
9 - */  
10 -@Service  
11 -public class CombinationActivityApiImpl implements CombinationActivityApi {  
12 -  
13 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationR @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationR
8 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; 8 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
9 import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; 9 import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService;
10 import org.springframework.stereotype.Service; 10 import org.springframework.stereotype.Service;
  11 +import org.springframework.validation.annotation.Validated;
11 12
12 import javax.annotation.Resource; 13 import javax.annotation.Resource;
13 14
@@ -20,6 +21,7 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINA @@ -20,6 +21,7 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINA
20 * @author HUIHUI 21 * @author HUIHUI
21 */ 22 */
22 @Service 23 @Service
  24 +@Validated
23 public class CombinationRecordApiImpl implements CombinationRecordApi { 25 public class CombinationRecordApiImpl implements CombinationRecordApi {
24 26
25 @Resource 27 @Resource
@@ -45,11 +47,6 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { @@ -45,11 +47,6 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
45 } 47 }
46 48
47 @Override 49 @Override
48 - public void updateRecordStatusToFailed(Long userId, Long orderId) {  
49 - recordService.updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordStatusEnum.FAILED.getStatus(), userId, orderId);  
50 - }  
51 -  
52 - @Override  
53 public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count) { 50 public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count) {
54 return recordService.validateJoinCombination(userId, activityId, headId, skuId, count); 51 return recordService.validateJoinCombination(userId, activityId, headId, skuId, count);
55 } 52 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert;
8 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
9 import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; 9 import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
10 import org.springframework.stereotype.Service; 10 import org.springframework.stereotype.Service;
  11 +import org.springframework.validation.annotation.Validated;
11 12
12 import javax.annotation.Resource; 13 import javax.annotation.Resource;
13 14
@@ -17,6 +18,7 @@ import javax.annotation.Resource; @@ -17,6 +18,7 @@ import javax.annotation.Resource;
17 * @author 芋道源码 18 * @author 芋道源码
18 */ 19 */
19 @Service 20 @Service
  21 +@Validated
20 public class CouponApiImpl implements CouponApi { 22 public class CouponApiImpl implements CouponApi {
21 23
22 @Resource 24 @Resource
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java
@@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO @@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO
4 import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert; 4 import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert;
5 import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; 5 import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService;
6 import org.springframework.stereotype.Service; 6 import org.springframework.stereotype.Service;
  7 +import org.springframework.validation.annotation.Validated;
7 8
8 import javax.annotation.Resource; 9 import javax.annotation.Resource;
9 import java.util.Collection; 10 import java.util.Collection;
@@ -15,6 +16,7 @@ import java.util.List; @@ -15,6 +16,7 @@ import java.util.List;
15 * @author 芋道源码 16 * @author 芋道源码
16 */ 17 */
17 @Service 18 @Service
  19 +@Validated
18 public class DiscountActivityApiImpl implements DiscountActivityApi { 20 public class DiscountActivityApiImpl implements DiscountActivityApi {
19 21
20 @Resource 22 @Resource
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/price/PriceApiImpl.java deleted
1 -package cn.iocoder.yudao.module.promotion.api.price;  
2 -  
3 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;  
4 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;  
5 -import cn.iocoder.yudao.module.promotion.service.price.PriceService;  
6 -import org.springframework.stereotype.Service;  
7 -  
8 -import javax.annotation.Resource;  
9 -  
10 -/**  
11 - * 价格 API 实现类  
12 - *  
13 - * @author 芋道源码  
14 - */  
15 -@Service  
16 -public class PriceApiImpl implements PriceApi {  
17 -  
18 - @Resource  
19 - private PriceService priceService;  
20 -  
21 - @Override  
22 - public PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO) {  
23 - //return priceService.calculatePrice(calculateReqDTO); TODO 没有 calculatePrice 这个方法  
24 -  
25 - return null;  
26 - }  
27 -  
28 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.api.reward; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.api.reward;
3 import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; 3 import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
4 import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; 4 import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;
5 import org.springframework.stereotype.Service; 5 import org.springframework.stereotype.Service;
  6 +import org.springframework.validation.annotation.Validated;
6 7
7 import javax.annotation.Resource; 8 import javax.annotation.Resource;
8 import java.util.Collection; 9 import java.util.Collection;
@@ -14,6 +15,7 @@ import java.util.List; @@ -14,6 +15,7 @@ import java.util.List;
14 * @author 芋道源码 15 * @author 芋道源码
15 */ 16 */
16 @Service 17 @Service
  18 +@Validated
17 public class RewardActivityApiImpl implements RewardActivityApi { 19 public class RewardActivityApiImpl implements RewardActivityApi {
18 20
19 @Resource 21 @Resource
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.api.seckill; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.api.seckill;
3 import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinRespDTO; 3 import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinRespDTO;
4 import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; 4 import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
5 import org.springframework.stereotype.Service; 5 import org.springframework.stereotype.Service;
  6 +import org.springframework.validation.annotation.Validated;
6 7
7 import javax.annotation.Resource; 8 import javax.annotation.Resource;
8 9
@@ -12,6 +13,7 @@ import javax.annotation.Resource; @@ -12,6 +13,7 @@ import javax.annotation.Resource;
12 * @author HUIHUI 13 * @author HUIHUI
13 */ 14 */
14 @Service 15 @Service
  16 +@Validated
15 public class SeckillActivityApiImpl implements SeckillActivityApi { 17 public class SeckillActivityApiImpl implements SeckillActivityApi {
16 18
17 @Resource 19 @Resource
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/banner/vo/BannerRespVO.java
@@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; @@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 4 import lombok.Data;
5 import lombok.ToString; 5 import lombok.ToString;
6 6
  7 +import java.time.LocalDateTime;
  8 +
7 @Schema(description = "管理后台 - Banner Response VO") 9 @Schema(description = "管理后台 - Banner Response VO")
8 @Data 10 @Data
9 @ToString(callSuper = true) 11 @ToString(callSuper = true)
@@ -12,4 +14,7 @@ public class BannerRespVO extends BannerBaseVO { @@ -12,4 +14,7 @@ public class BannerRespVO extends BannerBaseVO {
12 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) 14 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED)
13 private Long id; 15 private Long id;
14 16
  17 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2022-07-01 23:59:59")
  18 + private LocalDateTime createTime;
  19 +
15 } 20 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java
@@ -96,13 +96,13 @@ public class AppCouponTemplateController { @@ -96,13 +96,13 @@ public class AppCouponTemplateController {
96 */ 96 */
97 private Long getProductScopeValue(Integer productScope, Long spuId) { 97 private Long getProductScopeValue(Integer productScope, Long spuId) {
98 // 通用券:没有商品范围 98 // 通用券:没有商品范围
99 - if (productScope == null || ObjectUtils.equalsAny(productScope, PromotionProductScopeEnum.ALL.getScope(), null)) { 99 + if (ObjectUtils.equalsAny(productScope, PromotionProductScopeEnum.ALL.getScope(), null)) {
100 return null; 100 return null;
101 } 101 }
102 // 品类券:查询商品的品类编号 102 // 品类券:查询商品的品类编号
103 if (Objects.equals(productScope, PromotionProductScopeEnum.CATEGORY.getScope()) && spuId != null) { 103 if (Objects.equals(productScope, PromotionProductScopeEnum.CATEGORY.getScope()) && spuId != null) {
104 - return Optional.ofNullable(productSpuApi.getSpu(spuId))  
105 - .map(ProductSpuRespDTO::getCategoryId).orElse(null); 104 + ProductSpuRespDTO spu = productSpuApi.getSpu(spuId);
  105 + return spu != null ? spu.getCategoryId() : null;
106 } 106 }
107 // 商品卷:直接返回 107 // 商品卷:直接返回
108 return spuId; 108 return spuId;
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/price/PriceConvert.java deleted
1 -package cn.iocoder.yudao.module.promotion.convert.price;  
2 -  
3 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
4 -import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO;  
5 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;  
6 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;  
7 -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;  
8 -import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;  
9 -import org.mapstruct.Mapper;  
10 -import org.mapstruct.factory.Mappers;  
11 -  
12 -import java.util.ArrayList;  
13 -import java.util.List;  
14 -import java.util.Map;  
15 -  
16 -@Mapper  
17 -public interface PriceConvert {  
18 -  
19 - PriceConvert INSTANCE = Mappers.getMapper(PriceConvert.class);  
20 -  
21 - default PriceCalculateRespDTO convert(PriceCalculateReqDTO calculateReqDTO, List<ProductSkuRespDTO> skuList) {  
22 - // 创建 PriceCalculateRespDTO 对象  
23 - PriceCalculateRespDTO priceCalculate = new PriceCalculateRespDTO();  
24 - // 创建它的 Order 属性  
25 - PriceCalculateRespDTO.Order order = new PriceCalculateRespDTO.Order().setTotalPrice(0).setDiscountPrice(0)  
26 - .setCouponPrice(0).setPointPrice(0).setDeliveryPrice(0).setPayPrice(0)  
27 - .setItems(new ArrayList<>()).setCouponId(calculateReqDTO.getCouponId());  
28 - priceCalculate.setOrder(order).setPromotions(new ArrayList<>());  
29 - // 创建它的 OrderItem 属性  
30 - Map<Long, Integer> skuIdCountMap = CollectionUtils.convertMap(calculateReqDTO.getItems(),  
31 - PriceCalculateReqDTO.Item::getSkuId, PriceCalculateReqDTO.Item::getCount);  
32 - skuList.forEach(sku -> {  
33 - Integer count = skuIdCountMap.get(sku.getId());  
34 - PriceCalculateRespDTO.OrderItem orderItem = new PriceCalculateRespDTO.OrderItem()  
35 - .setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count)  
36 - .setOriginalUnitPrice(sku.getPrice()).setOriginalPrice(sku.getPrice() * count)  
37 - .setDiscountPrice(0).setOrderPartPrice(0);  
38 - orderItem.setPayPrice(orderItem.getOriginalPrice()).setOrderDividePrice(orderItem.getOriginalPrice());  
39 - priceCalculate.getOrder().getItems().add(orderItem);  
40 - // 补充价格信息到 Order 中  
41 - order.setTotalPrice(order.getTotalPrice() + orderItem.getOriginalPrice())  
42 - .setPayPrice(order.getTotalPrice());  
43 - });  
44 - return priceCalculate;  
45 - }  
46 -  
47 - CouponMeetRespDTO convert(CouponDO coupon);  
48 -  
49 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/coupon/UserCreateConsumer.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/coupon/CouponTakeByRegisterConsumer.java
1 package cn.iocoder.yudao.module.promotion.mq.consumer.coupon; 1 package cn.iocoder.yudao.module.promotion.mq.consumer.coupon;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;  
4 -import cn.iocoder.yudao.module.promotion.mq.message.coupon.UserCreateMessage; 3 +import cn.iocoder.yudao.module.member.message.user.MemberUserCreateMessage;
5 import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; 4 import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
6 import lombok.extern.slf4j.Slf4j; 5 import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.context.event.EventListener;
  7 +import org.springframework.scheduling.annotation.Async;
7 import org.springframework.stereotype.Component; 8 import org.springframework.stereotype.Component;
8 9
9 import javax.annotation.Resource; 10 import javax.annotation.Resource;
10 11
11 /** 12 /**
12 - * 针对 {@link UserCreateMessage} 的消费者 13 + * 用户注册时,发送优惠劵的消费者,基 {@link MemberUserCreateMessage} 消息
13 * 14 *
14 * @author owen 15 * @author owen
15 */ 16 */
16 @Component 17 @Component
17 @Slf4j 18 @Slf4j
18 -public class UserCreateConsumer extends AbstractStreamMessageListener<UserCreateMessage> { 19 +public class CouponTakeByRegisterConsumer {
19 20
20 @Resource 21 @Resource
21 private CouponService couponService; 22 private CouponService couponService;
22 23
23 - @Override  
24 - public void onMessage(UserCreateMessage message) { 24 + @EventListener
  25 + @Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步
  26 + public void onMessage(MemberUserCreateMessage message) {
25 log.info("[onMessage][消息内容({})]", message); 27 log.info("[onMessage][消息内容({})]", message);
26 couponService.takeCouponByRegister(message.getUserId()); 28 couponService.takeCouponByRegister(message.getUserId());
27 } 29 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/package-info.java 0 → 100644
  1 +/**
  2 + * 消息队列的消费者
  3 + */
  4 +package cn.iocoder.yudao.module.promotion.mq.consumer;
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/message/package-info.java 0 → 100644
  1 +/**
  2 + * 消息队列的消息
  3 + */
  4 +package cn.iocoder.yudao.module.promotion.mq.message;
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/producer/package-info.java 0 → 100644
  1 +/**
  2 + * 消息队列的生产者
  3 + */
  4 +package cn.iocoder.yudao.module.promotion.mq.producer;
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
@@ -108,8 +108,8 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -108,8 +108,8 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
108 } 108 }
109 109
110 // 2. 校验商品 sku 都存在 110 // 2. 校验商品 sku 都存在
111 - Map<Long, ProductSkuRespDTO> skuMap = convertMap(productSkuApi.getSkuListBySpuId(singletonList(spuId)),  
112 - ProductSkuRespDTO::getId); 111 + List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(singletonList(spuId));
  112 + Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId);
113 products.forEach(product -> { 113 products.forEach(product -> {
114 if (!skuMap.containsKey(product.getSkuId())) { 114 if (!skuMap.containsKey(product.getSkuId())) {
115 throw exception(SKU_NOT_EXISTS); 115 throw exception(SKU_NOT_EXISTS);
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
@@ -22,15 +22,6 @@ import java.util.Map; @@ -22,15 +22,6 @@ import java.util.Map;
22 public interface CombinationRecordService { 22 public interface CombinationRecordService {
23 23
24 /** 24 /**
25 - * 更新拼团状态  
26 - *  
27 - * @param status 状态  
28 - * @param userId 用户编号  
29 - * @param orderId 订单编号  
30 - */  
31 - void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId);  
32 -  
33 - /**  
34 * 【下单前】校验是否满足拼团活动条件 25 * 【下单前】校验是否满足拼团活动条件
35 * 26 *
36 * 如果校验失败,则抛出业务异常 27 * 如果校验失败,则抛出业务异常
@@ -63,15 +54,6 @@ public interface CombinationRecordService { @@ -63,15 +54,6 @@ public interface CombinationRecordService {
63 CombinationRecordDO getCombinationRecord(Long userId, Long orderId); 54 CombinationRecordDO getCombinationRecord(Long userId, Long orderId);
64 55
65 /** 56 /**
66 - * 获取拼团记录  
67 - *  
68 - * @param userId 用户 id  
69 - * @param activityId 活动 id  
70 - * @return 拼团记录列表  
71 - */  
72 - List<CombinationRecordDO> getCombinationRecordListByUserIdAndActivityId(Long userId, Long activityId);  
73 -  
74 - /**  
75 * 【下单前】校验是否满足拼团活动条件 57 * 【下单前】校验是否满足拼团活动条件
76 * 58 *
77 * 如果校验失败,则抛出业务异常 59 * 如果校验失败,则抛出业务异常
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
@@ -24,6 +24,7 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecord @@ -24,6 +24,7 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecord
24 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; 24 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
25 import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; 25 import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
26 import lombok.extern.slf4j.Slf4j; 26 import lombok.extern.slf4j.Slf4j;
  27 +import org.springframework.context.annotation.Lazy;
27 import org.springframework.stereotype.Service; 28 import org.springframework.stereotype.Service;
28 import org.springframework.transaction.annotation.Transactional; 29 import org.springframework.transaction.annotation.Transactional;
29 import org.springframework.validation.annotation.Validated; 30 import org.springframework.validation.annotation.Validated;
@@ -64,27 +65,9 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -64,27 +65,9 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
64 private ProductSkuApi productSkuApi; 65 private ProductSkuApi productSkuApi;
65 66
66 @Resource 67 @Resource
  68 + @Lazy
67 private TradeOrderApi tradeOrderApi; 69 private TradeOrderApi tradeOrderApi;
68 70
69 - @Override  
70 - @Transactional(rollbackFor = Exception.class)  
71 - public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) {  
72 - // 校验拼团是否存在  
73 - CombinationRecordDO record = validateCombinationRecord(userId, orderId);  
74 -  
75 - // 更新状态  
76 - combinationRecordMapper.updateById(new CombinationRecordDO().setId(record.getId()).setStatus(status));  
77 - }  
78 -  
79 - private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) {  
80 - // 校验拼团是否存在  
81 - CombinationRecordDO recordDO = combinationRecordMapper.selectByUserIdAndOrderId(userId, orderId);  
82 - if (recordDO == null) {  
83 - throw exception(COMBINATION_RECORD_NOT_EXISTS);  
84 - }  
85 - return recordDO;  
86 - }  
87 -  
88 // TODO @芋艿:在详细预览下; 71 // TODO @芋艿:在详细预览下;
89 @Override 72 @Override
90 public KeyValue<CombinationActivityDO, CombinationProductDO> validateCombinationRecord( 73 public KeyValue<CombinationActivityDO, CombinationProductDO> validateCombinationRecord(
@@ -230,11 +213,6 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -230,11 +213,6 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
230 } 213 }
231 214
232 @Override 215 @Override
233 - public List<CombinationRecordDO> getCombinationRecordListByUserIdAndActivityId(Long userId, Long activityId) {  
234 - return combinationRecordMapper.selectListByUserIdAndActivityId(userId, activityId);  
235 - }  
236 -  
237 - @Override  
238 public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, 216 public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId,
239 Long skuId, Integer count) { 217 Long skuId, Integer count) {
240 KeyValue<CombinationActivityDO, CombinationProductDO> keyValue = validateCombinationRecord(userId, activityId, 218 KeyValue<CombinationActivityDO, CombinationProductDO> keyValue = validateCombinationRecord(userId, activityId,
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
@@ -7,7 +7,6 @@ import cn.hutool.core.util.ObjectUtil; @@ -7,7 +7,6 @@ import cn.hutool.core.util.ObjectUtil;
7 import cn.hutool.core.util.StrUtil; 7 import cn.hutool.core.util.StrUtil;
8 import cn.hutool.extra.spring.SpringUtil; 8 import cn.hutool.extra.spring.SpringUtil;
9 import cn.iocoder.yudao.framework.common.pojo.PageResult; 9 import cn.iocoder.yudao.framework.common.pojo.PageResult;
10 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
11 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; 10 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
12 import cn.iocoder.yudao.module.member.api.user.MemberUserApi; 11 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
13 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 12 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
@@ -80,12 +79,11 @@ public class CouponServiceImpl implements CouponService { @@ -80,12 +79,11 @@ public class CouponServiceImpl implements CouponService {
80 public PageResult<CouponDO> getCouponPage(CouponPageReqVO pageReqVO) { 79 public PageResult<CouponDO> getCouponPage(CouponPageReqVO pageReqVO) {
81 // 获得用户编号 80 // 获得用户编号
82 if (StrUtil.isNotEmpty(pageReqVO.getNickname())) { 81 if (StrUtil.isNotEmpty(pageReqVO.getNickname())) {
83 - Set<Long> userIds = CollectionUtils.convertSet(memberUserApi.getUserListByNickname(pageReqVO.getNickname()),  
84 - MemberUserRespDTO::getId);  
85 - if (CollUtil.isEmpty(userIds)) { 82 + List<MemberUserRespDTO> users = memberUserApi.getUserListByNickname(pageReqVO.getNickname());
  83 + if (CollUtil.isEmpty(users)) {
86 return PageResult.empty(); 84 return PageResult.empty();
87 } 85 }
88 - pageReqVO.setUserIds(userIds); 86 + pageReqVO.setUserIds(convertSet(users, MemberUserRespDTO::getId));
89 } 87 }
90 // 分页查询 88 // 分页查询
91 return couponMapper.selectPage(pageReqVO); 89 return couponMapper.selectPage(pageReqVO);
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceService.java deleted
1 -package cn.iocoder.yudao.module.promotion.service.price;  
2 -  
3 -import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO;  
4 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;  
5 -  
6 -import java.util.List;  
7 -  
8 -/**  
9 - * 价格计算 Service 接口  
10 - *  
11 - * @author 芋道源码  
12 - */  
13 -public interface PriceService {  
14 -  
15 - /**  
16 - * 获得优惠劵的匹配信息列表  
17 - *  
18 - * @param calculateReqDTO 价格请求  
19 - * @return 价格响应  
20 - */  
21 - List<CouponMeetRespDTO> getMeetCouponList(PriceCalculateReqDTO calculateReqDTO);  
22 -  
23 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java deleted
1 -package cn.iocoder.yudao.module.promotion.service.price;  
2 -  
3 -import cn.hutool.core.collection.CollUtil;  
4 -import cn.iocoder.yudao.framework.common.exception.ServiceException;  
5 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
6 -import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO;  
7 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;  
8 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;  
9 -import cn.iocoder.yudao.module.promotion.convert.price.PriceConvert;  
10 -import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;  
11 -import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;  
12 -import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;  
13 -import lombok.extern.slf4j.Slf4j;  
14 -import org.springframework.stereotype.Service;  
15 -import org.springframework.validation.annotation.Validated;  
16 -  
17 -import javax.annotation.Resource;  
18 -import java.util.Collections;  
19 -import java.util.List;  
20 -  
21 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;  
22 -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_VALID_TIME_NOT_NOW;  
23 -  
24 -/**  
25 - * 价格计算 Service 实现类  
26 - *  
27 - * 优惠计算顺序:min(限时折扣, 会员折扣) > 满减送 > 优惠券。  
28 - * 参考文档:  
29 - * 1. <a href="https://help.youzan.com/displaylist/detail_4_4-1-60384">有赞文档:限时折扣、满减送、优惠券哪个优先计算?</a>  
30 - *  
31 - * TODO 芋艿:进一步完善  
32 - * 1. 限时折扣:指定金额、减免金额、折扣  
33 - * 2. 满减送:循环、折扣  
34 - * 3. 优惠劵:待定  
35 - *  
36 - * @author 芋道源码  
37 - */  
38 -@Service  
39 -@Validated  
40 -@Slf4j  
41 -public class PriceServiceImpl implements PriceService {  
42 -  
43 - @Resource  
44 - private CouponService couponService;  
45 -  
46 - @Override  
47 - public List<CouponMeetRespDTO> getMeetCouponList(PriceCalculateReqDTO calculateReqDTO) {  
48 - // 先计算一轮价格  
49 -// PriceCalculateRespDTO priceCalculate = calculatePrice(calculateReqDTO);  
50 - PriceCalculateRespDTO priceCalculate = null;  
51 -  
52 - // 获得用户的待使用优惠劵  
53 - List<CouponDO> couponList = couponService.getCouponList(calculateReqDTO.getUserId(), CouponStatusEnum.UNUSED.getStatus());  
54 - if (CollUtil.isEmpty(couponList)) {  
55 - return Collections.emptyList();  
56 - }  
57 -  
58 - // 获得优惠劵的匹配信息  
59 - return CollectionUtils.convertList(couponList, coupon -> {  
60 - CouponMeetRespDTO couponMeetRespDTO = PriceConvert.INSTANCE.convert(coupon);  
61 - try {  
62 - // 校验优惠劵  
63 - couponService.validCoupon(coupon);  
64 -  
65 - // 获得匹配的商品 SKU 数组  
66 - // TODO 芋艿:后续处理  
67 -// List<PriceCalculateRespDTO.OrderItem> orderItems = getMatchCouponOrderItems(priceCalculate, coupon);  
68 - List<PriceCalculateRespDTO.OrderItem> orderItems = null;  
69 - if (CollUtil.isEmpty(orderItems)) {  
70 - return couponMeetRespDTO.setMeet(false).setMeetTip("所结算商品没有符合条件的商品");  
71 - }  
72 -  
73 - // 计算是否满足优惠劵的使用金额  
74 - Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum);  
75 - assert originPrice != null;  
76 - if (originPrice < coupon.getUsePrice()) {  
77 - return couponMeetRespDTO.setMeet(false)  
78 -// .setMeetTip(String.format("差 %s 元可用优惠劵", formatPrice(coupon.getUsePrice() - originPrice)));  
79 - .setMeetTip("所结算的商品中未满足使用的金额");  
80 - }  
81 - } catch (ServiceException serviceException) {  
82 - couponMeetRespDTO.setMeet(false);  
83 - if (serviceException.getCode().equals(COUPON_VALID_TIME_NOT_NOW.getCode())) {  
84 - couponMeetRespDTO.setMeetTip("优惠劵未到使用时间");  
85 - } else {  
86 - log.error("[getMeetCouponList][calculateReqDTO({}) 获得优惠劵匹配信息异常]", calculateReqDTO, serviceException);  
87 - couponMeetRespDTO.setMeetTip("优惠劵不满足使用条件");  
88 - }  
89 - return couponMeetRespDTO;  
90 - }  
91 - // 满足  
92 - return couponMeetRespDTO.setMeet(true);  
93 - });  
94 - }  
95 -  
96 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
@@ -123,8 +123,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -123,8 +123,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
123 } 123 }
124 124
125 // 2. 校验商品 sku 都存在 125 // 2. 校验商品 sku 都存在
126 - Map<Long, ProductSkuRespDTO> skuMap = convertMap(productSkuApi.getSkuListBySpuId(singletonList(spuId)),  
127 - ProductSkuRespDTO::getId); 126 + List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(singletonList(spuId));
  127 + Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId);
128 products.forEach(product -> { 128 products.forEach(product -> {
129 if (!skuMap.containsKey(product.getSkuId())) { 129 if (!skuMap.containsKey(product.getSkuId())) {
130 throw exception(SKU_NOT_EXISTS); 130 throw exception(SKU_NOT_EXISTS);
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImplTest.java
@@ -138,7 +138,7 @@ public class DiscountActivityServiceImplTest extends BaseDbUnitTest { @@ -138,7 +138,7 @@ public class DiscountActivityServiceImplTest extends BaseDbUnitTest {
138 Long id = dbDiscountActivity.getId(); 138 Long id = dbDiscountActivity.getId();
139 139
140 // 调用 140 // 调用
141 - discountActivityService.closeRewardActivity(id); 141 + discountActivityService.closeDiscountActivity(id);
142 // 校验状态 142 // 校验状态
143 DiscountActivityDO discountActivity = discountActivityMapper.selectById(id); 143 DiscountActivityDO discountActivity = discountActivityMapper.selectById(id);
144 assertEquals(discountActivity.getStatus(), PromotionActivityStatusEnum.CLOSE.getStatus()); 144 assertEquals(discountActivity.getStatus(), PromotionActivityStatusEnum.CLOSE.getStatus());
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java deleted
1 -package cn.iocoder.yudao.module.promotion.service.price;  
2 -  
3 -import cn.iocoder.yudao.framework.common.exception.ServiceException;  
4 -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;  
5 -import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;  
6 -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;  
7 -import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO;  
8 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;  
9 -import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;  
10 -import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;  
11 -import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;  
12 -import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;  
13 -import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;  
14 -import org.junit.jupiter.api.Test;  
15 -import org.mockito.InjectMocks;  
16 -import org.mockito.Mock;  
17 -  
18 -import java.util.List;  
19 -  
20 -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;  
21 -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;  
22 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;  
23 -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_VALID_TIME_NOT_NOW;  
24 -import static java.util.Arrays.asList;  
25 -import static java.util.Collections.singletonList;  
26 -import static org.junit.jupiter.api.Assertions.*;  
27 -import static org.mockito.ArgumentMatchers.eq;  
28 -import static org.mockito.Mockito.doThrow;  
29 -import static org.mockito.Mockito.when;  
30 -  
31 -/**  
32 - * {@link PriceServiceImpl} 的单元测试  
33 - *  
34 - * @author 芋道源码  
35 - */  
36 -public class PriceServiceTest extends BaseMockitoUnitTest {  
37 -  
38 - @InjectMocks  
39 - private PriceServiceImpl priceService;  
40 -  
41 - @Mock  
42 - private RewardActivityService rewardActivityService;  
43 - @Mock  
44 - private CouponService couponService;  
45 - @Mock  
46 - private ProductSkuApi productSkuApi;  
47 -  
48 - /**  
49 - * 测试满减送活动,不匹配的情况  
50 - */  
51 - @Test  
52 - public void testCalculatePrice_rewardActivityNotMeet() {  
53 -  
54 - }  
55 -  
56 - @Test  
57 - public void testGetMeetCouponList() {  
58 - // 准备参数  
59 - PriceCalculateReqDTO calculateReqDTO = new PriceCalculateReqDTO().setUserId(1024L)  
60 - .setItems(singletonList(new PriceCalculateReqDTO.Item().setSkuId(10L).setCount(2)));  
61 - // mock 方法(商品 SKU 信息)  
62 - ProductSkuRespDTO productSku = randomPojo(ProductSkuRespDTO.class, o -> o.setId(10L).setPrice(100));  
63 - when(productSkuApi.getSkuList(eq(asSet(10L)))).thenReturn(singletonList(productSku));  
64 - // mock 方法(情况一:优惠劵未到使用时间)  
65 - CouponDO coupon01 = randomPojo(CouponDO.class);  
66 - doThrow(new ServiceException(COUPON_VALID_TIME_NOT_NOW)).when(couponService).validCoupon(coupon01);  
67 - // mock 方法(情况二:所结算商品没有符合条件的商品)  
68 - CouponDO coupon02 = randomPojo(CouponDO.class);  
69 - // mock 方法(情况三:使用金额不足)  
70 - CouponDO coupon03 = randomPojo(CouponDO.class, o -> o.setProductScope(PromotionProductScopeEnum.ALL.getScope())  
71 - .setUsePrice(300));  
72 - // mock 方法(情况五:满足条件)  
73 - CouponDO coupon04 = randomPojo(CouponDO.class, o -> o.setProductScope(PromotionProductScopeEnum.ALL.getScope())  
74 - .setUsePrice(190));  
75 - // mock 方法(获得用户的待使用优惠劵)  
76 - when(couponService.getCouponList(eq(1024L), eq(CouponStatusEnum.UNUSED.getStatus())))  
77 - .thenReturn(asList(coupon01, coupon02, coupon03, coupon04));  
78 - // 调用  
79 - List<CouponMeetRespDTO> list = priceService.getMeetCouponList(calculateReqDTO);  
80 - // 断言  
81 - assertEquals(list.size(), 4);  
82 - // 断言情况一:优惠劵未到使用时间  
83 - CouponMeetRespDTO couponMeetRespDTO01 = list.get(0);  
84 - assertPojoEquals(couponMeetRespDTO01, coupon01);  
85 - assertFalse(couponMeetRespDTO01.getMeet());  
86 - assertEquals(couponMeetRespDTO01.getMeetTip(), "优惠劵未到使用时间");  
87 - // 断言情况二:所结算商品没有符合条件的商品  
88 - CouponMeetRespDTO couponMeetRespDTO02 = list.get(1);  
89 - assertPojoEquals(couponMeetRespDTO02, coupon02);  
90 - assertFalse(couponMeetRespDTO02.getMeet());  
91 - assertEquals(couponMeetRespDTO02.getMeetTip(), "所结算商品没有符合条件的商品");  
92 - // 断言情况三:差 %s 元可用优惠劵  
93 - CouponMeetRespDTO couponMeetRespDTO03 = list.get(2);  
94 - assertPojoEquals(couponMeetRespDTO03, coupon03);  
95 - assertFalse(couponMeetRespDTO03.getMeet());  
96 - assertEquals(couponMeetRespDTO03.getMeetTip(), "所结算的商品中未满足使用的金额");  
97 - // 断言情况四:满足条件  
98 - CouponMeetRespDTO couponMeetRespDTO04 = list.get(3);  
99 - assertPojoEquals(couponMeetRespDTO04, coupon04);  
100 - assertTrue(couponMeetRespDTO04.getMeet());  
101 - assertNull(couponMeetRespDTO04.getMeetTip());  
102 - }  
103 -  
104 -}  
yudao-module-mall/yudao-module-statistics-biz/pom.xml
@@ -58,7 +58,6 @@ @@ -58,7 +58,6 @@
58 <groupId>cn.iocoder.boot</groupId> 58 <groupId>cn.iocoder.boot</groupId>
59 <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> 59 <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
60 </dependency> 60 </dependency>
61 -  
62 <dependency> 61 <dependency>
63 <groupId>cn.iocoder.boot</groupId> 62 <groupId>cn.iocoder.boot</groupId>
64 <artifactId>yudao-spring-boot-starter-biz-ip</artifactId> 63 <artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/member/MemberStatisticsDO.java
1 package cn.iocoder.yudao.module.statistics.dal.dataobject.member; 1 package cn.iocoder.yudao.module.statistics.dal.dataobject.member;
2 2
3 -import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; 3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import com.baomidou.mybatisplus.annotation.KeySequence; 4 import com.baomidou.mybatisplus.annotation.KeySequence;
5 import com.baomidou.mybatisplus.annotation.TableId; 5 import com.baomidou.mybatisplus.annotation.TableId;
6 import com.baomidou.mybatisplus.annotation.TableName; 6 import com.baomidou.mybatisplus.annotation.TableName;
@@ -23,7 +23,7 @@ import java.time.LocalDateTime; @@ -23,7 +23,7 @@ import java.time.LocalDateTime;
23 @Builder 23 @Builder
24 @NoArgsConstructor 24 @NoArgsConstructor
25 @AllArgsConstructor 25 @AllArgsConstructor
26 -public class MemberStatisticsDO extends TenantBaseDO { 26 +public class MemberStatisticsDO extends BaseDO {
27 27
28 /** 28 /**
29 * 编号,主键自增 29 * 编号,主键自增
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/trade/TradeStatisticsDO.java
1 package cn.iocoder.yudao.module.statistics.dal.dataobject.trade; 1 package cn.iocoder.yudao.module.statistics.dal.dataobject.trade;
2 2
3 -import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; 3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import com.baomidou.mybatisplus.annotation.KeySequence; 4 import com.baomidou.mybatisplus.annotation.KeySequence;
5 import com.baomidou.mybatisplus.annotation.TableId; 5 import com.baomidou.mybatisplus.annotation.TableId;
6 import com.baomidou.mybatisplus.annotation.TableName; 6 import com.baomidou.mybatisplus.annotation.TableName;
@@ -23,7 +23,7 @@ import java.time.LocalDateTime; @@ -23,7 +23,7 @@ import java.time.LocalDateTime;
23 @Builder 23 @Builder
24 @NoArgsConstructor 24 @NoArgsConstructor
25 @AllArgsConstructor 25 @AllArgsConstructor
26 -public class TradeStatisticsDO extends TenantBaseDO { 26 +public class TradeStatisticsDO extends BaseDO {
27 27
28 /** 28 /**
29 * 编号,主键自增 29 * 编号,主键自增
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsServiceImpl.java
1 package cn.iocoder.yudao.module.statistics.service.pay; 1 package cn.iocoder.yudao.module.statistics.service.pay;
2 2
3 -import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; 3 +import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
4 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 4 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
5 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; 5 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
6 import cn.iocoder.yudao.module.statistics.dal.mysql.pay.PayWalletStatisticsMapper; 6 import cn.iocoder.yudao.module.statistics.dal.mysql.pay.PayWalletStatisticsMapper;
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageUserController.java
@@ -77,6 +77,7 @@ public class BrokerageUserController { @@ -77,6 +77,7 @@ public class BrokerageUserController {
77 @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')") 77 @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')")
78 public CommonResult<BrokerageUserRespVO> getBrokerageUser(@RequestParam("id") Long id) { 78 public CommonResult<BrokerageUserRespVO> getBrokerageUser(@RequestParam("id") Long id) {
79 BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id); 79 BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id);
  80 + // TODO @疯狂:是不是搞成一个统一的 convert?
80 BrokerageUserRespVO respVO = BrokerageUserConvert.INSTANCE.convert(brokerageUser); 81 BrokerageUserRespVO respVO = BrokerageUserConvert.INSTANCE.convert(brokerageUser);
81 return success(BrokerageUserConvert.INSTANCE.copyTo(memberUserApi.getUser(id), respVO)); 82 return success(BrokerageUserConvert.INSTANCE.copyTo(memberUserApi.getUser(id), respVO));
82 } 83 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
@@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
7 import cn.iocoder.yudao.framework.common.util.string.StrUtils; 7 import cn.iocoder.yudao.framework.common.util.string.StrUtils;
8 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; 8 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
9 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; 9 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
10 -import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 10 +import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
11 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 11 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
12 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; 12 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
13 import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; 13 import cn.iocoder.yudao.module.pay.enums.DictTypeConstants;
@@ -241,7 +241,7 @@ public interface TradeOrderConvert { @@ -241,7 +241,7 @@ public interface TradeOrderConvert {
241 return reqBO; 241 return reqBO;
242 } 242 }
243 243
244 - default AppTradeOrderSettlementRespVO convert(TradePriceCalculateRespBO calculate, AddressRespDTO address) { 244 + default AppTradeOrderSettlementRespVO convert(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address) {
245 AppTradeOrderSettlementRespVO respVO = convert0(calculate, address); 245 AppTradeOrderSettlementRespVO respVO = convert0(calculate, address);
246 if (address != null) { 246 if (address != null) {
247 respVO.getAddress().setAreaName(AreaUtils.format(address.getAreaId())); 247 respVO.getAddress().setAreaName(AreaUtils.format(address.getAreaId()));
@@ -249,7 +249,7 @@ public interface TradeOrderConvert { @@ -249,7 +249,7 @@ public interface TradeOrderConvert {
249 return respVO; 249 return respVO;
250 } 250 }
251 251
252 - AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address); 252 + AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address);
253 253
254 List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list); 254 List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list);
255 255
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserServiceImpl.java
@@ -232,7 +232,8 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -232,7 +232,8 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
232 return PageResult.empty(); 232 return PageResult.empty();
233 } 233 }
234 // 1.2 根据昵称过滤下级用户 234 // 1.2 根据昵称过滤下级用户
235 - Map<Long, MemberUserRespDTO> userMap = convertMapByFilter(memberUserApi.getUserList(childIds), 235 + List<MemberUserRespDTO> users = memberUserApi.getUserList(childIds);
  236 + Map<Long, MemberUserRespDTO> userMap = convertMapByFilter(users,
236 user -> StrUtil.contains(user.getNickname(), pageReqVO.getNickname()), 237 user -> StrUtil.contains(user.getNickname(), pageReqVO.getNickname()),
237 MemberUserRespDTO::getId); 238 MemberUserRespDTO::getId);
238 if (CollUtil.isEmpty(userMap)) { 239 if (CollUtil.isEmpty(userMap)) {
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
@@ -11,8 +11,8 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; @@ -11,8 +11,8 @@ import cn.iocoder.yudao.framework.common.core.KeyValue;
11 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 11 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
12 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 12 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
13 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; 13 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
14 -import cn.iocoder.yudao.module.member.api.address.AddressApi;  
15 -import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 14 +import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
  15 +import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
16 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; 16 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
17 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; 17 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
18 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; 18 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
@@ -98,7 +98,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -98,7 +98,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
98 @Resource 98 @Resource
99 private PayOrderApi payOrderApi; 99 private PayOrderApi payOrderApi;
100 @Resource 100 @Resource
101 - private AddressApi addressApi; 101 + private MemberAddressApi addressApi;
102 @Resource 102 @Resource
103 private ProductCommentApi productCommentApi; 103 private ProductCommentApi productCommentApi;
104 104
@@ -110,7 +110,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -110,7 +110,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
110 @Override 110 @Override
111 public AppTradeOrderSettlementRespVO settlementOrder(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) { 111 public AppTradeOrderSettlementRespVO settlementOrder(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) {
112 // 1. 获得收货地址 112 // 1. 获得收货地址
113 - AddressRespDTO address = getAddress(userId, settlementReqVO.getAddressId()); 113 + MemberAddressRespDTO address = getAddress(userId, settlementReqVO.getAddressId());
114 if (address != null) { 114 if (address != null) {
115 settlementReqVO.setAddressId(address.getId()); 115 settlementReqVO.setAddressId(address.getId());
116 } 116 }
@@ -129,7 +129,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -129,7 +129,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
129 * @param addressId 地址编号 129 * @param addressId 地址编号
130 * @return 地址 130 * @return 地址
131 */ 131 */
132 - private AddressRespDTO getAddress(Long userId, Long addressId) { 132 + private MemberAddressRespDTO getAddress(Long userId, Long addressId) {
133 if (addressId != null) { 133 if (addressId != null) {
134 return addressApi.getAddress(addressId, userId); 134 return addressApi.getAddress(addressId, userId);
135 } 135 }
@@ -193,7 +193,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -193,7 +193,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
193 // 物流信息 193 // 物流信息
194 order.setDeliveryType(createReqVO.getDeliveryType()); 194 order.setDeliveryType(createReqVO.getDeliveryType());
195 if (Objects.equals(createReqVO.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getType())) { 195 if (Objects.equals(createReqVO.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getType())) {
196 - AddressRespDTO address = addressApi.getAddress(createReqVO.getAddressId(), userId); 196 + MemberAddressRespDTO address = addressApi.getAddress(createReqVO.getAddressId(), userId);
197 Assert.notNull(address, "地址({}) 不能为空", createReqVO.getAddressId()); // 价格计算时,已经计算 197 Assert.notNull(address, "地址({}) 不能为空", createReqVO.getAddressId()); // 价格计算时,已经计算
198 order.setReceiverName(address.getName()).setReceiverMobile(address.getMobile()) 198 order.setReceiverName(address.getName()).setReceiverMobile(address.getMobile())
199 .setReceiverAreaId(address.getAreaId()).setReceiverDetailAddress(address.getDetailAddress()); 199 .setReceiverAreaId(address.getAreaId()).setReceiverDetailAddress(address.getDetailAddress());
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculator.java
@@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil; @@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 -import cn.iocoder.yudao.module.member.api.address.AddressApi;  
8 -import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 7 +import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
  8 +import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
9 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; 9 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
10 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO; 10 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
11 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum; 11 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
@@ -41,7 +41,7 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; @@ -41,7 +41,7 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
41 public class TradeDeliveryPriceCalculator implements TradePriceCalculator { 41 public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
42 42
43 @Resource 43 @Resource
44 - private AddressApi addressApi; 44 + private MemberAddressApi addressApi;
45 45
46 @Resource 46 @Resource
47 private DeliveryPickUpStoreService deliveryPickUpStoreService; 47 private DeliveryPickUpStoreService deliveryPickUpStoreService;
@@ -81,7 +81,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { @@ -81,7 +81,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
81 // 价格计算时,如果为空就不算~最终下单,会校验该字段不允许空 81 // 价格计算时,如果为空就不算~最终下单,会校验该字段不允许空
82 return; 82 return;
83 } 83 }
84 - AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId()); 84 + MemberAddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId());
85 Assert.notNull(address, "收件人({})的地址,不能为空", param.getUserId()); 85 Assert.notNull(address, "收件人({})的地址,不能为空", param.getUserId());
86 86
87 // 情况一:全局包邮 87 // 情况一:全局包邮
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java
1 package cn.iocoder.yudao.module.trade.service.order; 1 package cn.iocoder.yudao.module.trade.service.order;
2 2
3 -import cn.iocoder.yudao.framework.common.enums.TerminalEnum;  
4 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 3 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
5 -import cn.iocoder.yudao.module.member.api.address.AddressApi;  
6 -import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 4 +import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
7 import cn.iocoder.yudao.module.member.api.user.MemberUserApi; 5 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
8 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; 6 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
9 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; 7 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
10 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 8 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
11 -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;  
12 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; 9 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
13 -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;  
14 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; 10 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
15 -import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;  
16 -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;  
17 import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; 11 import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
18 -import cn.iocoder.yudao.module.promotion.api.price.PriceApi;  
19 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;  
20 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; 12 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
21 -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;  
22 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; 13 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
23 -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;  
24 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; 14 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
25 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; 15 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
26 -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;  
27 -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum;  
28 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; 16 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
29 -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;  
30 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig; 17 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig;
31 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; 18 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
32 import org.junit.jupiter.api.BeforeEach; 19 import org.junit.jupiter.api.BeforeEach;
@@ -36,17 +23,11 @@ import org.springframework.context.annotation.Import; @@ -36,17 +23,11 @@ import org.springframework.context.annotation.Import;
36 23
37 import javax.annotation.Resource; 24 import javax.annotation.Resource;
38 import java.time.Duration; 25 import java.time.Duration;
39 -import java.util.Arrays;  
40 -import java.util.List;  
41 26
42 -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;  
43 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; 27 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
44 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; 28 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
45 -import static java.util.Collections.singletonList;  
46 import static org.junit.jupiter.api.Assertions.*; 29 import static org.junit.jupiter.api.Assertions.*;
47 -import static org.mockito.ArgumentMatchers.argThat;  
48 import static org.mockito.ArgumentMatchers.eq; 30 import static org.mockito.ArgumentMatchers.eq;
49 -import static org.mockito.Mockito.verify;  
50 import static org.mockito.Mockito.when; 31 import static org.mockito.Mockito.when;
51 32
52 /** 33 /**
@@ -72,12 +53,12 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { @@ -72,12 +53,12 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest {
72 private ProductSpuApi productSpuApi; 53 private ProductSpuApi productSpuApi;
73 @MockBean 54 @MockBean
74 private ProductSkuApi productSkuApi; 55 private ProductSkuApi productSkuApi;
75 - @MockBean  
76 - private PriceApi priceApi; 56 +// @MockBean
  57 +// private PriceApi priceApi;
77 @MockBean 58 @MockBean
78 private PayOrderApi payOrderApi; 59 private PayOrderApi payOrderApi;
79 @MockBean 60 @MockBean
80 - private AddressApi addressApi; 61 + private MemberAddressApi addressApi;
81 @MockBean 62 @MockBean
82 private CouponApi couponApi; 63 private CouponApi couponApi;
83 64
@@ -90,159 +71,159 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { @@ -90,159 +71,159 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest {
90 when(tradeOrderProperties.getPayExpireTime()).thenReturn(Duration.ofDays(1)); 71 when(tradeOrderProperties.getPayExpireTime()).thenReturn(Duration.ofDays(1));
91 } 72 }
92 73
93 - @Test  
94 - public void testCreateTradeOrder_success() {  
95 - // 准备参数  
96 - Long userId = 100L;  
97 - String userIp = "127.0.0.1";  
98 -// AppTradeOrderCreateReqVO reqVO = new AppTradeOrderCreateReqVO()  
99 -// .setAddressId(10L).setCouponId(101L).setRemark("我是备注").setFromCart(true)  
100 -// .setItems(Arrays.asList(new AppTradeOrderCreateReqVO.Item().setSkuId(1L).setCount(3),  
101 -// new AppTradeOrderCreateReqVO.Item().setSkuId(2L).setCount(4)));  
102 - AppTradeOrderCreateReqVO reqVO = null;  
103 - // TODO 芋艿:重新高下  
104 - // mock 方法(商品 SKU 检查)  
105 - ProductSkuRespDTO sku01 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(1L).setSpuId(11L)  
106 - .setPrice(50).setStock(100)  
107 - .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(111L).setValueId(222L))));  
108 - ProductSkuRespDTO sku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(2L).setSpuId(21L)  
109 - .setPrice(20).setStock(50))  
110 - .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(333L).setValueId(444L)));  
111 - when(productSkuApi.getSkuList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(sku01, sku02));  
112 - // mock 方法(商品 SPU 检查)  
113 - ProductSpuRespDTO spu01 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(11L)  
114 - .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()).setName("商品 1"));  
115 - ProductSpuRespDTO spu02 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(21L)  
116 - .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()));  
117 - when(productSpuApi.getSpuList(eq(asSet(11L, 21L)))).thenReturn(Arrays.asList(spu01, spu02));  
118 - // mock 方法(用户收件地址的校验)  
119 - AddressRespDTO addressRespDTO = new AddressRespDTO().setId(10L).setUserId(userId).setName("芋艿")  
120 - .setMobile("15601691300").setAreaId(3306).setDetailAddress("土豆村");  
121 - when(addressApi.getAddress(eq(10L), eq(userId))).thenReturn(addressRespDTO);  
122 - // mock 方法(价格计算)  
123 - PriceCalculateRespDTO.OrderItem priceOrderItem01 = new PriceCalculateRespDTO.OrderItem()  
124 - .setSpuId(11L).setSkuId(1L).setCount(3).setOriginalPrice(150).setOriginalUnitPrice(50)  
125 - .setDiscountPrice(20).setPayPrice(130).setOrderPartPrice(7).setOrderDividePrice(35);  
126 - PriceCalculateRespDTO.OrderItem priceOrderItem02 = new PriceCalculateRespDTO.OrderItem()  
127 - .setSpuId(21L).setSkuId(2L).setCount(4).setOriginalPrice(80).setOriginalUnitPrice(20)  
128 - .setDiscountPrice(40).setPayPrice(40).setOrderPartPrice(15).setOrderDividePrice(25);  
129 - PriceCalculateRespDTO.Order priceOrder = new PriceCalculateRespDTO.Order()  
130 - .setTotalPrice(230).setDiscountPrice(0).setCouponPrice(30)  
131 - .setPointPrice(10).setDeliveryPrice(20).setPayPrice(80).setCouponId(101L).setCouponPrice(30)  
132 - .setItems(Arrays.asList(priceOrderItem01, priceOrderItem02));  
133 - when(priceApi.calculatePrice(argThat(priceCalculateReqDTO -> {  
134 - assertEquals(priceCalculateReqDTO.getUserId(), 100L);  
135 - assertEquals(priceCalculateReqDTO.getCouponId(), 101L);  
136 - assertEquals(priceCalculateReqDTO.getItems().get(0).getSkuId(), 1L);  
137 - assertEquals(priceCalculateReqDTO.getItems().get(0).getCount(), 3);  
138 - assertEquals(priceCalculateReqDTO.getItems().get(1).getSkuId(), 2L);  
139 - assertEquals(priceCalculateReqDTO.getItems().get(1).getCount(), 4);  
140 - return true;  
141 - }))).thenReturn(new PriceCalculateRespDTO().setOrder(priceOrder));  
142 - // mock 方法(创建支付单)  
143 - when(payOrderApi.createOrder(argThat(createReqDTO -> {  
144 - assertEquals(createReqDTO.getAppId(), 888L);  
145 - assertEquals(createReqDTO.getUserIp(), userIp);  
146 - assertNotNull(createReqDTO.getMerchantOrderId()); // 由于 tradeOrderId 后生成,只能校验非空  
147 - assertEquals(createReqDTO.getSubject(), "商品 1 等多件");  
148 - assertNull(createReqDTO.getBody());  
149 - assertEquals(createReqDTO.getPrice(), 80);  
150 - assertNotNull(createReqDTO.getExpireTime());  
151 - return true;  
152 - }))).thenReturn(1000L);  
153 -  
154 - // 调用方法  
155 - TradeOrderDO order = tradeOrderUpdateService.createOrder(userId, userIp, reqVO, null);  
156 - // 断言 TradeOrderDO 订单  
157 - List<TradeOrderDO> tradeOrderDOs = tradeOrderMapper.selectList();  
158 - assertEquals(tradeOrderDOs.size(), 1);  
159 - TradeOrderDO tradeOrderDO = tradeOrderDOs.get(0);  
160 - assertEquals(tradeOrderDO.getId(), order.getId());  
161 - assertNotNull(tradeOrderDO.getNo());  
162 - assertEquals(tradeOrderDO.getType(), TradeOrderTypeEnum.NORMAL.getType());  
163 - assertEquals(tradeOrderDO.getTerminal(), TerminalEnum.H5.getTerminal());  
164 - assertEquals(tradeOrderDO.getUserId(), userId);  
165 - assertEquals(tradeOrderDO.getUserIp(), userIp);  
166 - assertEquals(tradeOrderDO.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus());  
167 - assertEquals(tradeOrderDO.getProductCount(), 7);  
168 - assertNull(tradeOrderDO.getFinishTime());  
169 - assertNull(tradeOrderDO.getCancelTime());  
170 - assertNull(tradeOrderDO.getCancelType());  
171 - assertEquals(tradeOrderDO.getUserRemark(), "我是备注");  
172 - assertNull(tradeOrderDO.getRemark());  
173 - assertFalse(tradeOrderDO.getPayStatus());  
174 - assertNull(tradeOrderDO.getPayTime());  
175 - assertEquals(tradeOrderDO.getTotalPrice(), 230);  
176 - assertEquals(tradeOrderDO.getDiscountPrice(), 0);  
177 - assertEquals(tradeOrderDO.getAdjustPrice(), 0);  
178 - assertEquals(tradeOrderDO.getPayPrice(), 80);  
179 - assertEquals(tradeOrderDO.getPayOrderId(), 1000L);  
180 - assertNull(tradeOrderDO.getPayChannelCode());  
181 - assertNull(tradeOrderDO.getLogisticsId());  
182 - assertNull(tradeOrderDO.getDeliveryTime());  
183 - assertNull(tradeOrderDO.getReceiveTime());  
184 - assertEquals(tradeOrderDO.getReceiverName(), "芋艿");  
185 - assertEquals(tradeOrderDO.getReceiverMobile(), "15601691300");  
186 - assertEquals(tradeOrderDO.getReceiverAreaId(), 3306);  
187 - assertEquals(tradeOrderDO.getReceiverDetailAddress(), "土豆村");  
188 - assertEquals(tradeOrderDO.getRefundStatus(), TradeOrderRefundStatusEnum.NONE.getStatus());  
189 - assertEquals(tradeOrderDO.getRefundPrice(), 0);  
190 - assertEquals(tradeOrderDO.getCouponPrice(), 30);  
191 - assertEquals(tradeOrderDO.getPointPrice(), 10);  
192 - // 断言 TradeOrderItemDO 订单(第 1 个)  
193 - List<TradeOrderItemDO> tradeOrderItemDOs = tradeOrderItemMapper.selectList();  
194 - assertEquals(tradeOrderItemDOs.size(), 2);  
195 - TradeOrderItemDO tradeOrderItemDO01 = tradeOrderItemDOs.get(0);  
196 - assertNotNull(tradeOrderItemDO01.getId());  
197 - assertEquals(tradeOrderItemDO01.getUserId(), userId);  
198 - assertEquals(tradeOrderItemDO01.getOrderId(), order.getId());  
199 - assertEquals(tradeOrderItemDO01.getSpuId(), 11L);  
200 - assertEquals(tradeOrderItemDO01.getSkuId(), 1L);  
201 - assertEquals(tradeOrderItemDO01.getProperties().size(), 1);  
202 - assertEquals(tradeOrderItemDO01.getProperties().get(0).getPropertyId(), 111L);  
203 - assertEquals(tradeOrderItemDO01.getProperties().get(0).getValueId(), 222L);  
204 - //assertEquals(tradeOrderItemDO01.getSpuName(), sku01.getSpuName()); TODO 找不到spuName  
205 - assertEquals(tradeOrderItemDO01.getPicUrl(), sku01.getPicUrl());  
206 - assertEquals(tradeOrderItemDO01.getCount(), 3);  
207 -// assertEquals(tradeOrderItemDO01.getOriginalPrice(), 150);  
208 - assertEquals(tradeOrderItemDO01.getPrice(), 50);  
209 - assertEquals(tradeOrderItemDO01.getDiscountPrice(), 20);  
210 - assertEquals(tradeOrderItemDO01.getPayPrice(), 130);  
211 - assertEquals(tradeOrderItemDO01.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());  
212 - // 断言 TradeOrderItemDO 订单(第 2 个)  
213 - TradeOrderItemDO tradeOrderItemDO02 = tradeOrderItemDOs.get(1);  
214 - assertNotNull(tradeOrderItemDO02.getId());  
215 - assertEquals(tradeOrderItemDO02.getUserId(), userId);  
216 - assertEquals(tradeOrderItemDO02.getOrderId(), order.getId());  
217 - assertEquals(tradeOrderItemDO02.getSpuId(), 21L);  
218 - assertEquals(tradeOrderItemDO02.getSkuId(), 2L);  
219 - assertEquals(tradeOrderItemDO02.getProperties().size(), 1);  
220 - assertEquals(tradeOrderItemDO02.getProperties().get(0).getPropertyId(), 333L);  
221 - assertEquals(tradeOrderItemDO02.getProperties().get(0).getValueId(), 444L);  
222 - //assertEquals(tradeOrderItemDO02.getSpuName(), sku02.getSpuName()); TODO 找不到spuName  
223 - assertEquals(tradeOrderItemDO02.getPicUrl(), sku02.getPicUrl());  
224 - assertEquals(tradeOrderItemDO02.getCount(), 4);  
225 -// assertEquals(tradeOrderItemDO02.getOriginalPrice(), 80);  
226 - assertEquals(tradeOrderItemDO02.getPrice(), 20);  
227 - assertEquals(tradeOrderItemDO02.getDiscountPrice(), 40);  
228 - assertEquals(tradeOrderItemDO02.getPayPrice(), 40);  
229 - assertEquals(tradeOrderItemDO02.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());  
230 - // 校验调用  
231 - verify(productSkuApi).updateSkuStock(argThat(updateStockReqDTO -> {  
232 - assertEquals(updateStockReqDTO.getItems().size(), 2);  
233 - assertEquals(updateStockReqDTO.getItems().get(0).getId(), 1L);  
234 - assertEquals(updateStockReqDTO.getItems().get(0).getIncrCount(), 3);  
235 - assertEquals(updateStockReqDTO.getItems().get(1).getId(), 2L);  
236 - assertEquals(updateStockReqDTO.getItems().get(1).getIncrCount(), 4);  
237 - return true;  
238 - }));  
239 - verify(couponApi).useCoupon(argThat(reqDTO -> {  
240 - assertEquals(reqDTO.getId(), reqVO.getCouponId());  
241 - assertEquals(reqDTO.getUserId(), userId);  
242 - assertEquals(reqDTO.getOrderId(), order.getId());  
243 - return true;  
244 - }));  
245 - } 74 +// @Test
  75 +// public void testCreateTradeOrder_success() {
  76 +// // 准备参数
  77 +// Long userId = 100L;
  78 +// String userIp = "127.0.0.1";
  79 +//// AppTradeOrderCreateReqVO reqVO = new AppTradeOrderCreateReqVO()
  80 +//// .setAddressId(10L).setCouponId(101L).setRemark("我是备注").setFromCart(true)
  81 +//// .setItems(Arrays.asList(new AppTradeOrderCreateReqVO.Item().setSkuId(1L).setCount(3),
  82 +//// new AppTradeOrderCreateReqVO.Item().setSkuId(2L).setCount(4)));
  83 +// AppTradeOrderCreateReqVO reqVO = null;
  84 +// // TODO 芋艿:重新高下
  85 +// // mock 方法(商品 SKU 检查)
  86 +// ProductSkuRespDTO sku01 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(1L).setSpuId(11L)
  87 +// .setPrice(50).setStock(100)
  88 +// .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(111L).setValueId(222L))));
  89 +// ProductSkuRespDTO sku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(2L).setSpuId(21L)
  90 +// .setPrice(20).setStock(50))
  91 +// .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(333L).setValueId(444L)));
  92 +// when(productSkuApi.getSkuList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(sku01, sku02));
  93 +// // mock 方法(商品 SPU 检查)
  94 +// ProductSpuRespDTO spu01 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(11L)
  95 +// .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()).setName("商品 1"));
  96 +// ProductSpuRespDTO spu02 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(21L)
  97 +// .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()));
  98 +// when(productSpuApi.getSpuList(eq(asSet(11L, 21L)))).thenReturn(Arrays.asList(spu01, spu02));
  99 +// // mock 方法(用户收件地址的校验)
  100 +// MemberAddressRespDTO addressRespDTO = new MemberAddressRespDTO().setId(10L).setUserId(userId).setName("芋艿")
  101 +// .setMobile("15601691300").setAreaId(3306).setDetailAddress("土豆村");
  102 +// when(addressApi.getAddress(eq(10L), eq(userId))).thenReturn(addressRespDTO);
  103 +// // mock 方法(价格计算)
  104 +// PriceCalculateRespDTO.OrderItem priceOrderItem01 = new PriceCalculateRespDTO.OrderItem()
  105 +// .setSpuId(11L).setSkuId(1L).setCount(3).setOriginalPrice(150).setOriginalUnitPrice(50)
  106 +// .setDiscountPrice(20).setPayPrice(130).setOrderPartPrice(7).setOrderDividePrice(35);
  107 +// PriceCalculateRespDTO.OrderItem priceOrderItem02 = new PriceCalculateRespDTO.OrderItem()
  108 +// .setSpuId(21L).setSkuId(2L).setCount(4).setOriginalPrice(80).setOriginalUnitPrice(20)
  109 +// .setDiscountPrice(40).setPayPrice(40).setOrderPartPrice(15).setOrderDividePrice(25);
  110 +// PriceCalculateRespDTO.Order priceOrder = new PriceCalculateRespDTO.Order()
  111 +// .setTotalPrice(230).setDiscountPrice(0).setCouponPrice(30)
  112 +// .setPointPrice(10).setDeliveryPrice(20).setPayPrice(80).setCouponId(101L).setCouponPrice(30)
  113 +// .setItems(Arrays.asList(priceOrderItem01, priceOrderItem02));
  114 +// when(priceApi.calculatePrice(argThat(priceCalculateReqDTO -> {
  115 +// assertEquals(priceCalculateReqDTO.getUserId(), 100L);
  116 +// assertEquals(priceCalculateReqDTO.getCouponId(), 101L);
  117 +// assertEquals(priceCalculateReqDTO.getItems().get(0).getSkuId(), 1L);
  118 +// assertEquals(priceCalculateReqDTO.getItems().get(0).getCount(), 3);
  119 +// assertEquals(priceCalculateReqDTO.getItems().get(1).getSkuId(), 2L);
  120 +// assertEquals(priceCalculateReqDTO.getItems().get(1).getCount(), 4);
  121 +// return true;
  122 +// }))).thenReturn(new PriceCalculateRespDTO().setOrder(priceOrder));
  123 +// // mock 方法(创建支付单)
  124 +// when(payOrderApi.createOrder(argThat(createReqDTO -> {
  125 +// assertEquals(createReqDTO.getAppId(), 888L);
  126 +// assertEquals(createReqDTO.getUserIp(), userIp);
  127 +// assertNotNull(createReqDTO.getMerchantOrderId()); // 由于 tradeOrderId 后生成,只能校验非空
  128 +// assertEquals(createReqDTO.getSubject(), "商品 1 等多件");
  129 +// assertNull(createReqDTO.getBody());
  130 +// assertEquals(createReqDTO.getPrice(), 80);
  131 +// assertNotNull(createReqDTO.getExpireTime());
  132 +// return true;
  133 +// }))).thenReturn(1000L);
  134 +//
  135 +// // 调用方法
  136 +// TradeOrderDO order = tradeOrderUpdateService.createOrder(userId, userIp, reqVO, null);
  137 +// // 断言 TradeOrderDO 订单
  138 +// List<TradeOrderDO> tradeOrderDOs = tradeOrderMapper.selectList();
  139 +// assertEquals(tradeOrderDOs.size(), 1);
  140 +// TradeOrderDO tradeOrderDO = tradeOrderDOs.get(0);
  141 +// assertEquals(tradeOrderDO.getId(), order.getId());
  142 +// assertNotNull(tradeOrderDO.getNo());
  143 +// assertEquals(tradeOrderDO.getType(), TradeOrderTypeEnum.NORMAL.getType());
  144 +// assertEquals(tradeOrderDO.getTerminal(), TerminalEnum.H5.getTerminal());
  145 +// assertEquals(tradeOrderDO.getUserId(), userId);
  146 +// assertEquals(tradeOrderDO.getUserIp(), userIp);
  147 +// assertEquals(tradeOrderDO.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus());
  148 +// assertEquals(tradeOrderDO.getProductCount(), 7);
  149 +// assertNull(tradeOrderDO.getFinishTime());
  150 +// assertNull(tradeOrderDO.getCancelTime());
  151 +// assertNull(tradeOrderDO.getCancelType());
  152 +// assertEquals(tradeOrderDO.getUserRemark(), "我是备注");
  153 +// assertNull(tradeOrderDO.getRemark());
  154 +// assertFalse(tradeOrderDO.getPayStatus());
  155 +// assertNull(tradeOrderDO.getPayTime());
  156 +// assertEquals(tradeOrderDO.getTotalPrice(), 230);
  157 +// assertEquals(tradeOrderDO.getDiscountPrice(), 0);
  158 +// assertEquals(tradeOrderDO.getAdjustPrice(), 0);
  159 +// assertEquals(tradeOrderDO.getPayPrice(), 80);
  160 +// assertEquals(tradeOrderDO.getPayOrderId(), 1000L);
  161 +// assertNull(tradeOrderDO.getPayChannelCode());
  162 +// assertNull(tradeOrderDO.getLogisticsId());
  163 +// assertNull(tradeOrderDO.getDeliveryTime());
  164 +// assertNull(tradeOrderDO.getReceiveTime());
  165 +// assertEquals(tradeOrderDO.getReceiverName(), "芋艿");
  166 +// assertEquals(tradeOrderDO.getReceiverMobile(), "15601691300");
  167 +// assertEquals(tradeOrderDO.getReceiverAreaId(), 3306);
  168 +// assertEquals(tradeOrderDO.getReceiverDetailAddress(), "土豆村");
  169 +// assertEquals(tradeOrderDO.getRefundStatus(), TradeOrderRefundStatusEnum.NONE.getStatus());
  170 +// assertEquals(tradeOrderDO.getRefundPrice(), 0);
  171 +// assertEquals(tradeOrderDO.getCouponPrice(), 30);
  172 +// assertEquals(tradeOrderDO.getPointPrice(), 10);
  173 +// // 断言 TradeOrderItemDO 订单(第 1 个)
  174 +// List<TradeOrderItemDO> tradeOrderItemDOs = tradeOrderItemMapper.selectList();
  175 +// assertEquals(tradeOrderItemDOs.size(), 2);
  176 +// TradeOrderItemDO tradeOrderItemDO01 = tradeOrderItemDOs.get(0);
  177 +// assertNotNull(tradeOrderItemDO01.getId());
  178 +// assertEquals(tradeOrderItemDO01.getUserId(), userId);
  179 +// assertEquals(tradeOrderItemDO01.getOrderId(), order.getId());
  180 +// assertEquals(tradeOrderItemDO01.getSpuId(), 11L);
  181 +// assertEquals(tradeOrderItemDO01.getSkuId(), 1L);
  182 +// assertEquals(tradeOrderItemDO01.getProperties().size(), 1);
  183 +// assertEquals(tradeOrderItemDO01.getProperties().get(0).getPropertyId(), 111L);
  184 +// assertEquals(tradeOrderItemDO01.getProperties().get(0).getValueId(), 222L);
  185 +// //assertEquals(tradeOrderItemDO01.getSpuName(), sku01.getSpuName()); TODO 找不到spuName
  186 +// assertEquals(tradeOrderItemDO01.getPicUrl(), sku01.getPicUrl());
  187 +// assertEquals(tradeOrderItemDO01.getCount(), 3);
  188 +//// assertEquals(tradeOrderItemDO01.getOriginalPrice(), 150);
  189 +// assertEquals(tradeOrderItemDO01.getPrice(), 50);
  190 +// assertEquals(tradeOrderItemDO01.getDiscountPrice(), 20);
  191 +// assertEquals(tradeOrderItemDO01.getPayPrice(), 130);
  192 +// assertEquals(tradeOrderItemDO01.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
  193 +// // 断言 TradeOrderItemDO 订单(第 2 个)
  194 +// TradeOrderItemDO tradeOrderItemDO02 = tradeOrderItemDOs.get(1);
  195 +// assertNotNull(tradeOrderItemDO02.getId());
  196 +// assertEquals(tradeOrderItemDO02.getUserId(), userId);
  197 +// assertEquals(tradeOrderItemDO02.getOrderId(), order.getId());
  198 +// assertEquals(tradeOrderItemDO02.getSpuId(), 21L);
  199 +// assertEquals(tradeOrderItemDO02.getSkuId(), 2L);
  200 +// assertEquals(tradeOrderItemDO02.getProperties().size(), 1);
  201 +// assertEquals(tradeOrderItemDO02.getProperties().get(0).getPropertyId(), 333L);
  202 +// assertEquals(tradeOrderItemDO02.getProperties().get(0).getValueId(), 444L);
  203 +// //assertEquals(tradeOrderItemDO02.getSpuName(), sku02.getSpuName()); TODO 找不到spuName
  204 +// assertEquals(tradeOrderItemDO02.getPicUrl(), sku02.getPicUrl());
  205 +// assertEquals(tradeOrderItemDO02.getCount(), 4);
  206 +//// assertEquals(tradeOrderItemDO02.getOriginalPrice(), 80);
  207 +// assertEquals(tradeOrderItemDO02.getPrice(), 20);
  208 +// assertEquals(tradeOrderItemDO02.getDiscountPrice(), 40);
  209 +// assertEquals(tradeOrderItemDO02.getPayPrice(), 40);
  210 +// assertEquals(tradeOrderItemDO02.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
  211 +// // 校验调用
  212 +// verify(productSkuApi).updateSkuStock(argThat(updateStockReqDTO -> {
  213 +// assertEquals(updateStockReqDTO.getItems().size(), 2);
  214 +// assertEquals(updateStockReqDTO.getItems().get(0).getId(), 1L);
  215 +// assertEquals(updateStockReqDTO.getItems().get(0).getIncrCount(), 3);
  216 +// assertEquals(updateStockReqDTO.getItems().get(1).getId(), 2L);
  217 +// assertEquals(updateStockReqDTO.getItems().get(1).getIncrCount(), 4);
  218 +// return true;
  219 +// }));
  220 +// verify(couponApi).useCoupon(argThat(reqDTO -> {
  221 +// assertEquals(reqDTO.getId(), reqVO.getCouponId());
  222 +// assertEquals(reqDTO.getUserId(), userId);
  223 +// assertEquals(reqDTO.getOrderId(), order.getId());
  224 +// return true;
  225 +// }));
  226 +// }
246 227
247 @Test 228 @Test
248 public void testUpdateOrderPaid() { 229 public void testUpdateOrderPaid() {
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculatorTest.java
@@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.trade.service.price.calculator;
2 2
3 import cn.hutool.core.map.MapUtil; 3 import cn.hutool.core.map.MapUtil;
4 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; 4 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
5 -import cn.iocoder.yudao.module.member.api.address.AddressApi;  
6 -import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 5 +import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
  6 +import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
7 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; 7 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
8 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum; 8 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
9 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; 9 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
@@ -38,7 +38,7 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { @@ -38,7 +38,7 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
38 private TradeDeliveryPriceCalculator calculator; 38 private TradeDeliveryPriceCalculator calculator;
39 39
40 @Mock 40 @Mock
41 - private AddressApi addressApi; 41 + private MemberAddressApi addressApi;
42 42
43 @Mock 43 @Mock
44 private DeliveryExpressTemplateService deliveryExpressTemplateService; 44 private DeliveryExpressTemplateService deliveryExpressTemplateService;
@@ -80,7 +80,7 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { @@ -80,7 +80,7 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
80 TradePriceCalculatorHelper.recountAllPrice(resultBO); 80 TradePriceCalculatorHelper.recountAllPrice(resultBO);
81 81
82 // 准备收件地址数据 82 // 准备收件地址数据
83 - AddressRespDTO addressResp = randomPojo(AddressRespDTO.class, item -> item.setAreaId(10)); 83 + MemberAddressRespDTO addressResp = randomPojo(MemberAddressRespDTO.class, item -> item.setAreaId(10));
84 when(addressApi.getAddress(eq(10L), eq(1L))).thenReturn(addressResp); 84 when(addressApi.getAddress(eq(10L), eq(1L))).thenReturn(addressResp);
85 85
86 // 准备运费模板费用配置数据 86 // 准备运费模板费用配置数据
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/AddressApi.java renamed to yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/MemberAddressApi.java
1 package cn.iocoder.yudao.module.member.api.address; 1 package cn.iocoder.yudao.module.member.api.address;
2 2
3 -import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 3 +import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
4 4
5 /** 5 /**
6 * 用户收件地址 API 接口 6 * 用户收件地址 API 接口
7 * 7 *
8 * @author 芋道源码 8 * @author 芋道源码
9 */ 9 */
10 -public interface AddressApi { 10 +public interface MemberAddressApi {
11 11
12 /** 12 /**
13 * 获得用户收件地址 13 * 获得用户收件地址
@@ -16,7 +16,7 @@ public interface AddressApi { @@ -16,7 +16,7 @@ public interface AddressApi {
16 * @param userId 用户编号 16 * @param userId 用户编号
17 * @return 用户收件地址 17 * @return 用户收件地址
18 */ 18 */
19 - AddressRespDTO getAddress(Long id, Long userId); 19 + MemberAddressRespDTO getAddress(Long id, Long userId);
20 20
21 /** 21 /**
22 * 获得用户默认收件地址 22 * 获得用户默认收件地址
@@ -24,6 +24,6 @@ public interface AddressApi { @@ -24,6 +24,6 @@ public interface AddressApi {
24 * @param userId 用户编号 24 * @param userId 用户编号
25 * @return 用户收件地址 25 * @return 用户收件地址
26 */ 26 */
27 - AddressRespDTO getDefaultAddress(Long userId); 27 + MemberAddressRespDTO getDefaultAddress(Long userId);
28 28
29 } 29 }
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/dto/AddressRespDTO.java renamed to yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/address/dto/MemberAddressRespDTO.java
@@ -8,7 +8,7 @@ import lombok.Data; @@ -8,7 +8,7 @@ import lombok.Data;
8 * @author 芋道源码 8 * @author 芋道源码
9 */ 9 */
10 @Data 10 @Data
11 -public class AddressRespDTO { 11 +public class MemberAddressRespDTO {
12 12
13 /** 13 /**
14 * 编号 14 * 编号
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java
@@ -38,7 +38,8 @@ public interface MemberUserApi { @@ -38,7 +38,8 @@ public interface MemberUserApi {
38 * @return 会员用户 Map 38 * @return 会员用户 Map
39 */ 39 */
40 default Map<Long, MemberUserRespDTO> getUserMap(Collection<Long> ids) { 40 default Map<Long, MemberUserRespDTO> getUserMap(Collection<Long> ids) {
41 - return convertMap(getUserList(ids), MemberUserRespDTO::getId); 41 + List<MemberUserRespDTO> list = getUserList(ids);
  42 + return convertMap(list, MemberUserRespDTO::getId);
42 } 43 }
43 44
44 /** 45 /**
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/message/package-info.java 0 → 100644
  1 +/**
  2 + * 消息队列的消息
  3 + */
  4 +package cn.iocoder.yudao.module.member.message;
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/message/coupon/UserCreateMessage.java renamed to yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/message/user/MemberUserCreateMessage.java
1 -package cn.iocoder.yudao.module.promotion.mq.message.coupon; 1 +package cn.iocoder.yudao.module.member.message.user;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;  
4 import lombok.Data; 3 import lombok.Data;
5 -import lombok.EqualsAndHashCode;  
6 4
7 import javax.validation.constraints.NotNull; 5 import javax.validation.constraints.NotNull;
8 6
@@ -12,8 +10,7 @@ import javax.validation.constraints.NotNull; @@ -12,8 +10,7 @@ import javax.validation.constraints.NotNull;
12 * @author owen 10 * @author owen
13 */ 11 */
14 @Data 12 @Data
15 -@EqualsAndHashCode(callSuper = true)  
16 -public class UserCreateMessage extends AbstractStreamMessage { 13 +public class MemberUserCreateMessage {
17 14
18 /** 15 /**
19 * 用户编号 16 * 用户编号
@@ -21,9 +18,4 @@ public class UserCreateMessage extends AbstractStreamMessage { @@ -21,9 +18,4 @@ public class UserCreateMessage extends AbstractStreamMessage {
21 @NotNull(message = "用户编号不能为空") 18 @NotNull(message = "用户编号不能为空")
22 private Long userId; 19 private Long userId;
23 20
24 - @Override  
25 - public String getStreamKey() {  
26 - return "member.create.send";  
27 - }  
28 -  
29 } 21 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/address/AddressApiImpl.java renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/address/MemberAddressApiImpl.java
1 package cn.iocoder.yudao.module.member.api.address; 1 package cn.iocoder.yudao.module.member.api.address;
2 2
3 -import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 3 +import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
4 import cn.iocoder.yudao.module.member.convert.address.AddressConvert; 4 import cn.iocoder.yudao.module.member.convert.address.AddressConvert;
5 import cn.iocoder.yudao.module.member.service.address.AddressService; 5 import cn.iocoder.yudao.module.member.service.address.AddressService;
6 import org.springframework.stereotype.Service; 6 import org.springframework.stereotype.Service;
@@ -15,18 +15,18 @@ import javax.annotation.Resource; @@ -15,18 +15,18 @@ import javax.annotation.Resource;
15 */ 15 */
16 @Service 16 @Service
17 @Validated 17 @Validated
18 -public class AddressApiImpl implements AddressApi { 18 +public class MemberAddressApiImpl implements MemberAddressApi {
19 19
20 @Resource 20 @Resource
21 private AddressService addressService; 21 private AddressService addressService;
22 22
23 @Override 23 @Override
24 - public AddressRespDTO getAddress(Long id, Long userId) { 24 + public MemberAddressRespDTO getAddress(Long id, Long userId) {
25 return AddressConvert.INSTANCE.convert02(addressService.getAddress(userId, id)); 25 return AddressConvert.INSTANCE.convert02(addressService.getAddress(userId, id));
26 } 26 }
27 27
28 @Override 28 @Override
29 - public AddressRespDTO getDefaultAddress(Long userId) { 29 + public MemberAddressRespDTO getDefaultAddress(Long userId) {
30 return AddressConvert.INSTANCE.convert02(addressService.getDefaultUserAddress(userId)); 30 return AddressConvert.INSTANCE.convert02(addressService.getDefaultUserAddress(userId));
31 } 31 }
32 32
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/point/MemberPointRecordController.java
@@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.member.controller.admin.point; @@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.member.controller.admin.point;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 -import cn.iocoder.yudao.module.member.api.user.MemberUserApi;  
6 -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;  
7 import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO; 5 import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO;
8 import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordRespVO; 6 import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordRespVO;
9 import cn.iocoder.yudao.module.member.convert.point.MemberPointRecordConvert; 7 import cn.iocoder.yudao.module.member.convert.point.MemberPointRecordConvert;
10 import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; 8 import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO;
  9 +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
11 import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; 10 import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService;
  11 +import cn.iocoder.yudao.module.member.service.user.MemberUserService;
12 import io.swagger.v3.oas.annotations.Operation; 12 import io.swagger.v3.oas.annotations.Operation;
13 import io.swagger.v3.oas.annotations.tags.Tag; 13 import io.swagger.v3.oas.annotations.tags.Tag;
14 import org.springframework.security.access.prepost.PreAuthorize; 14 import org.springframework.security.access.prepost.PreAuthorize;
@@ -35,7 +35,7 @@ public class MemberPointRecordController { @@ -35,7 +35,7 @@ public class MemberPointRecordController {
35 private MemberPointRecordService pointRecordService; 35 private MemberPointRecordService pointRecordService;
36 36
37 @Resource 37 @Resource
38 - private MemberUserApi memberUserApi; 38 + private MemberUserService memberUserService;
39 39
40 @GetMapping("/page") 40 @GetMapping("/page")
41 @Operation(summary = "获得用户积分记录分页") 41 @Operation(summary = "获得用户积分记录分页")
@@ -48,7 +48,7 @@ public class MemberPointRecordController { @@ -48,7 +48,7 @@ public class MemberPointRecordController {
48 } 48 }
49 49
50 // 拼接结果返回 50 // 拼接结果返回
51 - List<MemberUserRespDTO> users = memberUserApi.getUserList( 51 + List<MemberUserDO> users = memberUserService.getUserList(
52 convertSet(pageResult.getList(), MemberPointRecordDO::getUserId)); 52 convertSet(pageResult.getList(), MemberPointRecordDO::getUserId));
53 return success(MemberPointRecordConvert.INSTANCE.convertPage(pageResult, users)); 53 return success(MemberPointRecordConvert.INSTANCE.convertPage(pageResult, users));
54 } 54 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/MemberSignInRecordController.java
@@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.member.controller.admin.signin; @@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.member.controller.admin.signin;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 -import cn.iocoder.yudao.module.member.api.user.MemberUserApi;  
6 -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;  
7 import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordPageReqVO; 5 import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordPageReqVO;
8 import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO; 6 import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO;
9 import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert; 7 import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert;
10 import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; 8 import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO;
  9 +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
11 import cn.iocoder.yudao.module.member.service.signin.MemberSignInRecordService; 10 import cn.iocoder.yudao.module.member.service.signin.MemberSignInRecordService;
  11 +import cn.iocoder.yudao.module.member.service.user.MemberUserService;
12 import io.swagger.v3.oas.annotations.Operation; 12 import io.swagger.v3.oas.annotations.Operation;
13 import io.swagger.v3.oas.annotations.tags.Tag; 13 import io.swagger.v3.oas.annotations.tags.Tag;
14 import org.springframework.security.access.prepost.PreAuthorize; 14 import org.springframework.security.access.prepost.PreAuthorize;
@@ -35,7 +35,7 @@ public class MemberSignInRecordController { @@ -35,7 +35,7 @@ public class MemberSignInRecordController {
35 private MemberSignInRecordService signInRecordService; 35 private MemberSignInRecordService signInRecordService;
36 36
37 @Resource 37 @Resource
38 - private MemberUserApi memberUserApi; 38 + private MemberUserService memberUserService;
39 39
40 @GetMapping("/page") 40 @GetMapping("/page")
41 @Operation(summary = "获得签到记录分页") 41 @Operation(summary = "获得签到记录分页")
@@ -48,7 +48,7 @@ public class MemberSignInRecordController { @@ -48,7 +48,7 @@ public class MemberSignInRecordController {
48 } 48 }
49 49
50 // 拼接结果返回 50 // 拼接结果返回
51 - List<MemberUserRespDTO> users = memberUserApi.getUserList( 51 + List<MemberUserDO> users = memberUserService.getUserList(
52 convertSet(pageResult.getList(), MemberSignInRecordDO::getUserId)); 52 convertSet(pageResult.getList(), MemberSignInRecordDO::getUserId));
53 return success(MemberSignInRecordConvert.INSTANCE.convertPage(pageResult, users)); 53 return success(MemberSignInRecordConvert.INSTANCE.convertPage(pageResult, users));
54 } 54 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http
@@ -4,7 +4,7 @@ Content-Type: application/json @@ -4,7 +4,7 @@ Content-Type: application/json
4 tenant-id: {{appTenentId}} 4 tenant-id: {{appTenentId}}
5 5
6 { 6 {
7 - "mobile": "15601691300", 7 + "mobile": "15601691388",
8 "password": "admin123" 8 "password": "admin123"
9 } 9 }
10 10
@@ -14,7 +14,7 @@ Content-Type: application/json @@ -14,7 +14,7 @@ Content-Type: application/json
14 tenant-id: {{appTenentId}} 14 tenant-id: {{appTenentId}}
15 15
16 { 16 {
17 - "mobile": "15601691399", 17 + "mobile": "15601691388",
18 "scene": 1 18 "scene": 1
19 } 19 }
20 20
@@ -22,9 +22,10 @@ tenant-id: {{appTenentId}} @@ -22,9 +22,10 @@ tenant-id: {{appTenentId}}
22 POST {{appApi}}/member/auth/sms-login 22 POST {{appApi}}/member/auth/sms-login
23 Content-Type: application/json 23 Content-Type: application/json
24 tenant-id: {{appTenentId}} 24 tenant-id: {{appTenentId}}
  25 +terminal: 30
25 26
26 { 27 {
27 - "mobile": "15601691301", 28 + "mobile": "15601691388",
28 "code": 9999 29 "code": 9999
29 } 30 }
30 31
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java
1 package cn.iocoder.yudao.module.member.convert.address; 1 package cn.iocoder.yudao.module.member.convert.address;
2 2
3 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; 3 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
4 -import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 4 +import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
5 import cn.iocoder.yudao.module.member.controller.admin.address.vo.AddressRespVO; 5 import cn.iocoder.yudao.module.member.controller.admin.address.vo.AddressRespVO;
6 import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; 6 import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO;
7 import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO; 7 import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO;
@@ -33,7 +33,7 @@ public interface AddressConvert { @@ -33,7 +33,7 @@ public interface AddressConvert {
33 33
34 List<AppAddressRespVO> convertList(List<MemberAddressDO> list); 34 List<AppAddressRespVO> convertList(List<MemberAddressDO> list);
35 35
36 - AddressRespDTO convert02(MemberAddressDO bean); 36 + MemberAddressRespDTO convert02(MemberAddressDO bean);
37 37
38 @Named("convertAreaIdToAreaName") 38 @Named("convertAreaIdToAreaName")
39 default String convertAreaIdToAreaName(Integer areaId) { 39 default String convertAreaIdToAreaName(Integer areaId) {
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/point/MemberPointRecordConvert.java
@@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.member.convert.point; @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.member.convert.point;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.common.util.collection.MapUtils; 4 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
5 -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;  
6 import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordRespVO; 5 import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordRespVO;
7 import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordRespVO; 6 import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordRespVO;
8 import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; 7 import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO;
  8 +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
9 import org.mapstruct.Mapper; 9 import org.mapstruct.Mapper;
10 import org.mapstruct.factory.Mappers; 10 import org.mapstruct.factory.Mappers;
11 11
@@ -24,10 +24,10 @@ public interface MemberPointRecordConvert { @@ -24,10 +24,10 @@ public interface MemberPointRecordConvert {
24 24
25 MemberPointRecordConvert INSTANCE = Mappers.getMapper(MemberPointRecordConvert.class); 25 MemberPointRecordConvert INSTANCE = Mappers.getMapper(MemberPointRecordConvert.class);
26 26
27 - default PageResult<MemberPointRecordRespVO> convertPage(PageResult<MemberPointRecordDO> pageResult, List<MemberUserRespDTO> users) { 27 + default PageResult<MemberPointRecordRespVO> convertPage(PageResult<MemberPointRecordDO> pageResult, List<MemberUserDO> users) {
28 PageResult<MemberPointRecordRespVO> voPageResult = convertPage(pageResult); 28 PageResult<MemberPointRecordRespVO> voPageResult = convertPage(pageResult);
29 // user 拼接 29 // user 拼接
30 - Map<Long, MemberUserRespDTO> userMap = convertMap(users, MemberUserRespDTO::getId); 30 + Map<Long, MemberUserDO> userMap = convertMap(users, MemberUserDO::getId);
31 voPageResult.getList().forEach(record -> MapUtils.findAndThen(userMap, record.getUserId(), 31 voPageResult.getList().forEach(record -> MapUtils.findAndThen(userMap, record.getUserId(),
32 memberUserRespDTO -> record.setNickname(memberUserRespDTO.getNickname()))); 32 memberUserRespDTO -> record.setNickname(memberUserRespDTO.getNickname())));
33 return voPageResult; 33 return voPageResult;
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInRecordConvert.java
@@ -4,11 +4,11 @@ import cn.hutool.core.collection.CollUtil; @@ -4,11 +4,11 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjUtil; 4 import cn.hutool.core.util.ObjUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.common.util.collection.MapUtils; 6 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
7 -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;  
8 import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO; 7 import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO;
9 import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO; 8 import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO;
10 import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; 9 import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO;
11 import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; 10 import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO;
  11 +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
12 import org.mapstruct.Mapper; 12 import org.mapstruct.Mapper;
13 import org.mapstruct.factory.Mappers; 13 import org.mapstruct.factory.Mappers;
14 14
@@ -28,10 +28,10 @@ public interface MemberSignInRecordConvert { @@ -28,10 +28,10 @@ public interface MemberSignInRecordConvert {
28 28
29 MemberSignInRecordConvert INSTANCE = Mappers.getMapper(MemberSignInRecordConvert.class); 29 MemberSignInRecordConvert INSTANCE = Mappers.getMapper(MemberSignInRecordConvert.class);
30 30
31 - default PageResult<MemberSignInRecordRespVO> convertPage(PageResult<MemberSignInRecordDO> pageResult, List<MemberUserRespDTO> users) { 31 + default PageResult<MemberSignInRecordRespVO> convertPage(PageResult<MemberSignInRecordDO> pageResult, List<MemberUserDO> users) {
32 PageResult<MemberSignInRecordRespVO> voPageResult = convertPage(pageResult); 32 PageResult<MemberSignInRecordRespVO> voPageResult = convertPage(pageResult);
33 // user 拼接 33 // user 拼接
34 - Map<Long, MemberUserRespDTO> userMap = convertMap(users, MemberUserRespDTO::getId); 34 + Map<Long, MemberUserDO> userMap = convertMap(users, MemberUserDO::getId);
35 voPageResult.getList().forEach(record -> MapUtils.findAndThen(userMap, record.getUserId(), 35 voPageResult.getList().forEach(record -> MapUtils.findAndThen(userMap, record.getUserId(),
36 memberUserRespDTO -> record.setNickname(memberUserRespDTO.getNickname()))); 36 memberUserRespDTO -> record.setNickname(memberUserRespDTO.getNickname())));
37 return voPageResult; 37 return voPageResult;
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/consumer/package-info.java 0 → 100644
  1 +/**
  2 + * 消息队列的消费者
  3 + */
  4 +package cn.iocoder.yudao.module.member.mq.consumer;
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/message/package-info.java 0 → 100644
  1 +/**
  2 + * 消息队列的消息
  3 + */
  4 +package cn.iocoder.yudao.module.member.mq.message;
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/message/user/UserCreateMessage.java deleted
1 -package cn.iocoder.yudao.module.member.mq.message.user;  
2 -  
3 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;  
4 -import lombok.Data;  
5 -import lombok.EqualsAndHashCode;  
6 -  
7 -import javax.validation.constraints.NotNull;  
8 -  
9 -/**  
10 - * 会员用户创建消息  
11 - *  
12 - * @author owen  
13 - */  
14 -@Data  
15 -@EqualsAndHashCode(callSuper = true)  
16 -public class UserCreateMessage extends AbstractStreamMessage {  
17 -  
18 - /**  
19 - * 用户编号  
20 - */  
21 - @NotNull(message = "用户编号不能为空")  
22 - private Long userId;  
23 -  
24 - @Override  
25 - public String getStreamKey() {  
26 - return "member.create.send";  
27 - }  
28 -  
29 -}  
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/package-info.java 0 → 100644
  1 +/**
  2 + * 消息队列的生产者
  3 + */
  4 +package cn.iocoder.yudao.module.member.mq.producer;
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/user/UserCreateProducer.java renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/user/MemberUserProducer.java
1 package cn.iocoder.yudao.module.member.mq.producer.user; 1 package cn.iocoder.yudao.module.member.mq.producer.user;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;  
4 -import cn.iocoder.yudao.module.member.mq.message.user.UserCreateMessage; 3 +import cn.iocoder.yudao.module.member.message.user.MemberUserCreateMessage;
5 import lombok.extern.slf4j.Slf4j; 4 import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.context.ApplicationContext;
6 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
7 7
8 import javax.annotation.Resource; 8 import javax.annotation.Resource;
9 9
10 /** 10 /**
11 - * 会员用户创建 Producer 11 + * 会员用户 Producer
12 * 12 *
13 * @author owen 13 * @author owen
14 */ 14 */
15 @Slf4j 15 @Slf4j
16 @Component 16 @Component
17 -public class UserCreateProducer { 17 +public class MemberUserProducer {
18 18
19 @Resource 19 @Resource
20 - private RedisMQTemplate redisMQTemplate; 20 + private ApplicationContext applicationContext;
21 21
22 /** 22 /**
23 - * 发送 {@link UserCreateMessage} 消息 23 + * 发送 {@link MemberUserCreateMessage} 消息
24 * 24 *
25 * @param userId 用户编号 25 * @param userId 用户编号
26 */ 26 */
27 public void sendUserCreateMessage(Long userId) { 27 public void sendUserCreateMessage(Long userId) {
28 - redisMQTemplate.send(new UserCreateMessage().setUserId(userId)); 28 + applicationContext.publishEvent(new MemberUserCreateMessage().setUserId(userId));
29 } 29 }
30 30
31 } 31 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java
@@ -7,18 +7,18 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; @@ -7,18 +7,18 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 import cn.iocoder.yudao.framework.common.util.date.DateUtils; 8 import cn.iocoder.yudao.framework.common.util.date.DateUtils;
9 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 9 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
10 -import cn.iocoder.yudao.module.member.api.user.MemberUserApi;  
11 -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;  
12 import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordPageReqVO; 10 import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordPageReqVO;
13 import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordSummaryRespVO; 11 import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordSummaryRespVO;
14 import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert; 12 import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert;
15 import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; 13 import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO;
16 import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; 14 import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO;
  15 +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
17 import cn.iocoder.yudao.module.member.dal.mysql.signin.MemberSignInRecordMapper; 16 import cn.iocoder.yudao.module.member.dal.mysql.signin.MemberSignInRecordMapper;
18 import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; 17 import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
19 import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; 18 import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
20 import cn.iocoder.yudao.module.member.service.level.MemberLevelService; 19 import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
21 import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; 20 import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService;
  21 +import cn.iocoder.yudao.module.member.service.user.MemberUserService;
22 import org.apache.commons.lang3.StringUtils; 22 import org.apache.commons.lang3.StringUtils;
23 import org.springframework.stereotype.Service; 23 import org.springframework.stereotype.Service;
24 import org.springframework.transaction.annotation.Transactional; 24 import org.springframework.transaction.annotation.Transactional;
@@ -53,7 +53,7 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService @@ -53,7 +53,7 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService
53 private MemberLevelService memberLevelService; 53 private MemberLevelService memberLevelService;
54 54
55 @Resource 55 @Resource
56 - private MemberUserApi memberUserApi; 56 + private MemberUserService memberUserService;
57 57
58 @Override 58 @Override
59 public AppMemberSignInRecordSummaryRespVO getSignInRecordSummary(Long userId) { 59 public AppMemberSignInRecordSummaryRespVO getSignInRecordSummary(Long userId) {
@@ -126,12 +126,12 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService @@ -126,12 +126,12 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService
126 // 根据用户昵称查询出用户ids 126 // 根据用户昵称查询出用户ids
127 Set<Long> userIds = null; 127 Set<Long> userIds = null;
128 if (StringUtils.isNotBlank(pageReqVO.getNickname())) { 128 if (StringUtils.isNotBlank(pageReqVO.getNickname())) {
129 - List<MemberUserRespDTO> users = memberUserApi.getUserListByNickname(pageReqVO.getNickname()); 129 + List<MemberUserDO> users = memberUserService.getUserListByNickname(pageReqVO.getNickname());
130 // 如果查询用户结果为空直接返回无需继续查询 130 // 如果查询用户结果为空直接返回无需继续查询
131 if (CollUtil.isEmpty(users)) { 131 if (CollUtil.isEmpty(users)) {
132 return PageResult.empty(); 132 return PageResult.empty();
133 } 133 }
134 - userIds = convertSet(users, MemberUserRespDTO::getId); 134 + userIds = convertSet(users, MemberUserDO::getId);
135 } 135 }
136 // 分页查询 136 // 分页查询
137 return signInRecordMapper.selectPage(pageReqVO, userIds); 137 return signInRecordMapper.selectPage(pageReqVO, userIds);
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
@@ -7,7 +7,6 @@ import cn.hutool.core.util.ObjectUtil; @@ -7,7 +7,6 @@ import cn.hutool.core.util.ObjectUtil;
7 import cn.hutool.core.util.StrUtil; 7 import cn.hutool.core.util.StrUtil;
8 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 8 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
9 import cn.iocoder.yudao.framework.common.pojo.PageResult; 9 import cn.iocoder.yudao.framework.common.pojo.PageResult;
10 -import cn.iocoder.yudao.module.infra.api.file.FileApi;  
11 import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO; 10 import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO;
12 import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO; 11 import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
13 import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserResetPasswordReqVO; 12 import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserResetPasswordReqVO;
@@ -18,7 +17,7 @@ import cn.iocoder.yudao.module.member.convert.auth.AuthConvert; @@ -18,7 +17,7 @@ import cn.iocoder.yudao.module.member.convert.auth.AuthConvert;
18 import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; 17 import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert;
19 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; 18 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
20 import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; 19 import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
21 -import cn.iocoder.yudao.module.member.mq.producer.user.UserCreateProducer; 20 +import cn.iocoder.yudao.module.member.mq.producer.user.MemberUserProducer;
22 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; 21 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
23 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; 22 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
24 import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; 23 import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
@@ -29,7 +28,6 @@ import org.springframework.stereotype.Service; @@ -29,7 +28,6 @@ import org.springframework.stereotype.Service;
29 import org.springframework.transaction.annotation.Transactional; 28 import org.springframework.transaction.annotation.Transactional;
30 import org.springframework.transaction.support.TransactionSynchronization; 29 import org.springframework.transaction.support.TransactionSynchronization;
31 import org.springframework.transaction.support.TransactionSynchronizationManager; 30 import org.springframework.transaction.support.TransactionSynchronizationManager;
32 -import org.springframework.transaction.support.TransactionTemplate;  
33 31
34 import javax.annotation.Resource; 32 import javax.annotation.Resource;
35 import javax.validation.Valid; 33 import javax.validation.Valid;
@@ -55,18 +53,13 @@ public class MemberUserServiceImpl implements MemberUserService { @@ -55,18 +53,13 @@ public class MemberUserServiceImpl implements MemberUserService {
55 private MemberUserMapper memberUserMapper; 53 private MemberUserMapper memberUserMapper;
56 54
57 @Resource 55 @Resource
58 - private FileApi fileApi;  
59 - @Resource  
60 private SmsCodeApi smsCodeApi; 56 private SmsCodeApi smsCodeApi;
61 57
62 @Resource 58 @Resource
63 private PasswordEncoder passwordEncoder; 59 private PasswordEncoder passwordEncoder;
64 60
65 @Resource 61 @Resource
66 - private UserCreateProducer registerCouponProducer;  
67 -  
68 - @Resource  
69 - private TransactionTemplate transactionTemplate; 62 + private MemberUserProducer memberUserProducer;
70 63
71 @Override 64 @Override
72 public MemberUserDO getUserByMobile(String mobile) { 65 public MemberUserDO getUserByMobile(String mobile) {
@@ -107,7 +100,7 @@ public class MemberUserServiceImpl implements MemberUserService { @@ -107,7 +100,7 @@ public class MemberUserServiceImpl implements MemberUserService {
107 100
108 @Override 101 @Override
109 public void afterCommit() { 102 public void afterCommit() {
110 - registerCouponProducer.sendUserCreateMessage(user.getId()); 103 + memberUserProducer.sendUserCreateMessage(user.getId());
111 } 104 }
112 105
113 }); 106 });
yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java renamed to yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/MemberAddressServiceImplTest.java
@@ -24,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertNull; @@ -24,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
24 * @author 芋道源码 24 * @author 芋道源码
25 */ 25 */
26 @Import(AddressServiceImpl.class) 26 @Import(AddressServiceImpl.class)
27 -public class AddressServiceImplTest extends BaseDbUnitTest { 27 +public class MemberAddressServiceImplTest extends BaseDbUnitTest {
28 28
29 @Resource 29 @Resource
30 private AddressServiceImpl addressService; 30 private AddressServiceImpl addressService;
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java
@@ -11,6 +11,8 @@ import javax.validation.constraints.NotNull; @@ -11,6 +11,8 @@ import javax.validation.constraints.NotNull;
11 import java.util.Map; 11 import java.util.Map;
12 12
13 /** 13 /**
  14 + * 转账单创建 Request DTO
  15 + *
14 * @author jason 16 * @author jason
15 */ 17 */
16 @Data 18 @Data
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/PayWalletBizTypeEnum.java renamed to yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/wallet/PayWalletBizTypeEnum.java
1 -package cn.iocoder.yudao.module.pay.enums.member; 1 +package cn.iocoder.yudao.module.pay.enums.wallet;
2 2
3 import cn.iocoder.yudao.framework.common.core.IntArrayValuable; 3 import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
4 import lombok.AllArgsConstructor; 4 import lombok.AllArgsConstructor;
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/package-info.java deleted
1 -package cn.iocoder.yudao.module.pay;  
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/PayWalletController.java
@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollectionUtil; @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollectionUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
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.collection.CollectionUtils;  
8 import cn.iocoder.yudao.module.member.api.user.MemberUserApi; 7 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
9 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 8 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
10 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletPageReqVO; 9 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletPageReqVO;
@@ -26,12 +25,10 @@ import javax.annotation.Resource; @@ -26,12 +25,10 @@ import javax.annotation.Resource;
26 import javax.validation.Valid; 25 import javax.validation.Valid;
27 import java.util.List; 26 import java.util.List;
28 import java.util.Map; 27 import java.util.Map;
29 -import java.util.Set;  
30 28
31 import static cn.iocoder.yudao.framework.common.enums.UserTypeEnum.MEMBER; 29 import static cn.iocoder.yudao.framework.common.enums.UserTypeEnum.MEMBER;
32 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 30 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
33 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;  
34 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; 31 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
35 32
36 @Tag(name = "管理后台 - 用户钱包") 33 @Tag(name = "管理后台 - 用户钱包")
37 @RestController 34 @RestController
@@ -50,6 +47,7 @@ public class PayWalletController { @@ -50,6 +47,7 @@ public class PayWalletController {
50 @Operation(summary = "获得用户钱包明细") 47 @Operation(summary = "获得用户钱包明细")
51 public CommonResult<PayWalletRespVO> getWallet(PayWalletUserReqVO reqVO) { 48 public CommonResult<PayWalletRespVO> getWallet(PayWalletUserReqVO reqVO) {
52 PayWalletDO wallet = payWalletService.getOrCreateWallet(reqVO.getUserId(), MEMBER.getValue()); 49 PayWalletDO wallet = payWalletService.getOrCreateWallet(reqVO.getUserId(), MEMBER.getValue());
  50 + // TODO jason:如果为空,返回给前端只要 null 就可以了
53 MemberUserRespDTO memberUser = memberUserApi.getUser(reqVO.getUserId()); 51 MemberUserRespDTO memberUser = memberUserApi.getUser(reqVO.getUserId());
54 String nickname = memberUser == null ? "" : memberUser.getNickname(); 52 String nickname = memberUser == null ? "" : memberUser.getNickname();
55 String avatar = memberUser == null ? "" : memberUser.getAvatar(); 53 String avatar = memberUser == null ? "" : memberUser.getAvatar();
@@ -61,9 +59,8 @@ public class PayWalletController { @@ -61,9 +59,8 @@ public class PayWalletController {
61 @PreAuthorize("@ss.hasPermission('pay:wallet:query')") 59 @PreAuthorize("@ss.hasPermission('pay:wallet:query')")
62 public CommonResult<PageResult<PayWalletRespVO>> getWalletPage(@Valid PayWalletPageReqVO pageVO) { 60 public CommonResult<PageResult<PayWalletRespVO>> getWalletPage(@Valid PayWalletPageReqVO pageVO) {
63 if (StrUtil.isNotEmpty(pageVO.getNickname())) { 61 if (StrUtil.isNotEmpty(pageVO.getNickname())) {
64 - Set<Long> userIds = CollectionUtils.convertSet(memberUserApi.getUserListByNickname(pageVO.getNickname()),  
65 - MemberUserRespDTO::getId);  
66 - pageVO.setUserIds(userIds); 62 + List<MemberUserRespDTO> users = memberUserApi.getUserListByNickname(pageVO.getNickname());
  63 + pageVO.setUserIds(convertSet(users, MemberUserRespDTO::getId));
67 } 64 }
68 // TODO @jason:管理员也可以先查询下。。 65 // TODO @jason:管理员也可以先查询下。。
69 // 暂时支持查询 userType 会员类型。管理员类型还不知道使用场景 66 // 暂时支持查询 userType 会员类型。管理员类型还不知道使用场景
@@ -71,8 +68,8 @@ public class PayWalletController { @@ -71,8 +68,8 @@ public class PayWalletController {
71 if (CollectionUtil.isEmpty(pageResult.getList())) { 68 if (CollectionUtil.isEmpty(pageResult.getList())) {
72 return success(new PageResult<>(pageResult.getTotal())); 69 return success(new PageResult<>(pageResult.getTotal()));
73 } 70 }
74 - List<Long> userIds = convertList(pageResult.getList(), PayWalletDO::getUserId);  
75 - Map<Long, MemberUserRespDTO> userMap = convertMap(memberUserApi.getUserList(userIds),MemberUserRespDTO::getId); 71 + List<MemberUserRespDTO> users = memberUserApi.getUserList(convertList(pageResult.getList(), PayWalletDO::getUserId));
  72 + Map<Long, MemberUserRespDTO> userMap = convertMap(users, MemberUserRespDTO::getId);
76 return success(PayWalletConvert.INSTANCE.convertPage(pageResult, userMap)); 73 return success(PayWalletConvert.INSTANCE.convertPage(pageResult, userMap));
77 } 74 }
78 75
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletTransactionDO.java
1 package cn.iocoder.yudao.module.pay.dal.dataobject.wallet; 1 package cn.iocoder.yudao.module.pay.dal.dataobject.wallet;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 -import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; 4 +import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
5 import com.baomidou.mybatisplus.annotation.KeySequence; 5 import com.baomidou.mybatisplus.annotation.KeySequence;
6 import com.baomidou.mybatisplus.annotation.TableId; 6 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 7 import com.baomidou.mybatisplus.annotation.TableName;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/WalletPayClient.java
@@ -17,7 +17,7 @@ import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; @@ -17,7 +17,7 @@ import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
17 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; 17 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
18 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; 18 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
19 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; 19 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
20 -import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; 20 +import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
21 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 21 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
22 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 22 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
23 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; 23 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
@@ -421,6 +421,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -421,6 +421,7 @@ public class PayOrderServiceImpl implements PayOrderService {
421 return; 421 return;
422 } 422 }
423 423
  424 + // TODO 芋艿:应该 new 出来更新
424 order.setPrice(payPrice); 425 order.setPrice(payPrice);
425 orderMapper.updateById(order); 426 orderMapper.updateById(order);
426 } 427 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java
@@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; @@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
11 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO; 11 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO;
12 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargePackageDO; 12 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargePackageDO;
13 import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletRechargeMapper; 13 import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletRechargeMapper;
14 -import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; 14 +import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
15 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 15 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
16 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; 16 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
17 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 17 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
@@ -64,6 +64,7 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { @@ -64,6 +64,7 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
64 @Transactional(rollbackFor = Exception.class) 64 @Transactional(rollbackFor = Exception.class)
65 public PayWalletRechargeDO createWalletRecharge(Long userId, Integer userType, String userIp, 65 public PayWalletRechargeDO createWalletRecharge(Long userId, Integer userType, String userIp,
66 AppPayWalletRechargeCreateReqVO reqVO) { 66 AppPayWalletRechargeCreateReqVO reqVO) {
  67 +
67 // 1.1 计算充值金额 68 // 1.1 计算充值金额
68 int payPrice; 69 int payPrice;
69 int bonusPrice = 0; 70 int bonusPrice = 0;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletPageReqVO; 4 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.wallet.PayWalletPageReqVO;
5 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; 5 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
6 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; 6 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
7 -import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; 7 +import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
8 8
9 /** 9 /**
10 * 钱包 Service 接口 10 * 钱包 Service 接口
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
@@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; @@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
8 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; 8 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
9 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; 9 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
10 import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper; 10 import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper;
11 -import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; 11 +import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
12 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 12 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
13 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; 13 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
14 import cn.iocoder.yudao.module.pay.service.wallet.bo.WalletTransactionCreateReqBO; 14 import cn.iocoder.yudao.module.pay.service.wallet.bo.WalletTransactionCreateReqBO;
@@ -22,8 +22,8 @@ import java.time.LocalDateTime; @@ -22,8 +22,8 @@ import java.time.LocalDateTime;
22 22
23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
24 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; 24 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
25 -import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT;  
26 -import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT_REFUND; 25 +import static cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum.PAYMENT;
  26 +import static cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum.PAYMENT_REFUND;
27 27
28 /** 28 /**
29 * 钱包 Service 实现类 29 * 钱包 Service 实现类
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.transaction.PayWalletTransactionPageReqVO; 4 import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.transaction.PayWalletTransactionPageReqVO;
5 import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; 5 import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO;
6 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; 6 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
7 -import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; 7 +import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
8 import cn.iocoder.yudao.module.pay.service.wallet.bo.WalletTransactionCreateReqBO; 8 import cn.iocoder.yudao.module.pay.service.wallet.bo.WalletTransactionCreateReqBO;
9 9
10 import javax.validation.Valid; 10 import javax.validation.Valid;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java
@@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; @@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
8 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; 8 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
9 import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletTransactionMapper; 9 import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletTransactionMapper;
10 import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; 10 import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
11 -import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; 11 +import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
12 import cn.iocoder.yudao.module.pay.service.wallet.bo.WalletTransactionCreateReqBO; 12 import cn.iocoder.yudao.module.pay.service.wallet.bo.WalletTransactionCreateReqBO;
13 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
14 import org.springframework.stereotype.Service; 14 import org.springframework.stereotype.Service;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/bo/WalletTransactionCreateReqBO.java
1 package cn.iocoder.yudao.module.pay.service.wallet.bo; 1 package cn.iocoder.yudao.module.pay.service.wallet.bo;
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.module.pay.enums.member.PayWalletBizTypeEnum; 4 +import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
5 import lombok.Data; 5 import lombok.Data;
6 6
7 import javax.validation.constraints.NotEmpty; 7 import javax.validation.constraints.NotEmpty;
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.pay.service.order; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.pay.service.order;
3 import cn.hutool.extra.spring.SpringUtil; 3 import cn.hutool.extra.spring.SpringUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 5 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
6 -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;  
7 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; 6 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
8 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; 7 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
9 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; 8 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
@@ -68,8 +67,6 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -68,8 +67,6 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
68 private PayOrderExtensionMapper orderExtensionMapper; 67 private PayOrderExtensionMapper orderExtensionMapper;
69 68
70 @MockBean 69 @MockBean
71 - private PayClientFactory payClientFactory;  
72 - @MockBean  
73 private PayProperties properties; 70 private PayProperties properties;
74 @MockBean 71 @MockBean
75 private PayAppService appService; 72 private PayAppService appService;
@@ -351,7 +348,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -351,7 +348,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
351 .thenReturn(channel); 348 .thenReturn(channel);
352 // mock 方法(client) 349 // mock 方法(client)
353 PayClient client = mock(PayClient.class); 350 PayClient client = mock(PayClient.class);
354 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 351 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
355 // mock 方法() 352 // mock 方法()
356 PayOrderRespDTO unifiedOrderResp = randomPojo(PayOrderRespDTO.class, o -> 353 PayOrderRespDTO unifiedOrderResp = randomPojo(PayOrderRespDTO.class, o ->
357 o.setChannelErrorCode("001").setChannelErrorMsg("模拟异常")); 354 o.setChannelErrorCode("001").setChannelErrorMsg("模拟异常"));
@@ -405,7 +402,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -405,7 +402,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
405 .thenReturn(channel); 402 .thenReturn(channel);
406 // mock 方法(client) 403 // mock 方法(client)
407 PayClient client = mock(PayClient.class); 404 PayClient client = mock(PayClient.class);
408 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 405 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
409 // mock 方法(支付渠道的调用) 406 // mock 方法(支付渠道的调用)
410 PayOrderRespDTO unifiedOrderResp = randomPojo(PayOrderRespDTO.class, o -> o.setChannelErrorCode(null).setChannelErrorMsg(null) 407 PayOrderRespDTO unifiedOrderResp = randomPojo(PayOrderRespDTO.class, o -> o.setChannelErrorCode(null).setChannelErrorMsg(null)
411 .setDisplayMode(PayOrderDisplayModeEnum.URL.getMode()).setDisplayContent("tudou")); 408 .setDisplayMode(PayOrderDisplayModeEnum.URL.getMode()).setDisplayContent("tudou"));
@@ -463,7 +460,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -463,7 +460,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
463 orderExtensionMapper.insert(orderExtension); 460 orderExtensionMapper.insert(orderExtension);
464 // mock 方法(PayClient 已支付) 461 // mock 方法(PayClient 已支付)
465 PayClient client = mock(PayClient.class); 462 PayClient client = mock(PayClient.class);
466 - when(payClientFactory.getPayClient(eq(orderExtension.getChannelId()))).thenReturn(client); 463 + when(channelService.getPayClient(eq(orderExtension.getChannelId()))).thenReturn(client);
467 when(client.getOrder(eq(orderExtension.getNo()))).thenReturn(randomPojo(PayOrderRespDTO.class, 464 when(client.getOrder(eq(orderExtension.getNo()))).thenReturn(randomPojo(PayOrderRespDTO.class,
468 o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()))); 465 o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus())));
469 466
@@ -482,7 +479,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -482,7 +479,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
482 orderExtensionMapper.insert(orderExtension); 479 orderExtensionMapper.insert(orderExtension);
483 // mock 方法(PayClient 已支付) 480 // mock 方法(PayClient 已支付)
484 PayClient client = mock(PayClient.class); 481 PayClient client = mock(PayClient.class);
485 - when(payClientFactory.getPayClient(eq(orderExtension.getChannelId()))).thenReturn(client); 482 + when(channelService.getPayClient(eq(orderExtension.getChannelId()))).thenReturn(client);
486 when(client.getOrder(eq(orderExtension.getNo()))).thenReturn(randomPojo(PayOrderRespDTO.class, 483 when(client.getOrder(eq(orderExtension.getNo()))).thenReturn(randomPojo(PayOrderRespDTO.class,
487 o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus()))); 484 o -> o.setStatus(PayOrderStatusEnum.WAITING.getStatus())));
488 485
@@ -639,7 +636,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -639,7 +636,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
639 orderExtensionMapper.insert(orderExtension); 636 orderExtensionMapper.insert(orderExtension);
640 // 准备参数 637 // 准备参数
641 PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L) 638 PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)
642 - .setFeeRate(0.1D)); 639 + .setFeeRate(10D));
643 PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class, 640 PayOrderRespDTO notify = randomPojo(PayOrderRespDTO.class,
644 o -> o.setStatus(PayOrderStatusRespEnum.SUCCESS.getStatus()) 641 o -> o.setStatus(PayOrderStatusRespEnum.SUCCESS.getStatus())
645 .setOutTradeNo("P110")); 642 .setOutTradeNo("P110"));
@@ -656,7 +653,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -656,7 +653,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
656 .setChannelId(10L).setChannelCode(channel.getCode()) 653 .setChannelId(10L).setChannelCode(channel.getCode())
657 .setSuccessTime(notify.getSuccessTime()).setExtensionId(orderExtension.getId()).setNo(orderExtension.getNo()) 654 .setSuccessTime(notify.getSuccessTime()).setExtensionId(orderExtension.getId()).setNo(orderExtension.getNo())
658 .setChannelOrderNo(notify.getChannelOrderNo()).setChannelUserId(notify.getChannelUserId()) 655 .setChannelOrderNo(notify.getChannelOrderNo()).setChannelUserId(notify.getChannelUserId())
659 - .setChannelFeeRate(0.1D).setChannelFeePrice(1); 656 + .setChannelFeeRate(10D).setChannelFeePrice(1);
660 assertPojoEquals(order, orderMapper.selectOne(null), 657 assertPojoEquals(order, orderMapper.selectOne(null),
661 "updateTime", "updater"); 658 "updateTime", "updater");
662 // 断言,调用 659 // 断言,调用
@@ -874,7 +871,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -874,7 +871,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
874 orderExtensionMapper.insert(orderExtension); 871 orderExtensionMapper.insert(orderExtension);
875 // mock 方法(PayClient) 872 // mock 方法(PayClient)
876 PayClient client = mock(PayClient.class); 873 PayClient client = mock(PayClient.class);
877 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 874 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
878 // mock 方法(PayClient 异常) 875 // mock 方法(PayClient 异常)
879 when(client.getOrder(any())).thenThrow(new RuntimeException()); 876 when(client.getOrder(any())).thenThrow(new RuntimeException());
880 877
@@ -901,7 +898,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -901,7 +898,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
901 orderExtensionMapper.insert(orderExtension); 898 orderExtensionMapper.insert(orderExtension);
902 // mock 方法(PayClient) 899 // mock 方法(PayClient)
903 PayClient client = mock(PayClient.class); 900 PayClient client = mock(PayClient.class);
904 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 901 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
905 // mock 方法(PayClient 成功返回) 902 // mock 方法(PayClient 成功返回)
906 PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class, 903 PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class,
907 o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus())); 904 o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()));
@@ -935,7 +932,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -935,7 +932,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
935 orderExtensionMapper.insert(orderExtension); 932 orderExtensionMapper.insert(orderExtension);
936 // mock 方法(PayClient) 933 // mock 方法(PayClient)
937 PayClient client = mock(PayClient.class); 934 PayClient client = mock(PayClient.class);
938 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 935 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
939 // mock 方法(PayClient 成功返回) 936 // mock 方法(PayClient 成功返回)
940 PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class, 937 PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class,
941 o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus())); 938 o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()));
@@ -966,7 +963,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -966,7 +963,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
966 orderExtensionMapper.insert(orderExtension); 963 orderExtensionMapper.insert(orderExtension);
967 // mock 方法(PayClient) 964 // mock 方法(PayClient)
968 PayClient client = mock(PayClient.class); 965 PayClient client = mock(PayClient.class);
969 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 966 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
970 967
971 // 调用 968 // 调用
972 int count = orderService.expireOrder(); 969 int count = orderService.expireOrder();
@@ -1013,7 +1010,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -1013,7 +1010,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
1013 orderExtensionMapper.insert(orderExtension); 1010 orderExtensionMapper.insert(orderExtension);
1014 // mock 方法(PayClient) 1011 // mock 方法(PayClient)
1015 PayClient client = mock(PayClient.class); 1012 PayClient client = mock(PayClient.class);
1016 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 1013 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
1017 // mock 方法(PayClient 退款返回) 1014 // mock 方法(PayClient 退款返回)
1018 PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class, 1015 PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class,
1019 o -> o.setStatus(PayOrderStatusEnum.REFUND.getStatus())); 1016 o -> o.setStatus(PayOrderStatusEnum.REFUND.getStatus()));
@@ -1047,7 +1044,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -1047,7 +1044,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
1047 orderExtensionMapper.insert(orderExtension); 1044 orderExtensionMapper.insert(orderExtension);
1048 // mock 方法(PayClient) 1045 // mock 方法(PayClient)
1049 PayClient client = mock(PayClient.class); 1046 PayClient client = mock(PayClient.class);
1050 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 1047 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
1051 // mock 方法(PayClient 成功返回) 1048 // mock 方法(PayClient 成功返回)
1052 PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class, 1049 PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class,
1053 o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus())); 1050 o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()));
@@ -1081,7 +1078,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { @@ -1081,7 +1078,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
1081 orderExtensionMapper.insert(orderExtension); 1078 orderExtensionMapper.insert(orderExtension);
1082 // mock 方法(PayClient) 1079 // mock 方法(PayClient)
1083 PayClient client = mock(PayClient.class); 1080 PayClient client = mock(PayClient.class);
1084 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 1081 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
1085 // mock 方法(PayClient 关闭返回) 1082 // mock 方法(PayClient 关闭返回)
1086 PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class, 1083 PayOrderRespDTO respDTO = randomPojo(PayOrderRespDTO.class,
1087 o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus())); 1084 o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus()));
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.pay.service.refund; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.pay.service.refund;
3 import cn.hutool.extra.spring.SpringUtil; 3 import cn.hutool.extra.spring.SpringUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 5 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
6 -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;  
7 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; 6 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
8 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; 7 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
9 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; 8 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
@@ -67,8 +66,6 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { @@ -67,8 +66,6 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
67 @MockBean 66 @MockBean
68 private PayProperties payProperties; 67 private PayProperties payProperties;
69 @MockBean 68 @MockBean
70 - private PayClientFactory payClientFactory;  
71 - @MockBean  
72 private PayOrderService orderService; 69 private PayOrderService orderService;
73 @MockBean 70 @MockBean
74 private PayAppService appService; 71 private PayAppService appService;
@@ -335,7 +332,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { @@ -335,7 +332,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
335 when(channelService.validPayChannel(eq(1L))).thenReturn(channel); 332 when(channelService.validPayChannel(eq(1L))).thenReturn(channel);
336 // mock 方法(client) 333 // mock 方法(client)
337 PayClient client = mock(PayClient.class); 334 PayClient client = mock(PayClient.class);
338 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 335 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
339 // mock 数据(refund 已存在) 336 // mock 数据(refund 已存在)
340 PayRefundDO refund = randomPojo(PayRefundDO.class, o -> 337 PayRefundDO refund = randomPojo(PayRefundDO.class, o ->
341 o.setAppId(1L).setMerchantRefundId("200")); 338 o.setAppId(1L).setMerchantRefundId("200"));
@@ -367,7 +364,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { @@ -367,7 +364,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
367 when(channelService.validPayChannel(eq(10L))).thenReturn(channel); 364 when(channelService.validPayChannel(eq(10L))).thenReturn(channel);
368 // mock 方法(client) 365 // mock 方法(client)
369 PayClient client = mock(PayClient.class); 366 PayClient client = mock(PayClient.class);
370 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 367 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
371 // mock 方法(client 调用发生异常) 368 // mock 方法(client 调用发生异常)
372 when(client.unifiedRefund(any(PayRefundUnifiedReqDTO.class))).thenThrow(new RuntimeException()); 369 when(client.unifiedRefund(any(PayRefundUnifiedReqDTO.class))).thenThrow(new RuntimeException());
373 370
@@ -411,7 +408,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { @@ -411,7 +408,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
411 when(channelService.validPayChannel(eq(10L))).thenReturn(channel); 408 when(channelService.validPayChannel(eq(10L))).thenReturn(channel);
412 // mock 方法(client) 409 // mock 方法(client)
413 PayClient client = mock(PayClient.class); 410 PayClient client = mock(PayClient.class);
414 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 411 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
415 // mock 方法(client 成功) 412 // mock 方法(client 成功)
416 PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class); 413 PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class);
417 when(client.unifiedRefund(argThat(unifiedReqDTO -> { 414 when(client.unifiedRefund(argThat(unifiedReqDTO -> {
@@ -668,7 +665,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { @@ -668,7 +665,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
668 refundMapper.insert(refund); 665 refundMapper.insert(refund);
669 // mock 方法(client) 666 // mock 方法(client)
670 PayClient client = mock(PayClient.class); 667 PayClient client = mock(PayClient.class);
671 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 668 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
672 // mock 方法(client 返回指定状态) 669 // mock 方法(client 返回指定状态)
673 PayRefundRespDTO respDTO = randomPojo(PayRefundRespDTO.class, o -> o.setStatus(status)); 670 PayRefundRespDTO respDTO = randomPojo(PayRefundRespDTO.class, o -> o.setStatus(status));
674 when(client.getRefund(eq("P110"), eq("R220"))).thenReturn(respDTO); 671 when(client.getRefund(eq("P110"), eq("R220"))).thenReturn(respDTO);
@@ -690,7 +687,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { @@ -690,7 +687,7 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
690 refundMapper.insert(refund); 687 refundMapper.insert(refund);
691 // mock 方法(client) 688 // mock 方法(client)
692 PayClient client = mock(PayClient.class); 689 PayClient client = mock(PayClient.class);
693 - when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); 690 + when(channelService.getPayClient(eq(10L))).thenReturn(client);
694 // mock 方法(client 抛出异常) 691 // mock 方法(client 抛出异常)
695 when(client.getRefund(eq("P110"), eq("R220"))).thenThrow(new RuntimeException()); 692 when(client.getRefund(eq("P110"), eq("R220"))).thenThrow(new RuntimeException());
696 693
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApi.java
@@ -14,12 +14,12 @@ public interface SocialClientApi { @@ -14,12 +14,12 @@ public interface SocialClientApi {
14 /** 14 /**
15 * 获得社交平台的授权 URL 15 * 获得社交平台的授权 URL
16 * 16 *
17 - * @param type 社交平台的类型 {@link SocialTypeEnum} 17 + * @param socialType 社交平台的类型 {@link SocialTypeEnum}
18 * @param userType 用户类型 18 * @param userType 用户类型
19 * @param redirectUri 重定向 URL 19 * @param redirectUri 重定向 URL
20 * @return 社交平台的授权 URL 20 * @return 社交平台的授权 URL
21 */ 21 */
22 - String getAuthorizeUrl(Integer type, Integer userType, String redirectUri); 22 + String getAuthorizeUrl(Integer socialType, Integer userType, String redirectUri);
23 23
24 /** 24 /**
25 * 创建微信公众号 JS SDK 初始化所需的签名 25 * 创建微信公众号 JS SDK 初始化所需的签名
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java
@@ -35,12 +35,12 @@ public interface SocialUserApi { @@ -35,12 +35,12 @@ public interface SocialUserApi {
35 * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 35 * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常
36 * 36 *
37 * @param userType 用户类型 37 * @param userType 用户类型
38 - * @param type 社交平台的类型 38 + * @param socialType 社交平台的类型
39 * @param code 授权码 39 * @param code 授权码
40 * @param state state 40 * @param state state
41 * @return 社交用户 41 * @return 社交用户
42 */ 42 */
43 - SocialUserRespDTO getSocialUser(Integer userType, Integer type, 43 + SocialUserRespDTO getSocialUser(Integer userType, Integer socialType,
44 String code, String state); 44 String code, String state);
45 45
46 } 46 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java
@@ -24,8 +24,8 @@ public class SocialClientApiImpl implements SocialClientApi { @@ -24,8 +24,8 @@ public class SocialClientApiImpl implements SocialClientApi {
24 private SocialClientService socialClientService; 24 private SocialClientService socialClientService;
25 25
26 @Override 26 @Override
27 - public String getAuthorizeUrl(Integer type, Integer userType, String redirectUri) {  
28 - return socialClientService.getAuthorizeUrl(type, userType, redirectUri); 27 + public String getAuthorizeUrl(Integer socialType, Integer userType, String redirectUri) {
  28 + return socialClientService.getAuthorizeUrl(socialType, userType, redirectUri);
29 } 29 }
30 30
31 @Override 31 @Override
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java
@@ -33,8 +33,8 @@ public class SocialUserApiImpl implements SocialUserApi { @@ -33,8 +33,8 @@ public class SocialUserApiImpl implements SocialUserApi {
33 } 33 }
34 34
35 @Override 35 @Override
36 - public SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state) {  
37 - return socialUserService.getSocialUser(userType, type, code, state); 36 + public SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, String code, String state) {
  37 + return socialUserService.getSocialUser(userType, socialType, code, state);
38 } 38 }
39 39
40 } 40 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
@@ -148,7 +148,8 @@ public class AuthController { @@ -148,7 +148,8 @@ public class AuthController {
148 }) 148 })
149 public CommonResult<String> socialLogin(@RequestParam("type") Integer type, 149 public CommonResult<String> socialLogin(@RequestParam("type") Integer type,
150 @RequestParam("redirectUri") String redirectUri) { 150 @RequestParam("redirectUri") String redirectUri) {
151 - return success(socialClientService.getAuthorizeUrl(type, UserTypeEnum.ADMIN.getValue(), redirectUri)); 151 + return success(socialClientService.getAuthorizeUrl(
  152 + type, UserTypeEnum.ADMIN.getValue(), redirectUri));
152 } 153 }
153 154
154 @PostMapping("/social-login") 155 @PostMapping("/social-login")
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http
@@ -6,9 +6,9 @@ tenant-id: {{adminTenentId}} @@ -6,9 +6,9 @@ tenant-id: {{adminTenentId}}
6 6
7 { 7 {
8 "templateCode": "test_01", 8 "templateCode": "test_01",
9 - "mobile": "156016913900",  
10 - "params": {  
11 - "key01": "value01",  
12 - "key02": "value02" 9 + "mobile": "15601691390",
  10 + "templateParams": {
  11 + "operation": "value01",
  12 + "code": "value02"
13 } 13 }
14 } 14 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictDataConvert.java
@@ -31,5 +31,4 @@ public interface DictDataConvert { @@ -31,5 +31,4 @@ public interface DictDataConvert {
31 31
32 List<AppDictDataRespVO> convertList03(List<DictDataDO> list); 32 List<AppDictDataRespVO> convertList03(List<DictDataDO> list);
33 33
34 - List<DictDataRespDTO> convertList04(List<DictDataDO> list);  
35 } 34 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/mail/MailSendConsumer.java
1 package cn.iocoder.yudao.module.system.mq.consumer.mail; 1 package cn.iocoder.yudao.module.system.mq.consumer.mail;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;  
4 import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; 3 import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
5 -import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage;  
6 import cn.iocoder.yudao.module.system.service.mail.MailSendService; 4 import cn.iocoder.yudao.module.system.service.mail.MailSendService;
7 import lombok.extern.slf4j.Slf4j; 5 import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.context.event.EventListener;
  7 +import org.springframework.scheduling.annotation.Async;
8 import org.springframework.stereotype.Component; 8 import org.springframework.stereotype.Component;
9 9
10 import javax.annotation.Resource; 10 import javax.annotation.Resource;
@@ -16,12 +16,13 @@ import javax.annotation.Resource; @@ -16,12 +16,13 @@ import javax.annotation.Resource;
16 */ 16 */
17 @Component 17 @Component
18 @Slf4j 18 @Slf4j
19 -public class MailSendConsumer extends AbstractStreamMessageListener<MailSendMessage> { 19 +public class MailSendConsumer {
20 20
21 @Resource 21 @Resource
22 private MailSendService mailSendService; 22 private MailSendService mailSendService;
23 23
24 - @Override 24 + @EventListener
  25 + @Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步
25 public void onMessage(MailSendMessage message) { 26 public void onMessage(MailSendMessage message) {
26 log.info("[onMessage][消息内容({})]", message); 27 log.info("[onMessage][消息内容({})]", message);
27 mailSendService.doSendMail(message); 28 mailSendService.doSendMail(message);
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsSendConsumer.java
@@ -2,8 +2,9 @@ package cn.iocoder.yudao.module.system.mq.consumer.sms; @@ -2,8 +2,9 @@ package cn.iocoder.yudao.module.system.mq.consumer.sms;
2 2
3 import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage; 3 import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage;
4 import cn.iocoder.yudao.module.system.service.sms.SmsSendService; 4 import cn.iocoder.yudao.module.system.service.sms.SmsSendService;
5 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;  
6 import lombok.extern.slf4j.Slf4j; 5 import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.context.event.EventListener;
  7 +import org.springframework.scheduling.annotation.Async;
7 import org.springframework.stereotype.Component; 8 import org.springframework.stereotype.Component;
8 9
9 import javax.annotation.Resource; 10 import javax.annotation.Resource;
@@ -15,12 +16,13 @@ import javax.annotation.Resource; @@ -15,12 +16,13 @@ import javax.annotation.Resource;
15 */ 16 */
16 @Component 17 @Component
17 @Slf4j 18 @Slf4j
18 -public class SmsSendConsumer extends AbstractStreamMessageListener<SmsSendMessage> { 19 +public class SmsSendConsumer {
19 20
20 @Resource 21 @Resource
21 private SmsSendService smsSendService; 22 private SmsSendService smsSendService;
22 23
23 - @Override 24 + @EventListener
  25 + @Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步
24 public void onMessage(SmsSendMessage message) { 26 public void onMessage(SmsSendMessage message) {
25 log.info("[onMessage][消息内容({})]", message); 27 log.info("[onMessage][消息内容({})]", message);
26 smsSendService.doSendSms(message); 28 smsSendService.doSendSms(message);
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailSendMessage.java
1 package cn.iocoder.yudao.module.system.mq.message.mail; 1 package cn.iocoder.yudao.module.system.mq.message.mail;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;  
4 import lombok.Data; 3 import lombok.Data;
5 -import lombok.EqualsAndHashCode;  
6 4
7 import javax.validation.constraints.NotEmpty; 5 import javax.validation.constraints.NotEmpty;
8 import javax.validation.constraints.NotNull; 6 import javax.validation.constraints.NotNull;
@@ -13,8 +11,7 @@ import javax.validation.constraints.NotNull; @@ -13,8 +11,7 @@ import javax.validation.constraints.NotNull;
13 * @author 芋道源码 11 * @author 芋道源码
14 */ 12 */
15 @Data 13 @Data
16 -@EqualsAndHashCode(callSuper = true)  
17 -public class MailSendMessage extends AbstractStreamMessage { 14 +public class MailSendMessage {
18 15
19 /** 16 /**
20 * 邮件日志编号 17 * 邮件日志编号
@@ -47,9 +44,4 @@ public class MailSendMessage extends AbstractStreamMessage { @@ -47,9 +44,4 @@ public class MailSendMessage extends AbstractStreamMessage {
47 @NotEmpty(message = "邮件内容不能为空") 44 @NotEmpty(message = "邮件内容不能为空")
48 private String content; 45 private String content;
49 46
50 - @Override  
51 - public String getStreamKey() {  
52 - return "system.mail.send";  
53 - }  
54 -  
55 } 47 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/sms/SmsSendMessage.java
1 package cn.iocoder.yudao.module.system.mq.message.sms; 1 package cn.iocoder.yudao.module.system.mq.message.sms;
2 2
3 import cn.iocoder.yudao.framework.common.core.KeyValue; 3 import cn.iocoder.yudao.framework.common.core.KeyValue;
4 -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;  
5 import lombok.Data; 4 import lombok.Data;
6 -import lombok.EqualsAndHashCode;  
7 5
8 import javax.validation.constraints.NotNull; 6 import javax.validation.constraints.NotNull;
9 import java.util.List; 7 import java.util.List;
@@ -14,8 +12,7 @@ import java.util.List; @@ -14,8 +12,7 @@ import java.util.List;
14 * @author 芋道源码 12 * @author 芋道源码
15 */ 13 */
16 @Data 14 @Data
17 -@EqualsAndHashCode(callSuper = true)  
18 -public class SmsSendMessage extends AbstractStreamMessage { 15 +public class SmsSendMessage {
19 16
20 /** 17 /**
21 * 短信日志编号 18 * 短信日志编号
@@ -42,9 +39,4 @@ public class SmsSendMessage extends AbstractStreamMessage { @@ -42,9 +39,4 @@ public class SmsSendMessage extends AbstractStreamMessage {
42 */ 39 */
43 private List<KeyValue<String, Object>> templateParams; 40 private List<KeyValue<String, Object>> templateParams;
44 41
45 - @Override  
46 - public String getStreamKey() {  
47 - return "system.sms.send";  
48 - }  
49 -  
50 } 42 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/mail/MailProducer.java
1 package cn.iocoder.yudao.module.system.mq.producer.mail; 1 package cn.iocoder.yudao.module.system.mq.producer.mail;
2 2
3 -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;  
4 import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; 3 import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
5 import lombok.extern.slf4j.Slf4j; 4 import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.context.ApplicationContext;
6 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
7 7
8 import javax.annotation.Resource; 8 import javax.annotation.Resource;
@@ -18,7 +18,7 @@ import javax.annotation.Resource; @@ -18,7 +18,7 @@ import javax.annotation.Resource;
18 public class MailProducer { 18 public class MailProducer {
19 19
20 @Resource 20 @Resource
21 - private RedisMQTemplate redisMQTemplate; 21 + private ApplicationContext applicationContext;
22 22
23 /** 23 /**
24 * 发送 {@link MailSendMessage} 消息 24 * 发送 {@link MailSendMessage} 消息
@@ -35,7 +35,7 @@ public class MailProducer { @@ -35,7 +35,7 @@ public class MailProducer {
35 MailSendMessage message = new MailSendMessage() 35 MailSendMessage message = new MailSendMessage()
36 .setLogId(sendLogId).setMail(mail).setAccountId(accountId) 36 .setLogId(sendLogId).setMail(mail).setAccountId(accountId)
37 .setNickname(nickname).setTitle(title).setContent(content); 37 .setNickname(nickname).setTitle(title).setContent(content);
38 - redisMQTemplate.send(message); 38 + applicationContext.publishEvent(message);
39 } 39 }
40 40
41 } 41 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/sms/SmsProducer.java
1 package cn.iocoder.yudao.module.system.mq.producer.sms; 1 package cn.iocoder.yudao.module.system.mq.producer.sms;
2 2
3 import cn.iocoder.yudao.framework.common.core.KeyValue; 3 import cn.iocoder.yudao.framework.common.core.KeyValue;
4 -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;  
5 import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage; 4 import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage;
6 import lombok.extern.slf4j.Slf4j; 5 import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.context.ApplicationContext;
7 import org.springframework.stereotype.Component; 7 import org.springframework.stereotype.Component;
8 8
9 import javax.annotation.Resource; 9 import javax.annotation.Resource;
@@ -20,7 +20,7 @@ import java.util.List; @@ -20,7 +20,7 @@ import java.util.List;
20 public class SmsProducer { 20 public class SmsProducer {
21 21
22 @Resource 22 @Resource
23 - private RedisMQTemplate redisMQTemplate; 23 + private ApplicationContext applicationContext;
24 24
25 /** 25 /**
26 * 发送 {@link SmsSendMessage} 消息 26 * 发送 {@link SmsSendMessage} 消息
@@ -35,7 +35,7 @@ public class SmsProducer { @@ -35,7 +35,7 @@ public class SmsProducer {
35 Long channelId, String apiTemplateId, List<KeyValue<String, Object>> templateParams) { 35 Long channelId, String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
36 SmsSendMessage message = new SmsSendMessage().setLogId(logId).setMobile(mobile); 36 SmsSendMessage message = new SmsSendMessage().setLogId(logId).setMobile(mobile);
37 message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams); 37 message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams);
38 - redisMQTemplate.send(message); 38 + applicationContext.publishEvent(message);
39 } 39 }
40 40
41 } 41 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordService.java
@@ -91,8 +91,8 @@ public interface SensitiveWordService { @@ -91,8 +91,8 @@ public interface SensitiveWordService {
91 * 判断文本是否包含敏感词 91 * 判断文本是否包含敏感词
92 * 92 *
93 * @param text 文本 93 * @param text 文本
94 - * @param tags 表述数组  
95 - * @return 是否包含 94 + * @param tags 标签数组
  95 + * @return 是否包含敏感词
96 */ 96 */
97 boolean isTextValid(String text, List<String> tags); 97 boolean isTextValid(String text, List<String> tags);
98 98
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java
@@ -258,6 +258,7 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { @@ -258,6 +258,7 @@ public class SensitiveWordServiceImpl implements SensitiveWordService {
258 if (trie == null) { 258 if (trie == null) {
259 continue; 259 continue;
260 } 260 }
  261 + // 如果有一个标签不合法,则返回 false 不合法
261 if (!trie.isValid(text)) { 262 if (!trie.isValid(text)) {
262 return false; 263 return false;
263 } 264 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java
@@ -5,7 +5,6 @@ import cn.hutool.core.util.StrUtil; @@ -5,7 +5,6 @@ import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.sms.core.client.SmsClient; 7 import cn.iocoder.yudao.framework.sms.core.client.SmsClient;
8 -import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory;  
9 import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; 8 import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult;
10 import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; 9 import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO;
11 import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; 10 import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO;
@@ -53,9 +52,6 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { @@ -53,9 +52,6 @@ public class SmsTemplateServiceImpl implements SmsTemplateService {
53 @Resource 52 @Resource
54 private SmsChannelService smsChannelService; 53 private SmsChannelService smsChannelService;
55 54
56 - @Resource  
57 - private SmsClientFactory smsClientFactory;  
58 -  
59 @Override 55 @Override
60 public Long createSmsTemplate(SmsTemplateCreateReqVO createReqVO) { 56 public Long createSmsTemplate(SmsTemplateCreateReqVO createReqVO) {
61 // 校验短信渠道 57 // 校验短信渠道
@@ -173,7 +169,7 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { @@ -173,7 +169,7 @@ public class SmsTemplateServiceImpl implements SmsTemplateService {
173 @VisibleForTesting 169 @VisibleForTesting
174 void validateApiTemplate(Long channelId, String apiTemplateId) { 170 void validateApiTemplate(Long channelId, String apiTemplateId) {
175 // 获得短信模板 171 // 获得短信模板
176 - SmsClient smsClient = smsClientFactory.getSmsClient(channelId); 172 + SmsClient smsClient = smsChannelService.getSmsClient(channelId);
177 Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", channelId)); 173 Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", channelId));
178 SmsCommonResult<SmsTemplateRespDTO> templateResult = smsClient.getSmsTemplate(apiTemplateId); 174 SmsCommonResult<SmsTemplateRespDTO> templateResult = smsClient.getSmsTemplate(apiTemplateId);
179 // 校验短信模板是否正确 175 // 校验短信模板是否正确
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java
@@ -38,12 +38,12 @@ public interface SocialUserService { @@ -38,12 +38,12 @@ public interface SocialUserService {
38 /** 38 /**
39 * 取消绑定社交用户 39 * 取消绑定社交用户
40 * 40 *
41 - * @param userId 用户编号 41 + * @param userId 用户编号
42 * @param userType 全局用户类型 42 * @param userType 全局用户类型
43 - * @param type 社交平台的类型 {@link SocialTypeEnum}  
44 - * @param openid 社交平台的 openid 43 + * @param socialType 社交平台的类型 {@link SocialTypeEnum}
  44 + * @param openid 社交平台的 openid
45 */ 45 */
46 - void unbindSocialUser(Long userId, Integer userType, Integer type, String openid); 46 + void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid);
47 47
48 /** 48 /**
49 * 获得社交用户 49 * 获得社交用户
@@ -51,12 +51,12 @@ public interface SocialUserService { @@ -51,12 +51,12 @@ public interface SocialUserService {
51 * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 51 * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常
52 * 52 *
53 * @param userType 用户类型 53 * @param userType 用户类型
54 - * @param type 社交平台的类型  
55 - * @param code 授权码  
56 - * @param state state 54 + * @param socialType 社交平台的类型
  55 + * @param code 授权码
  56 + * @param state state
57 * @return 社交用户 57 * @return 社交用户
58 */ 58 */
59 - SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state); 59 + SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, String code, String state);
60 60
61 // ==================== 社交用户 CRUD ==================== 61 // ==================== 社交用户 CRUD ====================
62 62
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java
@@ -84,9 +84,9 @@ public class SocialUserServiceImpl implements SocialUserService { @@ -84,9 +84,9 @@ public class SocialUserServiceImpl implements SocialUserService {
84 } 84 }
85 85
86 @Override 86 @Override
87 - public void unbindSocialUser(Long userId, Integer userType, Integer type, String openid) { 87 + public void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid) {
88 // 获得 openid 对应的 SocialUserDO 社交用户 88 // 获得 openid 对应的 SocialUserDO 社交用户
89 - SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(type, openid); 89 + SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, openid);
90 if (socialUser == null) { 90 if (socialUser == null) {
91 throw exception(SOCIAL_USER_NOT_FOUND); 91 throw exception(SOCIAL_USER_NOT_FOUND);
92 } 92 }
@@ -96,9 +96,9 @@ public class SocialUserServiceImpl implements SocialUserService { @@ -96,9 +96,9 @@ public class SocialUserServiceImpl implements SocialUserService {
96 } 96 }
97 97
98 @Override 98 @Override
99 - public SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state) { 99 + public SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, String code, String state) {
100 // 获得社交用户 100 // 获得社交用户
101 - SocialUserDO socialUser = authSocialUser(type, userType, code, state); 101 + SocialUserDO socialUser = authSocialUser(socialType, userType, code, state);
102 Assert.notNull(socialUser, "社交用户不能为空"); 102 Assert.notNull(socialUser, "社交用户不能为空");
103 103
104 // 如果未绑定的社交用户,则无法自动登录,进行报错 104 // 如果未绑定的社交用户,则无法自动登录,进行报错
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/util/collection/SimpleTrie.java
@@ -30,9 +30,10 @@ public class SimpleTrie { @@ -30,9 +30,10 @@ public class SimpleTrie {
30 * @param strs 字符串数组 30 * @param strs 字符串数组
31 */ 31 */
32 public SimpleTrie(Collection<String> strs) { 32 public SimpleTrie(Collection<String> strs) {
33 - children = new HashMap<>(); 33 + // 排序,优先使用较短的前缀
  34 + strs = CollUtil.sort(strs, String::compareTo);
34 // 构建树 35 // 构建树
35 - CollUtil.sort(strs, String::compareTo); // 排序,优先使用较短的前缀 36 + children = new HashMap<>();
36 for (String str : strs) { 37 for (String str : strs) {
37 Map<Character, Object> child = children; 38 Map<Character, Object> child = children;
38 // 遍历每个字符 39 // 遍历每个字符
@@ -56,11 +57,11 @@ public class SimpleTrie { @@ -56,11 +57,11 @@ public class SimpleTrie {
56 * 验证文本是否合法,即不包含敏感词 57 * 验证文本是否合法,即不包含敏感词
57 * 58 *
58 * @param text 文本 59 * @param text 文本
59 - * @return 是否 ok 60 + * @return 是否 true-合法 false-不合法
60 */ 61 */
61 public boolean isValid(String text) { 62 public boolean isValid(String text) {
62 // 遍历 text,使用每一个 [i, n) 段的字符串,使用 children 前缀树匹配,是否包含敏感词 63 // 遍历 text,使用每一个 [i, n) 段的字符串,使用 children 前缀树匹配,是否包含敏感词
63 - for (int i = 0; i < text.length() - 1; i++) { 64 + for (int i = 0; i < text.length(); i++) {
64 Map<Character, Object> child = (Map<Character, Object>) children.get(text.charAt(i)); 65 Map<Character, Object> child = (Map<Character, Object>) children.get(text.charAt(i));
65 if (child == null) { 66 if (child == null) {
66 continue; 67 continue;
@@ -74,14 +75,17 @@ public class SimpleTrie { @@ -74,14 +75,17 @@ public class SimpleTrie {
74 } 75 }
75 76
76 /** 77 /**
77 - * 验证文本从指定位置开始,是否包含某个敏感词 78 + * 验证文本从指定位置开始,是否不包含某个敏感词
78 * 79 *
79 * @param text 文本 80 * @param text 文本
80 * @param index 开始位置 81 * @param index 开始位置
81 * @param child 节点(当前遍历到的) 82 * @param child 节点(当前遍历到的)
82 - * @return 是否包含 83 + * @return 是否不包含 true-不包含 false-包含
83 */ 84 */
84 private boolean recursion(String text, int index, Map<Character, Object> child) { 85 private boolean recursion(String text, int index, Map<Character, Object> child) {
  86 + if (child.containsKey(CHARACTER_END)) {
  87 + return false;
  88 + }
85 if (index == text.length()) { 89 if (index == text.length()) {
86 return true; 90 return true;
87 } 91 }
@@ -99,7 +103,7 @@ public class SimpleTrie { @@ -99,7 +103,7 @@ public class SimpleTrie {
99 */ 103 */
100 public List<String> validate(String text) { 104 public List<String> validate(String text) {
101 Set<String> results = new HashSet<>(); 105 Set<String> results = new HashSet<>();
102 - for (int i = 0; i < text.length() - 1; i++) { 106 + for (int i = 0; i < text.length(); i++) {
103 Character c = text.charAt(i); 107 Character c = text.charAt(i);
104 Map<Character, Object> child = (Map<Character, Object>) children.get(c); 108 Map<Character, Object> child = (Map<Character, Object>) children.get(c);
105 if (child == null) { 109 if (child == null) {
@@ -127,6 +131,9 @@ public class SimpleTrie { @@ -127,6 +131,9 @@ public class SimpleTrie {
127 */ 131 */
128 @SuppressWarnings("unchecked") 132 @SuppressWarnings("unchecked")
129 private static boolean recursionWithResult(String text, int index, Map<Character, Object> child, StringBuilder result) { 133 private static boolean recursionWithResult(String text, int index, Map<Character, Object> child, StringBuilder result) {
  134 + if (child.containsKey(CHARACTER_END)) {
  135 + return false;
  136 + }
130 if (index == text.length()) { 137 if (index == text.length()) {
131 return true; 138 return true;
132 } 139 }
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImplTest.java
@@ -56,20 +56,28 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { @@ -56,20 +56,28 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest {
56 SensitiveWordDO wordDO2 = randomPojo(SensitiveWordDO.class, o -> o.setName("笨蛋") 56 SensitiveWordDO wordDO2 = randomPojo(SensitiveWordDO.class, o -> o.setName("笨蛋")
57 .setTags(singletonList("蔬菜")).setStatus(CommonStatusEnum.ENABLE.getStatus())); 57 .setTags(singletonList("蔬菜")).setStatus(CommonStatusEnum.ENABLE.getStatus()));
58 sensitiveWordMapper.insert(wordDO2); 58 sensitiveWordMapper.insert(wordDO2);
  59 + SensitiveWordDO wordDO3 = randomPojo(SensitiveWordDO.class, o -> o.setName("白")
  60 + .setTags(singletonList("测试")).setStatus(CommonStatusEnum.ENABLE.getStatus()));
  61 + sensitiveWordMapper.insert(wordDO3);
  62 + SensitiveWordDO wordDO4 = randomPojo(SensitiveWordDO.class, o -> o.setName("白痴")
  63 + .setTags(singletonList("测试")).setStatus(CommonStatusEnum.ENABLE.getStatus()));
  64 + sensitiveWordMapper.insert(wordDO4);
59 65
60 // 调用 66 // 调用
61 sensitiveWordService.initLocalCache(); 67 sensitiveWordService.initLocalCache();
62 // 断言 sensitiveWordTagsCache 缓存 68 // 断言 sensitiveWordTagsCache 缓存
63 - assertEquals(SetUtils.asSet("论坛", "蔬菜"), sensitiveWordService.getSensitiveWordTagSet()); 69 + assertEquals(SetUtils.asSet("论坛", "蔬菜", "测试"), sensitiveWordService.getSensitiveWordTagSet());
64 // 断言 sensitiveWordCache 70 // 断言 sensitiveWordCache
65 - assertEquals(2, sensitiveWordService.getSensitiveWordCache().size()); 71 + assertEquals(4, sensitiveWordService.getSensitiveWordCache().size());
66 assertPojoEquals(wordDO1, sensitiveWordService.getSensitiveWordCache().get(0)); 72 assertPojoEquals(wordDO1, sensitiveWordService.getSensitiveWordCache().get(0));
67 assertPojoEquals(wordDO2, sensitiveWordService.getSensitiveWordCache().get(1)); 73 assertPojoEquals(wordDO2, sensitiveWordService.getSensitiveWordCache().get(1));
  74 + assertPojoEquals(wordDO3, sensitiveWordService.getSensitiveWordCache().get(2));
68 // 断言 tagSensitiveWordTries 缓存 75 // 断言 tagSensitiveWordTries 缓存
69 assertNotNull(sensitiveWordService.getDefaultSensitiveWordTrie()); 76 assertNotNull(sensitiveWordService.getDefaultSensitiveWordTrie());
70 - assertEquals(2, sensitiveWordService.getTagSensitiveWordTries().size()); 77 + assertEquals(3, sensitiveWordService.getTagSensitiveWordTries().size());
71 assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("论坛")); 78 assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("论坛"));
72 assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("蔬菜")); 79 assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("蔬菜"));
  80 + assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("测试"));
73 } 81 }
74 82
75 @Test 83 @Test
@@ -231,11 +239,17 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { @@ -231,11 +239,17 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest {
231 testInitLocalCache(); 239 testInitLocalCache();
232 // 准备参数 240 // 准备参数
233 String text = "你是傻瓜,你是笨蛋"; 241 String text = "你是傻瓜,你是笨蛋";
234 -  
235 // 调用 242 // 调用
236 List<String> result = sensitiveWordService.validateText(text, null); 243 List<String> result = sensitiveWordService.validateText(text, null);
237 // 断言 244 // 断言
238 assertEquals(Arrays.asList("傻瓜", "笨蛋"), result); 245 assertEquals(Arrays.asList("傻瓜", "笨蛋"), result);
  246 +
  247 + // 准备参数
  248 + String text2 = "你是傻瓜,你是笨蛋,你是白";
  249 + // 调用
  250 + List<String> result2 = sensitiveWordService.validateText(text2, null);
  251 + // 断言
  252 + assertEquals(Arrays.asList("傻瓜", "笨蛋","白"), result2);
239 } 253 }
240 254
241 @Test 255 @Test
@@ -243,11 +257,18 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { @@ -243,11 +257,18 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest {
243 testInitLocalCache(); 257 testInitLocalCache();
244 // 准备参数 258 // 准备参数
245 String text = "你是傻瓜,你是笨蛋"; 259 String text = "你是傻瓜,你是笨蛋";
246 -  
247 // 调用 260 // 调用
248 List<String> result = sensitiveWordService.validateText(text, singletonList("论坛")); 261 List<String> result = sensitiveWordService.validateText(text, singletonList("论坛"));
249 // 断言 262 // 断言
250 assertEquals(singletonList("傻瓜"), result); 263 assertEquals(singletonList("傻瓜"), result);
  264 +
  265 +
  266 + // 准备参数
  267 + String text2 = "你是白";
  268 + // 调用
  269 + List<String> result2 = sensitiveWordService.validateText(text2, singletonList("测试"));
  270 + // 断言
  271 + assertEquals(singletonList("白"), result2);
251 } 272 }
252 273
253 @Test 274 @Test
@@ -255,9 +276,13 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { @@ -255,9 +276,13 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest {
255 testInitLocalCache(); 276 testInitLocalCache();
256 // 准备参数 277 // 准备参数
257 String text = "你是傻瓜,你是笨蛋"; 278 String text = "你是傻瓜,你是笨蛋";
258 -  
259 // 调用,断言 279 // 调用,断言
260 assertFalse(sensitiveWordService.isTextValid(text, null)); 280 assertFalse(sensitiveWordService.isTextValid(text, null));
  281 +
  282 + // 准备参数
  283 + String text2 = "你是白";
  284 + // 调用,断言
  285 + assertFalse(sensitiveWordService.isTextValid(text2, null));
261 } 286 }
262 287
263 @Test 288 @Test
@@ -265,9 +290,13 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { @@ -265,9 +290,13 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest {
265 testInitLocalCache(); 290 testInitLocalCache();
266 // 准备参数 291 // 准备参数
267 String text = "你是傻瓜,你是笨蛋"; 292 String text = "你是傻瓜,你是笨蛋";
268 -  
269 // 调用,断言 293 // 调用,断言
270 assertFalse(sensitiveWordService.isTextValid(text, singletonList("论坛"))); 294 assertFalse(sensitiveWordService.isTextValid(text, singletonList("论坛")));
  295 +
  296 + // 准备参数
  297 + String text2 = "你是白";
  298 + // 调用,断言
  299 + assertFalse(sensitiveWordService.isTextValid(text2, singletonList("测试")));
271 } 300 }
272 301
273 } 302 }
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java
@@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; 6 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
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.sms.core.client.SmsClient; 8 import cn.iocoder.yudao.framework.sms.core.client.SmsClient;
9 -import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory;  
10 import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; 9 import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult;
11 import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; 10 import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO;
12 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 11 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
@@ -36,7 +35,7 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; @@ -36,7 +35,7 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
36 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; 35 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
37 import static org.junit.jupiter.api.Assertions.*; 36 import static org.junit.jupiter.api.Assertions.*;
38 import static org.mockito.ArgumentMatchers.eq; 37 import static org.mockito.ArgumentMatchers.eq;
39 -import static org.mockito.Mockito.*; 38 +import static org.mockito.Mockito.when;
40 39
41 @Import(SmsTemplateServiceImpl.class) 40 @Import(SmsTemplateServiceImpl.class)
42 public class SmsTemplateServiceImplTest extends BaseDbUnitTest { 41 public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
@@ -50,8 +49,6 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { @@ -50,8 +49,6 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
50 @MockBean 49 @MockBean
51 private SmsChannelService smsChannelService; 50 private SmsChannelService smsChannelService;
52 @MockBean 51 @MockBean
53 - private SmsClientFactory smsClientFactory;  
54 - @MockBean  
55 private SmsClient smsClient; 52 private SmsClient smsClient;
56 53
57 @Test 54 @Test
@@ -82,7 +79,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { @@ -82,7 +79,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
82 }); 79 });
83 when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO); 80 when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO);
84 // mock 获得 API 短信模板成功 81 // mock 获得 API 短信模板成功
85 - when(smsClientFactory.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient); 82 + when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient);
86 when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(randomPojo(SmsCommonResult.class, SmsTemplateRespDTO.class, 83 when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(randomPojo(SmsCommonResult.class, SmsTemplateRespDTO.class,
87 o -> o.setCode(GlobalErrorCodeConstants.SUCCESS.getCode()))); 84 o -> o.setCode(GlobalErrorCodeConstants.SUCCESS.getCode())));
88 85
@@ -117,7 +114,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { @@ -117,7 +114,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
117 }); 114 });
118 when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO); 115 when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO);
119 // mock 获得 API 短信模板成功 116 // mock 获得 API 短信模板成功
120 - when(smsClientFactory.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient); 117 + when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient);
121 when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(randomPojo(SmsCommonResult.class, SmsTemplateRespDTO.class, 118 when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(randomPojo(SmsCommonResult.class, SmsTemplateRespDTO.class,
122 o -> o.setCode(GlobalErrorCodeConstants.SUCCESS.getCode()))); 119 o -> o.setCode(GlobalErrorCodeConstants.SUCCESS.getCode())));
123 120
yudao-server/pom.xml
@@ -37,11 +37,11 @@ @@ -37,11 +37,11 @@
37 </dependency> 37 </dependency>
38 38
39 <!-- 会员中心。默认注释,保证编译速度 --> 39 <!-- 会员中心。默认注释,保证编译速度 -->
40 - <dependency>  
41 - <groupId>cn.iocoder.boot</groupId>  
42 - <artifactId>yudao-module-member-biz</artifactId>  
43 - <version>${revision}</version>  
44 - </dependency> 40 +<!-- <dependency>-->
  41 +<!-- <groupId>cn.iocoder.boot</groupId>-->
  42 +<!-- <artifactId>yudao-module-member-biz</artifactId>-->
  43 +<!-- <version>${revision}</version>-->
  44 +<!-- </dependency>-->
45 45
46 <!-- 数据报表。默认注释,保证编译速度 --> 46 <!-- 数据报表。默认注释,保证编译速度 -->
47 <!-- <dependency>--> 47 <!-- <dependency>-->
@@ -56,40 +56,40 @@ @@ -56,40 +56,40 @@
56 <!-- <version>${revision}</version>--> 56 <!-- <version>${revision}</version>-->
57 <!-- </dependency>--> 57 <!-- </dependency>-->
58 <!-- 支付服务。默认注释,保证编译速度 --> 58 <!-- 支付服务。默认注释,保证编译速度 -->
59 - <dependency>  
60 - <groupId>cn.iocoder.boot</groupId>  
61 - <artifactId>yudao-module-pay-biz</artifactId>  
62 - <version>${revision}</version>  
63 - </dependency> 59 +<!-- <dependency>-->
  60 +<!-- <groupId>cn.iocoder.boot</groupId>-->
  61 +<!-- <artifactId>yudao-module-pay-biz</artifactId>-->
  62 +<!-- <version>${revision}</version>-->
  63 +<!-- </dependency>-->
64 64
65 <!-- 微信公众号模块。默认注释,保证编译速度 --> 65 <!-- 微信公众号模块。默认注释,保证编译速度 -->
66 - <dependency>  
67 - <groupId>cn.iocoder.boot</groupId>  
68 - <artifactId>yudao-module-mp-biz</artifactId>  
69 - <version>${revision}</version>  
70 - </dependency> 66 +<!-- <dependency>-->
  67 +<!-- <groupId>cn.iocoder.boot</groupId>-->
  68 +<!-- <artifactId>yudao-module-mp-biz</artifactId>-->
  69 +<!-- <version>${revision}</version>-->
  70 +<!-- </dependency>-->
71 71
72 <!-- 商城相关模块。默认注释,保证编译速度--> 72 <!-- 商城相关模块。默认注释,保证编译速度-->
73 - <dependency>  
74 - <groupId>cn.iocoder.boot</groupId>  
75 - <artifactId>yudao-module-promotion-biz</artifactId>  
76 - <version>${revision}</version>  
77 - </dependency>  
78 - <dependency>  
79 - <groupId>cn.iocoder.boot</groupId>  
80 - <artifactId>yudao-module-product-biz</artifactId>  
81 - <version>${revision}</version>  
82 - </dependency>  
83 - <dependency>  
84 - <groupId>cn.iocoder.boot</groupId>  
85 - <artifactId>yudao-module-trade-biz</artifactId>  
86 - <version>${revision}</version>  
87 - </dependency>  
88 - <dependency>  
89 - <groupId>cn.iocoder.boot</groupId>  
90 - <artifactId>yudao-module-statistics-biz</artifactId>  
91 - <version>${revision}</version>  
92 - </dependency> 73 +<!-- <dependency>-->
  74 +<!-- <groupId>cn.iocoder.boot</groupId>-->
  75 +<!-- <artifactId>yudao-module-promotion-biz</artifactId>-->
  76 +<!-- <version>${revision}</version>-->
  77 +<!-- </dependency>-->
  78 +<!-- <dependency>-->
  79 +<!-- <groupId>cn.iocoder.boot</groupId>-->
  80 +<!-- <artifactId>yudao-module-product-biz</artifactId>-->
  81 +<!-- <version>${revision}</version>-->
  82 +<!-- </dependency>-->
  83 +<!-- <dependency>-->
  84 +<!-- <groupId>cn.iocoder.boot</groupId>-->
  85 +<!-- <artifactId>yudao-module-trade-biz</artifactId>-->
  86 +<!-- <version>${revision}</version>-->
  87 +<!-- </dependency>-->
  88 +<!-- <dependency>-->
  89 +<!-- <groupId>cn.iocoder.boot</groupId>-->
  90 +<!-- <artifactId>yudao-module-statistics-biz</artifactId>-->
  91 +<!-- <version>${revision}</version>-->
  92 +<!-- </dependency>-->
93 93
94 <!-- spring boot 配置所需依赖 --> 94 <!-- spring boot 配置所需依赖 -->
95 <dependency> 95 <dependency>
yudao-server/src/main/resources/application-dev.yaml
@@ -94,6 +94,23 @@ spring: @@ -94,6 +94,23 @@ spring:
94 jdbc: # 使用 JDBC 的 JobStore 的时候,JDBC 的配置 94 jdbc: # 使用 JDBC 的 JobStore 的时候,JDBC 的配置
95 initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。 95 initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。
96 96
  97 +--- #################### 消息队列相关 ####################
  98 +
  99 +# rocketmq 配置项,对应 RocketMQProperties 配置类
  100 +rocketmq:
  101 + name-server: 127.0.0.1:9876 # RocketMQ Namesrv
  102 +
  103 +spring:
  104 + # RabbitMQ 配置项,对应 RabbitProperties 配置类
  105 + rabbitmq:
  106 + host: 127.0.0.1 # RabbitMQ 服务的地址
  107 + port: 5672 # RabbitMQ 服务的端口
  108 + username: guest # RabbitMQ 服务的账号
  109 + password: guest # RabbitMQ 服务的密码
  110 + # Kafka 配置项,对应 KafkaProperties 配置类
  111 + kafka:
  112 + bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔
  113 +
97 --- #################### 服务保障相关配置 #################### 114 --- #################### 服务保障相关配置 ####################
98 115
99 # Lock4j 配置项 116 # Lock4j 配置项
yudao-server/src/main/resources/application-local.yaml
@@ -109,6 +109,23 @@ spring: @@ -109,6 +109,23 @@ spring:
109 jdbc: # 使用 JDBC 的 JobStore 的时候,JDBC 的配置 109 jdbc: # 使用 JDBC 的 JobStore 的时候,JDBC 的配置
110 initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。 110 initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。
111 111
  112 +--- #################### 消息队列相关 ####################
  113 +
  114 +# rocketmq 配置项,对应 RocketMQProperties 配置类
  115 +rocketmq:
  116 + name-server: 127.0.0.1:9876 # RocketMQ Namesrv
  117 +
  118 +spring:
  119 + # RabbitMQ 配置项,对应 RabbitProperties 配置类
  120 + rabbitmq:
  121 + host: 127.0.0.1 # RabbitMQ 服务的地址
  122 + port: 5672 # RabbitMQ 服务的端口
  123 + username: guest # RabbitMQ 服务的账号
  124 + password: guest # RabbitMQ 服务的密码
  125 + # Kafka 配置项,对应 KafkaProperties 配置类
  126 + kafka:
  127 + bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔
  128 +
112 --- #################### 服务保障相关配置 #################### 129 --- #################### 服务保障相关配置 ####################
113 130
114 # Lock4j 配置项 131 # Lock4j 配置项
yudao-server/src/main/resources/application.yaml
@@ -106,6 +106,32 @@ aj: @@ -106,6 +106,32 @@ aj:
106 req-check-minute-limit: 60 # check 接口一分钟内请求数限制 106 req-check-minute-limit: 60 # check 接口一分钟内请求数限制
107 req-verify-minute-limit: 60 # verify 接口一分钟内请求数限制 107 req-verify-minute-limit: 60 # verify 接口一分钟内请求数限制
108 108
  109 +--- #################### 消息队列相关 ####################
  110 +
  111 +# rocketmq 配置项,对应 RocketMQProperties 配置类
  112 +rocketmq:
  113 + # Producer 配置项
  114 + producer:
  115 + group: ${spring.application.name}_PRODUCER # 生产者分组
  116 +
  117 +spring:
  118 + # Kafka 配置项,对应 KafkaProperties 配置类
  119 + kafka:
  120 + # Kafka Producer 配置项
  121 + producer:
  122 + acks: 1 # 0-不应答。1-leader 应答。all-所有 leader 和 follower 应答。
  123 + retries: 3 # 发送失败时,重试发送的次数
  124 + value-serializer: org.springframework.kafka.support.serializer.JsonSerializer # 消息的 value 的序列化
  125 + # Kafka Consumer 配置项
  126 + consumer:
  127 + auto-offset-reset: earliest # 设置消费者分组最初的消费进度为 earliest 。可参考博客 https://blog.csdn.net/lishuangzhe7047/article/details/74530417 理解
  128 + value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
  129 + properties:
  130 + spring.json.trusted.packages: '*'
  131 + # Kafka Consumer Listener 监听器配置
  132 + listener:
  133 + missing-topics-fatal: false # 消费监听接口监听的主题不存在时,默认会报错。所以通过设置为 false ,解决报错
  134 +
109 --- #################### 芋道相关配置 #################### 135 --- #################### 芋道相关配置 ####################
110 136
111 yudao: 137 yudao:
@@ -145,12 +171,6 @@ yudao: @@ -145,12 +171,6 @@ yudao:
145 - cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants 171 - cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants
146 - cn.iocoder.yudao.module.system.enums.ErrorCodeConstants 172 - cn.iocoder.yudao.module.system.enums.ErrorCodeConstants
147 - cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants 173 - cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants
148 - mq:  
149 - redis:  
150 - pubsub:  
151 - enable: false # 是否开启 Redis pubsub 广播消费,默认为 true。这里设置成 false,可以按需开启  
152 - stream:  
153 - enable: false # 是否开启 Redis stream 集群消费,默认为 true。这里设置成 false,可以按需开启  
154 tenant: # 多租户相关配置项 174 tenant: # 多租户相关配置项
155 enable: true 175 enable: true
156 ignore-urls: 176 ignore-urls:
yudao-server/src/main/resources/static/MP_verify_DKOvVzFP7vPwwHx2.txt deleted
1 -DKOvVzFP7vPwwHx2  
2 \ No newline at end of file 0 \ No newline at end of file
yudao-server/src/main/resources/static/READMD.md deleted
1 -## 微信公众号  
2 -  
3 -参考文章:https://www.yuque.com/docs/share/0e2966dd-89f8-4b69-980d-b876168725df  
4 -  
5 -① 访问 social-login.html 选择【微信公众号】  
6 -  
7 -② 微信公众号授权完成后,跳转回 social-login2.html,输入手机号 + 密码,进行绑定  
8 -  
9 -## 微信小程序  
10 -  
11 -参考文章:https://www.yuque.com/docs/share/88e3d30a-6830-45fc-8c25-dae485aef3aa  
12 -  
13 -① 暂时使用 mini-program-test 项目  
yudao-server/src/main/resources/static/pay_wx_pub.html deleted
1 -<!DOCTYPE html>  
2 -<html>  
3 -<head>  
4 - <meta charset="UTF-8">  
5 - <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>  
6 - <title>支付测试页</title>  
7 - <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>  
8 - <script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>  
9 -</head>  
10 -<body>  
11 -<div>点击如下按钮,发起支付的测试</div>  
12 -<div>  
13 - <button id="wx_pub">微信公众号</button>  
14 -</div>  
15 -</body>  
16 -<script>  
17 - let shopOrderId = undefined;  
18 - let payOrderId = undefined;  
19 - let server = 'http://127.0.0.1:48080';  
20 - // let server = 'http://niubi.natapp1.cc';  
21 - // TODO openid  
22 - let openid = "ockUAwIZ-0OeMZl9ogcZ4ILrGba0";  
23 - $(function() {  
24 - // 获得 JsapiTicket  
25 - // 参考 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html 文档  
26 - $.ajax({  
27 - url: server + "/app-api/wx/mp/create-jsapi-signature?url=" + document.location.href,  
28 - method: 'POST',  
29 - headers: {  
30 - 'tenant-id': 1  
31 - },  
32 - success: function( result ) {  
33 - if (result.code !== 0) {  
34 - alert('获取 JsapiTicket 失败,原因:' + result.msg)  
35 - return;  
36 - }  
37 - var jsapiTicket = result.data;  
38 - jsapiTicket.jsApiList = ['chooseWXPay'];  
39 - jsapiTicket.debug = false;  
40 -  
41 - // 初始化 JS  
42 - wx.config(jsapiTicket);  
43 - }  
44 - });  
45 -  
46 - // 自动发起商城订单编号  
47 - $.ajax({  
48 - url: server + "/app-api/shop/order/create",  
49 - method: 'POST',  
50 - success: function( result ) {  
51 - if (result.code !== 0) {  
52 - alert('创建商城订单失败,原因:' + result.msg)  
53 - return;  
54 - }  
55 - shopOrderId = result.data.id;  
56 - payOrderId = result.data.payOrderId;  
57 - console.log("商城订单:" + shopOrderId)  
58 - console.log("支付订单:" + payOrderId)  
59 - }  
60 - })  
61 - })  
62 -  
63 - // 微信公众号  
64 - $( "#wx_pub").on( "click", function() {  
65 - if (typeof WeixinJSBridge == "undefined") {  
66 - // if (document.addEventListener) {  
67 - // document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);  
68 - // } else if (document.attachEvent) {  
69 - // document.attachEvent('WeixinJSBridgeReady', onBridgeReady);  
70 - // document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);  
71 - // }  
72 - alert('微信支付,只支持在微信客户端中使用!');  
73 - return;  
74 - }  
75 - if (navigator.userAgent.indexOf('wechatdevtools') >= 0) {  
76 - alert('微信支付,无法在微信开发者工具中使用!请使用微信客户端!');  
77 - return;  
78 - }  
79 -  
80 - // 提交支付  
81 - // 参考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 文档  
82 - // 参考 https://segmentfault.com/a/1190000020704650 文档  
83 - $.ajax({  
84 - url: server + "/app-api/pay/order/submit",  
85 - method: 'POST',  
86 - dataType: "json",  
87 - contentType: "application/json",  
88 - data: JSON.stringify({  
89 - "id": payOrderId,  
90 - "channelCode": 'wx_pub',  
91 - "channelExtras": {  
92 - "openid": openid  
93 - }  
94 - }),  
95 - success: function( result ) {  
96 - if (result.code !== 0) {  
97 - alert('提交支付订单失败,原因:' + result.msg)  
98 - return;  
99 - }  
100 - alert('点击确定,开始微信支付');  
101 - // 开始调用微信支付  
102 - let data = result.data.invokeResponse;  
103 - wx.chooseWXPay({  
104 - timestamp: data.timeStamp,  
105 - nonceStr: data.nonceStr,  
106 - package: data.packageValue,  
107 - signType: data.signType,  
108 - paySign: data.paySign,  
109 - success: function (res) {  
110 - alert(JSON.stringify(res));  
111 - },  
112 - error: function(e) {  
113 - alert(JSON.stringify(e));  
114 - }  
115 - });  
116 - }  
117 - })  
118 - });  
119 -</script>  
120 -</html>  
yudao-ui-admin/package.json
1 { 1 {
2 "name": "yudao-ui-admin", 2 "name": "yudao-ui-admin",
3 - "version": "1.8.0-snapshot", 3 + "version": "1.8.3-snapshot",
4 "description": "芋道管理系统", 4 "description": "芋道管理系统",
5 "author": "芋道", 5 "author": "芋道",
6 "license": "MIT", 6 "license": "MIT",