Commit b287fdb9f2a78e10011b511e1e90f86e8c3c2e8d

Authored by 芋道源码
Committed by Gitee
2 parents 91769f0b 6c174d9c

!544 同步最新商城代码

Merge pull request !544 from 芋道源码/feature/mall_product
Showing 198 changed files with 3229 additions and 956 deletions

Too many changes.

To preserve performance only 100 of 198 files are displayed.

yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
@@ -27,8 +27,6 @@ public interface WebFilterOrderEnum { @@ -27,8 +27,6 @@ public interface WebFilterOrderEnum {
27 27
28 int TENANT_SECURITY_FILTER = -99; // 需要保证在 Spring Security 过滤器后面 28 int TENANT_SECURITY_FILTER = -99; // 需要保证在 Spring Security 过滤器后面
29 29
30 - int ACTIVITI_FILTER = -98; // 需要保证在 Spring Security 过滤后面  
31 -  
32 int FLOWABLE_FILTER = -98; // 需要保证在 Spring Security 过滤后面 30 int FLOWABLE_FILTER = -98; // 需要保证在 Spring Security 过滤后面
33 31
34 int DEMO_FILTER = Integer.MAX_VALUE; 32 int DEMO_FILTER = Integer.MAX_VALUE;
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java
@@ -37,15 +37,4 @@ public interface GlobalErrorCodeConstants { @@ -37,15 +37,4 @@ public interface GlobalErrorCodeConstants {
37 37
38 ErrorCode UNKNOWN = new ErrorCode(999, "未知错误"); 38 ErrorCode UNKNOWN = new ErrorCode(999, "未知错误");
39 39
40 - /**  
41 - * 是否为服务端错误,参考 HTTP 5XX 错误码段  
42 - *  
43 - * @param code 错误码  
44 - * @return 是否  
45 - */  
46 - static boolean isServerErrorCode(Integer code) {  
47 - return code != null  
48 - && code >= INTERNAL_SERVER_ERROR.getCode() && code <= INTERNAL_SERVER_ERROR.getCode() + 99;  
49 - }  
50 -  
51 } 40 }
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/CommonResult.java
1 package cn.iocoder.yudao.framework.common.pojo; 1 package cn.iocoder.yudao.framework.common.pojo;
2 2
3 import cn.iocoder.yudao.framework.common.exception.ErrorCode; 3 import cn.iocoder.yudao.framework.common.exception.ErrorCode;
4 -import cn.iocoder.yudao.framework.common.exception.ServerException;  
5 import cn.iocoder.yudao.framework.common.exception.ServiceException; 4 import cn.iocoder.yudao.framework.common.exception.ServiceException;
6 import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; 5 import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
7 import com.fasterxml.jackson.annotation.JsonIgnore; 6 import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -92,10 +91,6 @@ public class CommonResult&lt;T&gt; implements Serializable { @@ -92,10 +91,6 @@ public class CommonResult&lt;T&gt; implements Serializable {
92 if (isSuccess()) { 91 if (isSuccess()) {
93 return; 92 return;
94 } 93 }
95 - // 服务端异常  
96 - if (GlobalErrorCodeConstants.isServerErrorCode(code)) {  
97 - throw new ServerException(code, msg);  
98 - }  
99 // 业务异常 94 // 业务异常
100 throw new ServiceException(code, msg); 95 throw new ServiceException(code, msg);
101 } 96 }
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
@@ -4,6 +4,7 @@ import cn.hutool.core.date.LocalDateTimeUtil; @@ -4,6 +4,7 @@ import cn.hutool.core.date.LocalDateTimeUtil;
4 4
5 import java.time.Duration; 5 import java.time.Duration;
6 import java.time.LocalDateTime; 6 import java.time.LocalDateTime;
  7 +import java.time.LocalTime;
7 8
8 /** 9 /**
9 * 时间工具类,用于 {@link java.time.LocalDateTime} 10 * 时间工具类,用于 {@link java.time.LocalDateTime}
@@ -50,7 +51,7 @@ public class LocalDateTimeUtils { @@ -50,7 +51,7 @@ public class LocalDateTimeUtils {
50 * 判断当前时间是否在该时间范围内 51 * 判断当前时间是否在该时间范围内
51 * 52 *
52 * @param startTime 开始时间 53 * @param startTime 开始时间
53 - * @param endTime 结束时间 54 + * @param endTime 结束时间
54 * @return 是否 55 * @return 是否
55 */ 56 */
56 public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime) { 57 public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime) {
@@ -60,4 +61,24 @@ public class LocalDateTimeUtils { @@ -60,4 +61,24 @@ public class LocalDateTimeUtils {
60 return LocalDateTimeUtil.isIn(LocalDateTime.now(), startTime, endTime); 61 return LocalDateTimeUtil.isIn(LocalDateTime.now(), startTime, endTime);
61 } 62 }
62 63
  64 + /**
  65 + * 检查时间重叠 不包含日期
  66 + *
  67 + * @param startTime1 需要校验的开始时间
  68 + * @param endTime1 需要校验的结束时间
  69 + * @param startTime2 校验所需的开始时间
  70 + * @param endTime2 校验所需的结束时间
  71 + * @return 是否重叠
  72 + */
  73 + // TODO @puhui999:LocalDateTimeUtil.isOverlap() 是不是可以满足呀?
  74 + public static boolean checkTimeOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) {
  75 + // 判断时间是否重叠
  76 + // 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 []
  77 + return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2)
  78 + // 开始时间在已配置时段的开始时间之前 且 结束时间在已配置时段的开始时间之后 (] 或 ()
  79 + || startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2)
  80 + // 开始时间在已配置时段的结束时间之前 且 结束时间在已配值时段的结束时间之后 [) 或 ()
  81 + || startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2);
  82 + }
  83 +
63 } 84 }
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
@@ -21,6 +21,7 @@ public class YudaoJacksonAutoConfiguration { @@ -21,6 +21,7 @@ public class YudaoJacksonAutoConfiguration {
21 @Bean 21 @Bean
22 public BeanPostProcessor objectMapperBeanPostProcessor() { 22 public BeanPostProcessor objectMapperBeanPostProcessor() {
23 return new BeanPostProcessor() { 23 return new BeanPostProcessor() {
  24 +
24 @Override 25 @Override
25 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 26 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
26 if (!(bean instanceof ObjectMapper)) { 27 if (!(bean instanceof ObjectMapper)) {
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
@@ -17,12 +17,9 @@ import org.flowable.task.api.Task; @@ -17,12 +17,9 @@ import org.flowable.task.api.Task;
17 import org.flowable.task.api.history.HistoricTaskInstance; 17 import org.flowable.task.api.history.HistoricTaskInstance;
18 import org.mapstruct.*; 18 import org.mapstruct.*;
19 import org.mapstruct.factory.Mappers; 19 import org.mapstruct.factory.Mappers;
20 -import org.springframework.beans.BeanUtils;  
21 20
22 -import java.util.Collections;  
23 import java.util.List; 21 import java.util.List;
24 import java.util.Map; 22 import java.util.Map;
25 -import java.util.stream.Collectors;  
26 23
27 /** 24 /**
28 * Bpm 任务 Convert 25 * Bpm 任务 Convert
@@ -34,37 +31,9 @@ public interface BpmTaskConvert { @@ -34,37 +31,9 @@ public interface BpmTaskConvert {
34 31
35 BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class); 32 BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class);
36 33
37 - /**  
38 - * 复制对象  
39 - *  
40 - * @param source 源 要复制的对象  
41 - * @param target 目标 复制到此对象  
42 - * @param <T>  
43 - *  
44 - * @return  
45 - */  
46 - public static <T> T copy(Object source, Class<T> target) {  
47 - if (source == null || target == null) {  
48 - return null;  
49 - }  
50 - try {  
51 - T newInstance = target.getDeclaredConstructor().newInstance();  
52 - BeanUtils.copyProperties(source, newInstance);  
53 - return newInstance;  
54 - } catch (Exception e) {  
55 - throw new RuntimeException(e);  
56 - }  
57 - }  
58 -  
59 - default <T, K> List<K> copyList(List<T> source, Class<K> target) {  
60 - if (null == source || source.isEmpty()) {  
61 - return Collections.emptyList();  
62 - }  
63 - return source.stream().map(e -> copy(e, target)).collect(Collectors.toList());  
64 - }  
65 -  
66 default List<BpmTaskTodoPageItemRespVO> convertList1(List<Task> tasks, 34 default List<BpmTaskTodoPageItemRespVO> convertList1(List<Task> tasks,
67 - Map<String, ProcessInstance> processInstanceMap, Map<Long, AdminUserRespDTO> userMap) { 35 + Map<String, ProcessInstance> processInstanceMap,
  36 + Map<Long, AdminUserRespDTO> userMap) {
68 return CollectionUtils.convertList(tasks, task -> { 37 return CollectionUtils.convertList(tasks, task -> {
69 BpmTaskTodoPageItemRespVO respVO = convert1(task); 38 BpmTaskTodoPageItemRespVO respVO = convert1(task);
70 ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId()); 39 ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId());
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java deleted
1 -package cn.iocoder.yudao.module.bpm.dal.dataobject.task;  
2 -  
3 -import com.fasterxml.jackson.annotation.JsonFormat;  
4 -import lombok.*;  
5 -import org.springframework.format.annotation.DateTimeFormat;  
6 -  
7 -import java.time.LocalDateTime;  
8 -  
9 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;  
10 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;  
11 -  
12 -/**  
13 - * 任务流程关联表  
14 - *  
15 - * @author kemengkai  
16 - * @create 2022-05-09 10:33  
17 - */  
18 -@Data  
19 -@AllArgsConstructor  
20 -@NoArgsConstructor  
21 -public class BpmActivityDO {  
22 -  
23 - /**  
24 - * 任务流程关联id  
25 - */  
26 - private String id;  
27 -  
28 - /**  
29 - * 审批结果  
30 - */  
31 - private Integer rev;  
32 -  
33 - /**  
34 - * 任务流程部署id  
35 - */  
36 - private String procDefId;  
37 -  
38 - /**  
39 - * 任务流程id  
40 - */  
41 - private String processInstanceId;  
42 -  
43 - /**  
44 - * 任务执行id  
45 - */  
46 - private String executionId;  
47 -  
48 - /**  
49 - * 任务key  
50 - */  
51 - private String activityId;  
52 -  
53 - /**  
54 - * 任务id  
55 - */  
56 - private String taskId;  
57 -  
58 - /**  
59 - * 调用流程id  
60 - */  
61 - private String callProcInstId;  
62 -  
63 - /**  
64 - * 任务名称  
65 - */  
66 - private String activityName;  
67 -  
68 - /**  
69 - * 任务类型  
70 - */  
71 - private String activityType;  
72 -  
73 - /**  
74 - * 任务审批人id  
75 - */  
76 - private String assignee;  
77 -  
78 - /**  
79 - * 任务开始时间  
80 - */  
81 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
82 - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)  
83 - private LocalDateTime startTime;  
84 -  
85 - /**  
86 - * 任务结束时间  
87 - */  
88 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
89 - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)  
90 - private LocalDateTime endTime;  
91 -  
92 - private Integer transactionOrder;  
93 -  
94 - private LocalDateTime duration;  
95 -  
96 - /**  
97 - * 删除结果  
98 - */  
99 - private String deleteReason;  
100 -  
101 - /**  
102 - * 租户id  
103 - */  
104 - private String tenantId;  
105 -}  
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenPreviewRespVO.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo; @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo;
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 4 import lombok.Data;
5 5
6 -@Schema(description = "管理后台 - 代码生成预览 Response VO,注意,每个文件都是一个该对象") 6 +@Schema(description = "管理后台 - 代码生成预览 Response VO,注意,每个文件都是一个该对象")
7 @Data 7 @Data
8 public class CodegenPreviewRespVO { 8 public class CodegenPreviewRespVO {
9 9
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java
@@ -70,7 +70,7 @@ public class CodegenColumnBaseVO { @@ -70,7 +70,7 @@ public class CodegenColumnBaseVO {
70 @NotNull(message = "是否为 List 查询操作的字段不能为空") 70 @NotNull(message = "是否为 List 查询操作的字段不能为空")
71 private Boolean listOperation; 71 private Boolean listOperation;
72 72
73 - @Schema(description = "List 查询操作的条件类型,参见 CodegenColumnListConditionEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "LIKE") 73 + @Schema(description = "List 查询操作的条件类型,参见 CodegenColumnListConditionEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "LIKE")
74 @NotNull(message = "List 查询操作的条件类型不能为空") 74 @NotNull(message = "List 查询操作的条件类型不能为空")
75 private String listOperationCondition; 75 private String listOperationCondition;
76 76
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java
@@ -12,7 +12,7 @@ import javax.validation.constraints.NotNull; @@ -12,7 +12,7 @@ import javax.validation.constraints.NotNull;
12 @Data 12 @Data
13 public class CodegenTableBaseVO { 13 public class CodegenTableBaseVO {
14 14
15 - @Schema(description = "生成场景,参见 CodegenSceneEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 15 + @Schema(description = "生成场景,参见 CodegenSceneEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
16 @NotNull(message = "导入类型不能为空") 16 @NotNull(message = "导入类型不能为空")
17 private Integer scene; 17 private Integer scene;
18 18
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java
@@ -17,13 +17,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -17,13 +17,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
17 @ToString(callSuper = true) 17 @ToString(callSuper = true)
18 public class CodegenTablePageReqVO extends PageParam { 18 public class CodegenTablePageReqVO extends PageParam {
19 19
20 - @Schema(description = "表名称,模糊匹配", example = "yudao") 20 + @Schema(description = "表名称,模糊匹配", example = "yudao")
21 private String tableName; 21 private String tableName;
22 22
23 - @Schema(description = "表描述,模糊匹配", example = "芋道") 23 + @Schema(description = "表描述,模糊匹配", example = "芋道")
24 private String tableComment; 24 private String tableComment;
25 25
26 - @Schema(description = "实体,模糊匹配", example = "Yudao") 26 + @Schema(description = "实体,模糊匹配", example = "Yudao")
27 private String className; 27 private String className;
28 28
29 @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") 29 @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java
@@ -15,10 +15,10 @@ public class ConfigExportReqVO { @@ -15,10 +15,10 @@ public class ConfigExportReqVO {
15 @Schema(description = "参数名称", example = "模糊匹配") 15 @Schema(description = "参数名称", example = "模糊匹配")
16 private String name; 16 private String name;
17 17
18 - @Schema(description = "参数键名,模糊匹配", example = "yunai.db.username") 18 + @Schema(description = "参数键名,模糊匹配", example = "yunai.db.username")
19 private String key; 19 private String key;
20 20
21 - @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1") 21 + @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1")
22 private Integer type; 22 private Integer type;
23 23
24 @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") 24 @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java
@@ -17,13 +17,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -17,13 +17,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
17 @ToString(callSuper = true) 17 @ToString(callSuper = true)
18 public class ConfigPageReqVO extends PageParam { 18 public class ConfigPageReqVO extends PageParam {
19 19
20 - @Schema(description = "数据源名称,模糊匹配", example = "名称") 20 + @Schema(description = "数据源名称,模糊匹配", example = "名称")
21 private String name; 21 private String name;
22 22
23 - @Schema(description = "参数键名,模糊匹配", example = "yunai.db.username") 23 + @Schema(description = "参数键名,模糊匹配", example = "yunai.db.username")
24 private String key; 24 private String key;
25 25
26 - @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1") 26 + @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1")
27 private Integer type; 27 private Integer type;
28 28
29 @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") 29 @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java
@@ -21,7 +21,7 @@ public class ConfigRespVO extends ConfigBaseVO { @@ -21,7 +21,7 @@ public class ConfigRespVO extends ConfigBaseVO {
21 @Size(max = 100, message = "参数键名长度不能超过100个字符") 21 @Size(max = 100, message = "参数键名长度不能超过100个字符")
22 private String key; 22 private String key;
23 23
24 - @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 24 + @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
25 private Integer type; 25 private Integer type;
26 26
27 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") 27 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java
@@ -14,7 +14,7 @@ import java.util.Map; @@ -14,7 +14,7 @@ import java.util.Map;
14 @ToString(callSuper = true) 14 @ToString(callSuper = true)
15 public class FileConfigCreateReqVO extends FileConfigBaseVO { 15 public class FileConfigCreateReqVO extends FileConfigBaseVO {
16 16
17 - @Schema(description = "存储器,参见 FileStorageEnum 枚举类参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 17 + @Schema(description = "存储器,参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
18 @NotNull(message = "存储器不能为空") 18 @NotNull(message = "存储器不能为空")
19 private Integer storage; 19 private Integer storage;
20 20
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java
@@ -23,8 +23,8 @@ public class FileConfigPageReqVO extends PageParam { @@ -23,8 +23,8 @@ public class FileConfigPageReqVO extends PageParam {
23 @Schema(description = "存储器", example = "1") 23 @Schema(description = "存储器", example = "1")
24 private Integer storage; 24 private Integer storage;
25 25
  26 + @Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
26 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 27 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
27 - @Schema(description = "创建时间")  
28 private LocalDateTime[] createTime; 28 private LocalDateTime[] createTime;
29 29
30 } 30 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java
@@ -18,7 +18,7 @@ public class FileConfigRespVO extends FileConfigBaseVO { @@ -18,7 +18,7 @@ public class FileConfigRespVO extends FileConfigBaseVO {
18 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 18 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
19 private Long id; 19 private Long id;
20 20
21 - @Schema(description = "存储器,参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 21 + @Schema(description = "存储器,参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
22 @NotNull(message = "存储器不能为空") 22 @NotNull(message = "存储器不能为空")
23 private Integer storage; 23 private Integer storage;
24 24
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
@@ -17,14 +17,14 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -17,14 +17,14 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
17 @ToString(callSuper = true) 17 @ToString(callSuper = true)
18 public class FilePageReqVO extends PageParam { 18 public class FilePageReqVO extends PageParam {
19 19
20 - @Schema(description = "文件路径,模糊匹配", example = "yudao") 20 + @Schema(description = "文件路径,模糊匹配", example = "yudao")
21 private String path; 21 private String path;
22 22
23 - @Schema(description = "文件类型,模糊匹配", example = "application/octet-stream") 23 + @Schema(description = "文件类型,模糊匹配", example = "jpg")
24 private String type; 24 private String type;
25 25
  26 + @Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
26 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 27 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
27 - @Schema(description = "创建时间")  
28 private LocalDateTime[] createTime; 28 private LocalDateTime[] createTime;
29 29
30 } 30 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java
@@ -12,13 +12,13 @@ import lombok.ToString; @@ -12,13 +12,13 @@ import lombok.ToString;
12 @ToString(callSuper = true) 12 @ToString(callSuper = true)
13 public class JobPageReqVO extends PageParam { 13 public class JobPageReqVO extends PageParam {
14 14
15 - @Schema(description = "任务名称,模糊匹配", example = "测试任务") 15 + @Schema(description = "任务名称,模糊匹配", example = "测试任务")
16 private String name; 16 private String name;
17 17
18 - @Schema(description = "任务状态,参见 JobStatusEnum 枚举", example = "1") 18 + @Schema(description = "任务状态,参见 JobStatusEnum 枚举", example = "1")
19 private Integer status; 19 private Integer status;
20 20
21 - @Schema(description = "处理器的名字,模糊匹配", example = "sysUserSessionTimeoutJob") 21 + @Schema(description = "处理器的名字,模糊匹配", example = "sysUserSessionTimeoutJob")
22 private String handlerName; 22 private String handlerName;
23 23
24 } 24 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java
@@ -43,7 +43,7 @@ public class JobLogBaseVO { @@ -43,7 +43,7 @@ public class JobLogBaseVO {
43 @Schema(description = "执行时长", example = "123") 43 @Schema(description = "执行时长", example = "123")
44 private Integer duration; 44 private Integer duration;
45 45
46 - @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 46 + @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
47 @NotNull(message = "任务状态不能为空") 47 @NotNull(message = "任务状态不能为空")
48 private Integer status; 48 private Integer status;
49 49
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java
@@ -8,14 +8,14 @@ import java.time.LocalDateTime; @@ -8,14 +8,14 @@ import java.time.LocalDateTime;
8 8
9 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 9 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
10 10
11 -@Schema(description = "管理后台 - 定时任务 Excel 导出 Request VO,参数和 JobLogPageReqVO 是一致的") 11 +@Schema(description = "管理后台 - 定时任务 Excel 导出 Request VO,参数和 JobLogPageReqVO 是一致的")
12 @Data 12 @Data
13 public class JobLogExportReqVO { 13 public class JobLogExportReqVO {
14 14
15 @Schema(description = "任务编号", example = "10") 15 @Schema(description = "任务编号", example = "10")
16 private Long jobId; 16 private Long jobId;
17 17
18 - @Schema(description = "处理器的名字,模糊匹配") 18 + @Schema(description = "处理器的名字,模糊匹配")
19 private String handlerName; 19 private String handlerName;
20 20
21 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 21 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@@ -26,7 +26,7 @@ public class JobLogExportReqVO { @@ -26,7 +26,7 @@ public class JobLogExportReqVO {
26 @Schema(description = "结束执行时间") 26 @Schema(description = "结束执行时间")
27 private LocalDateTime endTime; 27 private LocalDateTime endTime;
28 28
29 - @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举") 29 + @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举")
30 private Integer status; 30 private Integer status;
31 31
32 } 32 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java
@@ -20,7 +20,7 @@ public class JobLogPageReqVO extends PageParam { @@ -20,7 +20,7 @@ public class JobLogPageReqVO extends PageParam {
20 @Schema(description = "任务编号", example = "10") 20 @Schema(description = "任务编号", example = "10")
21 private Long jobId; 21 private Long jobId;
22 22
23 - @Schema(description = "处理器的名字,模糊匹配") 23 + @Schema(description = "处理器的名字,模糊匹配")
24 private String handlerName; 24 private String handlerName;
25 25
26 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 26 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@@ -31,7 +31,7 @@ public class JobLogPageReqVO extends PageParam { @@ -31,7 +31,7 @@ public class JobLogPageReqVO extends PageParam {
31 @Schema(description = "结束执行时间") 31 @Schema(description = "结束执行时间")
32 private LocalDateTime endTime; 32 private LocalDateTime endTime;
33 33
34 - @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举") 34 + @Schema(description = "任务状态,参见 JobLogStatusEnum 枚举")
35 private Integer status; 35 private Integer status;
36 36
37 } 37 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java
@@ -24,7 +24,7 @@ public class ApiAccessLogBaseVO { @@ -24,7 +24,7 @@ public class ApiAccessLogBaseVO {
24 @NotNull(message = "用户编号不能为空") 24 @NotNull(message = "用户编号不能为空")
25 private Long userId; 25 private Long userId;
26 26
27 - @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") 27 + @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
28 @NotNull(message = "用户类型不能为空") 28 @NotNull(message = "用户类型不能为空")
29 private Integer userType; 29 private Integer userType;
30 30
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java
@@ -8,7 +8,7 @@ import java.time.LocalDateTime; @@ -8,7 +8,7 @@ import java.time.LocalDateTime;
8 8
9 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 9 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
10 10
11 -@Schema(description = "管理后台 - API 访问日志 Excel 导出 Request VO,参数和 ApiAccessLogPageReqVO 是一致的") 11 +@Schema(description = "管理后台 - API 访问日志 Excel 导出 Request VO,参数和 ApiAccessLogPageReqVO 是一致的")
12 @Data 12 @Data
13 public class ApiAccessLogExportReqVO { 13 public class ApiAccessLogExportReqVO {
14 14
@@ -21,11 +21,11 @@ public class ApiAccessLogExportReqVO { @@ -21,11 +21,11 @@ public class ApiAccessLogExportReqVO {
21 @Schema(description = "应用名", example = "dashboard") 21 @Schema(description = "应用名", example = "dashboard")
22 private String applicationName; 22 private String applicationName;
23 23
24 - @Schema(description = "请求地址,模糊匹配", example = "/xxx/yyy") 24 + @Schema(description = "请求地址,模糊匹配", example = "/xxx/yyy")
25 private String requestUrl; 25 private String requestUrl;
26 26
  27 + @Schema(description = "开始时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
27 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 28 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
28 - @Schema(description = "开始请求时间")  
29 private LocalDateTime[] beginTime; 29 private LocalDateTime[] beginTime;
30 30
31 @Schema(description = "执行时长,大于等于,单位:毫秒", example = "100") 31 @Schema(description = "执行时长,大于等于,单位:毫秒", example = "100")
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java
@@ -26,11 +26,11 @@ public class ApiAccessLogPageReqVO extends PageParam { @@ -26,11 +26,11 @@ public class ApiAccessLogPageReqVO extends PageParam {
26 @Schema(description = "应用名", example = "dashboard") 26 @Schema(description = "应用名", example = "dashboard")
27 private String applicationName; 27 private String applicationName;
28 28
29 - @Schema(description = "请求地址,模糊匹配", example = "/xxx/yyy") 29 + @Schema(description = "请求地址,模糊匹配", example = "/xxx/yyy")
30 private String requestUrl; 30 private String requestUrl;
31 31
  32 + @Schema(description = "开始时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
32 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 33 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
33 - @Schema(description = "开始请求时间")  
34 private LocalDateTime[] beginTime; 34 private LocalDateTime[] beginTime;
35 35
36 @Schema(description = "执行时长,大于等于,单位:毫秒", example = "100") 36 @Schema(description = "执行时长,大于等于,单位:毫秒", example = "100")
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java
@@ -8,7 +8,7 @@ import java.time.LocalDateTime; @@ -8,7 +8,7 @@ import java.time.LocalDateTime;
8 8
9 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 9 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
10 10
11 -@Schema(description = "管理后台 - API 错误日志 Excel 导出 Request VO,参数和 ApiErrorLogPageReqVO 是一致的") 11 +@Schema(description = "管理后台 - API 错误日志 Excel 导出 Request VO,参数和 ApiErrorLogPageReqVO 是一致的")
12 @Data 12 @Data
13 public class ApiErrorLogExportReqVO { 13 public class ApiErrorLogExportReqVO {
14 14
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java
@@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat; @@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat;
7 7
8 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 8 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
9 9
10 -@Schema(description = "管理后台 - 字典类型 Excel 导出 Request VO,参数和 TestDemoPageReqVO 是一致的") 10 +@Schema(description = "管理后台 - 字典类型 Excel 导出 Request VO,参数和 TestDemoPageReqVO 是一致的")
11 @Data 11 @Data
12 public class TestDemoExportReqVO { 12 public class TestDemoExportReqVO {
13 13
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java
@@ -57,7 +57,7 @@ public class DatabaseTableServiceImpl implements DatabaseTableService { @@ -57,7 +57,7 @@ public class DatabaseTableServiceImpl implements DatabaseTableService {
57 strategyConfig.addExclude("ACT_[\\S\\s]+|QRTZ_[\\S\\s]+|FLW_[\\S\\s]+"); 57 strategyConfig.addExclude("ACT_[\\S\\s]+|QRTZ_[\\S\\s]+|FLW_[\\S\\s]+");
58 } 58 }
59 59
60 - GlobalConfig globalConfig = new GlobalConfig.Builder().dateType(DateType.TIME_PACK).build(); // 只使用 Date 类型,不使用 LocalDate 60 + GlobalConfig globalConfig = new GlobalConfig.Builder().dateType(DateType.TIME_PACK).build(); // 只使用 LocalDateTime 类型,不使用 LocalDate
61 ConfigBuilder builder = new ConfigBuilder(null, dataSourceConfig, strategyConfig.build(), 61 ConfigBuilder builder = new ConfigBuilder(null, dataSourceConfig, strategyConfig.build(),
62 null, globalConfig, null); 62 null, globalConfig, null);
63 // 按照名字排序 63 // 按照名字排序
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java
@@ -79,7 +79,7 @@ public class TestDemoServiceImpl implements TestDemoService { @@ -79,7 +79,7 @@ public class TestDemoServiceImpl implements TestDemoService {
79 79
80 @Override 80 @Override
81 public PageResult<TestDemoDO> getTestDemoPage(TestDemoPageReqVO pageReqVO) { 81 public PageResult<TestDemoDO> getTestDemoPage(TestDemoPageReqVO pageReqVO) {
82 - testDemoMapper.selectList2(); 82 +// testDemoMapper.selectList2();
83 return testDemoMapper.selectPage(pageReqVO); 83 return testDemoMapper.selectPage(pageReqVO);
84 } 84 }
85 85
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
@@ -30,14 +30,13 @@ public interface ProductSkuApi { @@ -30,14 +30,13 @@ public interface ProductSkuApi {
30 */ 30 */
31 List<ProductSkuRespDTO> getSkuList(Collection<Long> ids); 31 List<ProductSkuRespDTO> getSkuList(Collection<Long> ids);
32 32
33 - // TODO puhui999:入参用 Collection<Long> 更通用  
34 /** 33 /**
35 * 批量查询 SKU 数组 34 * 批量查询 SKU 数组
36 * 35 *
37 * @param spuIds SPU 编号列表 36 * @param spuIds SPU 编号列表
38 * @return SKU 数组 37 * @return SKU 数组
39 */ 38 */
40 - List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds); 39 + List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds);
41 40
42 /** 41 /**
43 * 更新 SKU 库存 42 * 更新 SKU 库存
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
@@ -45,10 +45,8 @@ public interface ErrorCodeConstants { @@ -45,10 +45,8 @@ public interface ErrorCodeConstants {
45 ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足"); 45 ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
46 46
47 // ========== 商品 评价 1008007000 ========== 47 // ========== 商品 评价 1008007000 ==========
48 - ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品 评价 不存在");  
49 - ErrorCode ORDER_SPU_COMMENT_EXISTS = new ErrorCode(1008007001, "订单 商品评价 已存在");  
50 - ErrorCode COMMENT_ERROR_OPT = new ErrorCode(1008007002, "商品评价非法操作");  
51 - ErrorCode COMMENT_ADDITIONAL_EXISTS = new ErrorCode(1008007003, "商品追加评价已存在"); 48 + ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品评价不存在");
  49 + ErrorCode COMMENT_ORDER_EXISTS = new ErrorCode(1008007001, "订单的商品评价已存在");
52 50
53 // ========== 商品 收藏 1008008000 ========== 51 // ========== 商品 收藏 1008008000 ==========
54 ErrorCode FAVORITE_EXISTS = new ErrorCode(1008008000, "该商品已经被收藏"); 52 ErrorCode FAVORITE_EXISTS = new ErrorCode(1008008000, "该商品已经被收藏");
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
@@ -43,7 +43,7 @@ public class ProductSkuApiImpl implements ProductSkuApi { @@ -43,7 +43,7 @@ public class ProductSkuApiImpl implements ProductSkuApi {
43 } 43 }
44 44
45 @Override 45 @Override
46 - public List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds) { 46 + public List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds) {
47 if (CollUtil.isEmpty(spuIds)) { 47 if (CollUtil.isEmpty(spuIds)) {
48 return Collections.emptyList(); 48 return Collections.emptyList();
49 } 49 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java
@@ -26,23 +26,10 @@ public class ProductCommentBaseVO { @@ -26,23 +26,10 @@ public class ProductCommentBaseVO {
26 @NotNull(message = "评价人头像不能为空") 26 @NotNull(message = "评价人头像不能为空")
27 private String userAvatar; 27 private String userAvatar;
28 28
29 - // TODO @puhui:spuId、spuName 是不是只有 ProductCommentRespVO 有呀。  
30 - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖")  
31 - @NotNull(message = "商品 SPU 编号不能为空")  
32 - private Long spuId;  
33 -  
34 - @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")  
35 - @NotNull(message = "商品 SPU 名称不能为空")  
36 - private String spuName;  
37 -  
38 @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 29 @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
39 @NotNull(message = "商品 SKU 编号不能为空") 30 @NotNull(message = "商品 SKU 编号不能为空")
40 private Long skuId; 31 private Long skuId;
41 32
42 - @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")  
43 - @NotNull(message = "评分星级不能为空")  
44 - private Integer scores;  
45 -  
46 @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") 33 @Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
47 @NotNull(message = "描述星级不能为空") 34 @NotNull(message = "描述星级不能为空")
48 private Integer descriptionScores; 35 private Integer descriptionScores;
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java
@@ -35,9 +35,8 @@ public class ProductCommentPageReqVO extends PageParam { @@ -35,9 +35,8 @@ public class ProductCommentPageReqVO extends PageParam {
35 @InEnum(ProductCommentScoresEnum.class) 35 @InEnum(ProductCommentScoresEnum.class)
36 private Integer scores; 36 private Integer scores;
37 37
38 - // TODO @puhui999:replyStatus 哈  
39 @Schema(description = "商家是否回复", example = "true") 38 @Schema(description = "商家是否回复", example = "true")
40 - private Boolean replied; 39 + private Boolean replyStatus;
41 40
42 @Schema(description = "创建时间") 41 @Schema(description = "创建时间")
43 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 42 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java
@@ -5,6 +5,7 @@ import lombok.Data; @@ -5,6 +5,7 @@ import lombok.Data;
5 import lombok.EqualsAndHashCode; 5 import lombok.EqualsAndHashCode;
6 import lombok.ToString; 6 import lombok.ToString;
7 7
  8 +import javax.validation.constraints.NotNull;
8 import java.time.LocalDateTime; 9 import java.time.LocalDateTime;
9 10
10 @Schema(description = "管理后台 - 商品评价 Response VO") 11 @Schema(description = "管理后台 - 商品评价 Response VO")
@@ -40,4 +41,15 @@ public class ProductCommentRespVO extends ProductCommentBaseVO { @@ -40,4 +41,15 @@ public class ProductCommentRespVO extends ProductCommentBaseVO {
40 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 41 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
41 private LocalDateTime createTime; 42 private LocalDateTime createTime;
42 43
  44 + @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
  45 + private Integer scores;
  46 +
  47 + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖")
  48 + @NotNull(message = "商品 SPU 编号不能为空")
  49 + private Long spuId;
  50 +
  51 + @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
  52 + @NotNull(message = "商品 SPU 名称不能为空")
  53 + private String spuName;
  54 +
43 } 55 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
@@ -21,6 +21,7 @@ import javax.annotation.Resource; @@ -21,6 +21,7 @@ import javax.annotation.Resource;
21 import javax.servlet.http.HttpServletResponse; 21 import javax.servlet.http.HttpServletResponse;
22 import javax.validation.Valid; 22 import javax.validation.Valid;
23 import java.io.IOException; 23 import java.io.IOException;
  24 +import java.util.Collection;
24 import java.util.List; 25 import java.util.List;
25 import java.util.Map; 26 import java.util.Map;
26 27
@@ -29,11 +30,6 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -29,11 +30,6 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
29 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 30 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
30 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; 31 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
31 32
32 -/**  
33 - * 商品 SPU 相关接口  
34 - *  
35 - * @author HUIHUI  
36 - */  
37 @Tag(name = "管理后台 - 商品 SPU") 33 @Tag(name = "管理后台 - 商品 SPU")
38 @RestController 34 @RestController
39 @RequestMapping("/product/spu") 35 @RequestMapping("/product/spu")
@@ -100,6 +96,15 @@ public class ProductSpuController { @@ -100,6 +96,15 @@ public class ProductSpuController {
100 return success(ProductSpuConvert.INSTANCE.convertList02(list)); 96 return success(ProductSpuConvert.INSTANCE.convertList02(list));
101 } 97 }
102 98
  99 + @GetMapping("/list")
  100 + @Operation(summary = "获得商品 SPU 详情列表")
  101 + @Parameter(name = "spuIds", description = "spu 编号列表", required = true, example = "[1,2,3]")
  102 + @PreAuthorize("@ss.hasPermission('product:spu:query')")
  103 + public CommonResult<List<ProductSpuDetailRespVO>> getSpuList(@RequestParam("spuIds") Collection<Long> spuIds) {
  104 + return success(ProductSpuConvert.INSTANCE.convertForSpuDetailRespListVO(
  105 + productSpuService.getSpuList(spuIds), productSkuService.getSkuListBySpuId(spuIds)));
  106 + }
  107 +
103 @GetMapping("/page") 108 @GetMapping("/page")
104 @Operation(summary = "获得商品 SPU 分页") 109 @Operation(summary = "获得商品 SPU 分页")
105 @PreAuthorize("@ss.hasPermission('product:spu:query')") 110 @PreAuthorize("@ss.hasPermission('product:spu:query')")
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
@@ -9,11 +9,6 @@ import lombok.ToString; @@ -9,11 +9,6 @@ import lombok.ToString;
9 import javax.validation.Valid; 9 import javax.validation.Valid;
10 import java.util.List; 10 import java.util.List;
11 11
12 -/**  
13 - * 商品 SPU 创建 Request VO  
14 - *  
15 - * @author HUIHUI  
16 - */  
17 @Schema(description = "管理后台 - 商品 SPU 创建 Request VO") 12 @Schema(description = "管理后台 - 商品 SPU 创建 Request VO")
18 @Data 13 @Data
19 @EqualsAndHashCode(callSuper = true) 14 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
@@ -8,12 +8,6 @@ import lombok.ToString; @@ -8,12 +8,6 @@ import lombok.ToString;
8 8
9 import java.util.List; 9 import java.util.List;
10 10
11 -/**  
12 - * 商品 SPU 详细 Response VO  
13 - * 包括关联的 SKU 等信息  
14 - *  
15 - * @author HUIHUI  
16 - */  
17 @Schema(description = "管理后台 - 商品 SPU 详细 Response VO") 11 @Schema(description = "管理后台 - 商品 SPU 详细 Response VO")
18 @Data 12 @Data
19 @EqualsAndHashCode(callSuper = true) 13 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuExportReqVO.java
@@ -10,12 +10,7 @@ import java.time.LocalDateTime; @@ -10,12 +10,7 @@ import java.time.LocalDateTime;
10 10
11 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 11 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
12 12
13 -/**  
14 - * 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的  
15 - *  
16 - * @author HUIHUI  
17 - */  
18 -@Schema(description = "管理后台 - 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的") 13 +@Schema(description = "管理后台 - 商品 SPU 导出 Request VO,参数和 ProductSpuPageReqVO 是一致的")
19 @Data 14 @Data
20 @NoArgsConstructor 15 @NoArgsConstructor
21 @AllArgsConstructor 16 @AllArgsConstructor
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
@@ -11,11 +11,6 @@ import java.time.LocalDateTime; @@ -11,11 +11,6 @@ import java.time.LocalDateTime;
11 11
12 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 12 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
13 13
14 -/**  
15 - * 商品 SPU 分页 Request VO  
16 - *  
17 - * @author HUIHUI  
18 - */  
19 @Schema(description = "管理后台 - 商品 SPU 分页 Request VO") 14 @Schema(description = "管理后台 - 商品 SPU 分页 Request VO")
20 @Data 15 @Data
21 @EqualsAndHashCode(callSuper = true) 16 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
@@ -7,11 +7,6 @@ import lombok.ToString; @@ -7,11 +7,6 @@ import lombok.ToString;
7 7
8 import java.time.LocalDateTime; 8 import java.time.LocalDateTime;
9 9
10 -/**  
11 - * 商品 SPU Response VO  
12 - *  
13 - * @author HUIHUI  
14 - */  
15 @Schema(description = "管理后台 - 商品 SPU Response VO") 10 @Schema(description = "管理后台 - 商品 SPU Response VO")
16 @Data 11 @Data
17 @EqualsAndHashCode(callSuper = true) 12 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java
@@ -4,11 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema; @@ -4,11 +4,6 @@ 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 -/**  
8 - * 商品 SPU 精简 Response VO  
9 - * TODO 商品 SPU 精简 VO 暂时没有使用到,用到的时候再按需添加\修改属性  
10 - * @author HUIHUI  
11 - */  
12 @Schema(description = "管理后台 - 商品 SPU 精简 Response VO") 7 @Schema(description = "管理后台 - 商品 SPU 精简 Response VO")
13 @Data 8 @Data
14 @ToString(callSuper = true) 9 @ToString(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java
@@ -12,11 +12,6 @@ import javax.validation.Valid; @@ -12,11 +12,6 @@ import javax.validation.Valid;
12 import javax.validation.constraints.NotNull; 12 import javax.validation.constraints.NotNull;
13 import java.util.List; 13 import java.util.List;
14 14
15 -/**  
16 - * 商品 SPU 更新 Request VO  
17 - *  
18 - * @author HUIHUI  
19 - */  
20 @Schema(description = "管理后台 - 商品 SPU 更新 Request VO") 15 @Schema(description = "管理后台 - 商品 SPU 更新 Request VO")
21 @Data 16 @Data
22 @EqualsAndHashCode(callSuper = true) 17 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java
@@ -7,11 +7,6 @@ import lombok.Data; @@ -7,11 +7,6 @@ import lombok.Data;
7 7
8 import javax.validation.constraints.NotNull; 8 import javax.validation.constraints.NotNull;
9 9
10 -/**  
11 - * 商品 SPU Status 更新 Request VO  
12 - *  
13 - * @author HUIHUI  
14 - */  
15 @Schema(description = "管理后台 - 商品 SPU Status 更新 Request VO") 10 @Schema(description = "管理后台 - 商品 SPU Status 更新 Request VO")
16 @Data 11 @Data
17 public class ProductSpuUpdateStatusReqVO{ 12 public class ProductSpuUpdateStatusReqVO{
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java
1 package cn.iocoder.yudao.module.product.controller.app.comment; 1 package cn.iocoder.yudao.module.product.controller.app.comment;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.util.ObjectUtil;  
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 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.CollectionUtils;
7 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; 7 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
8 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO; 8 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
9 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO; 9 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
10 -import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;  
11 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; 10 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
12 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; 11 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
13 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 12 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
14 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; 13 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
15 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; 14 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
  15 +import com.google.common.collect.Maps;
16 import io.swagger.v3.oas.annotations.Operation; 16 import io.swagger.v3.oas.annotations.Operation;
17 import io.swagger.v3.oas.annotations.Parameter; 17 import io.swagger.v3.oas.annotations.Parameter;
18 import io.swagger.v3.oas.annotations.Parameters; 18 import io.swagger.v3.oas.annotations.Parameters;
@@ -26,11 +26,9 @@ import org.springframework.web.bind.annotation.RestController; @@ -26,11 +26,9 @@ import org.springframework.web.bind.annotation.RestController;
26 26
27 import javax.annotation.Resource; 27 import javax.annotation.Resource;
28 import javax.validation.Valid; 28 import javax.validation.Valid;
29 -import java.util.HashMap;  
30 import java.util.List; 29 import java.util.List;
31 import java.util.Map; 30 import java.util.Map;
32 import java.util.Set; 31 import java.util.Set;
33 -import java.util.stream.Collectors;  
34 32
35 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 33 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
36 34
@@ -53,34 +51,24 @@ public class AppProductCommentController { @@ -53,34 +51,24 @@ public class AppProductCommentController {
53 @Parameter(name = "spuId", description = "商品 SPU 编号", required = true, example = "1024"), 51 @Parameter(name = "spuId", description = "商品 SPU 编号", required = true, example = "1024"),
54 @Parameter(name = "count", description = "数量", required = true, example = "10") 52 @Parameter(name = "count", description = "数量", required = true, example = "10")
55 }) 53 })
56 - public CommonResult<List<AppProductCommentRespVO>> getCommentList(@RequestParam("spuId") Long spuId,  
57 - @RequestParam(value = "count", defaultValue = "10") Integer count) { 54 + public CommonResult<List<AppProductCommentRespVO>> getCommentList(
  55 + @RequestParam("spuId") Long spuId,
  56 + @RequestParam(value = "count", defaultValue = "10") Integer count) {
58 return success(productCommentService.getCommentList(spuId, count)); 57 return success(productCommentService.getCommentList(spuId, count));
59 } 58 }
60 59
61 @GetMapping("/page") 60 @GetMapping("/page")
62 @Operation(summary = "获得商品评价分页") 61 @Operation(summary = "获得商品评价分页")
63 public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) { 62 public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
64 - PageResult<AppProductCommentRespVO> page = productCommentService.getCommentPage(pageVO, Boolean.TRUE);  
65 - // TODO @puhui CollUtils 有简化 convertmap 和 list 的方法  
66 - Set<Long> skuIds = page.getList().stream().map(AppProductCommentRespVO::getSkuId).collect(Collectors.toSet()); 63 + // TODO @puhui999:写到 convert 里,可以更简洁哈。
  64 + PageResult<ProductCommentDO> commentDOPage = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
  65 + Set<Long> skuIds = CollectionUtils.convertSet(commentDOPage.getList(), ProductCommentDO::getSkuId);
67 List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds); 66 List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds);
68 - Map<Long, ProductSkuDO> skuDOMap = new HashMap<>(skuIds.size()); 67 + Map<Long, ProductSkuDO> skuDOMap = Maps.newLinkedHashMapWithExpectedSize(skuIds.size());
69 if (CollUtil.isNotEmpty(skuList)) { 68 if (CollUtil.isNotEmpty(skuList)) {
70 - skuDOMap.putAll(skuList.stream().collect(Collectors.toMap(ProductSkuDO::getId, c -> c))); 69 + skuDOMap.putAll(CollectionUtils.convertMap(skuList, ProductSkuDO::getId, c -> c));
71 } 70 }
72 - // TODO @puihui999:下面也可以放到 convert 里哈  
73 - page.getList().forEach(item -> {  
74 - // 判断用户是否选择匿名  
75 - if (ObjectUtil.equal(item.getAnonymous(), true)) {  
76 - item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);  
77 - }  
78 - ProductSkuDO productSkuDO = skuDOMap.get(item.getSkuId());  
79 - if (productSkuDO != null) {  
80 - List<AppProductPropertyValueDetailRespVO> skuProperties = ProductCommentConvert.INSTANCE.convertList01(productSkuDO.getProperties());  
81 - item.setSkuProperties(skuProperties);  
82 - }  
83 - }); 71 + PageResult<AppProductCommentRespVO> page = ProductCommentConvert.INSTANCE.convertPage02(commentDOPage, skuDOMap);
84 return success(page); 72 return success(page);
85 } 73 }
86 74
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java
@@ -10,11 +10,6 @@ import javax.validation.constraints.Size; @@ -10,11 +10,6 @@ import javax.validation.constraints.Size;
10 import java.time.LocalDateTime; 10 import java.time.LocalDateTime;
11 import java.util.List; 11 import java.util.List;
12 12
13 -/**  
14 - * 用户 App - 商品评价详情 Response VO  
15 - *  
16 - * @author HUIHUI  
17 - */  
18 @Schema(description = "用户 App - 商品评价详情 Response VO") 13 @Schema(description = "用户 App - 商品评价详情 Response VO")
19 @Data 14 @Data
20 @ToString(callSuper = true) 15 @ToString(callSuper = true)
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java
1 package cn.iocoder.yudao.module.product.convert.comment; 1 package cn.iocoder.yudao.module.product.convert.comment;
2 2
  3 +import cn.hutool.core.util.ObjectUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
4 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 6 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
5 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; 7 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
6 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO; 8 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO;
@@ -19,6 +21,7 @@ import org.mapstruct.factory.Mappers; @@ -19,6 +21,7 @@ import org.mapstruct.factory.Mappers;
19 import java.math.BigDecimal; 21 import java.math.BigDecimal;
20 import java.math.RoundingMode; 22 import java.math.RoundingMode;
21 import java.util.List; 23 import java.util.List;
  24 +import java.util.Map;
22 25
23 /** 26 /**
24 * 商品评价 Convert 27 * 商品评价 Convert
@@ -32,19 +35,33 @@ public interface ProductCommentConvert { @@ -32,19 +35,33 @@ public interface ProductCommentConvert {
32 35
33 ProductCommentRespVO convert(ProductCommentDO bean); 36 ProductCommentRespVO convert(ProductCommentDO bean);
34 37
35 - // TODO @puhui999:这里貌似字段对上,就不用 mapping 了;可以测试下看看哈  
36 - @Mapping(target = "goodCount", source = "goodCount")  
37 - @Mapping(target = "mediocreCount", source = "mediocreCount")  
38 - @Mapping(target = "negativeCount", source = "negativeCount") 38 + @Mapping(target = "scores", expression = "java(calculateOverallScore(goodCount, mediocreCount, negativeCount))")
39 AppCommentStatisticsRespVO convert(Long goodCount, Long mediocreCount, Long negativeCount); 39 AppCommentStatisticsRespVO convert(Long goodCount, Long mediocreCount, Long negativeCount);
40 - 40 + @Named("calculateOverallScore")
  41 + default double calculateOverallScore(long goodCount, long mediocreCount, long negativeCount) {
  42 + return (goodCount * 5 + mediocreCount * 3 + negativeCount) / (double) (goodCount + mediocreCount + negativeCount);
  43 + }
  44 +
41 List<ProductCommentRespVO> convertList(List<ProductCommentDO> list); 45 List<ProductCommentRespVO> convertList(List<ProductCommentDO> list);
42 46
43 - List<AppProductPropertyValueDetailRespVO> convertList01(List<ProductSkuDO.Property> properties);  
44 -  
45 PageResult<ProductCommentRespVO> convertPage(PageResult<ProductCommentDO> page); 47 PageResult<ProductCommentRespVO> convertPage(PageResult<ProductCommentDO> page);
46 48
47 - PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult); 49 + PageResult<AppProductCommentRespVO> convertPage01(PageResult<ProductCommentDO> pageResult);
  50 +
  51 + default PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult,
  52 + Map<Long, ProductSkuDO> skuMap) {
  53 + PageResult<AppProductCommentRespVO> page = convertPage01(pageResult);
  54 + page.getList().forEach(item -> {
  55 + // 判断用户是否选择匿名
  56 + if (ObjectUtil.equal(item.getAnonymous(), true)) {
  57 + item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);
  58 + }
  59 + MapUtils.findAndThen(skuMap, item.getSkuId(),
  60 + sku -> item.setSkuProperties(convertList01(sku.getProperties())));
  61 + });
  62 + return page;
  63 + }
  64 + List<AppProductPropertyValueDetailRespVO> convertList01(List<ProductSkuDO.Property> properties);
48 65
49 /** 66 /**
50 * 计算综合评分 67 * 计算综合评分
@@ -63,14 +80,19 @@ public interface ProductCommentConvert { @@ -63,14 +80,19 @@ public interface ProductCommentConvert {
63 80
64 ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO); 81 ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO);
65 82
66 - @Mapping(target = "scores", expression = "java(convertScores(createReqDTO.getDescriptionScores(), createReqDTO.getBenefitScores()))") 83 + @Mapping(target = "scores",
  84 + expression = "java(convertScores(createReqDTO.getDescriptionScores(), createReqDTO.getBenefitScores()))")
67 default ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO, ProductSpuDO spuDO, MemberUserRespDTO user) { 85 default ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO, ProductSpuDO spuDO, MemberUserRespDTO user) {
68 ProductCommentDO commentDO = convert(createReqDTO); 86 ProductCommentDO commentDO = convert(createReqDTO);
69 - commentDO.setUserId(user.getId());  
70 - commentDO.setUserNickname(user.getNickname());  
71 - commentDO.setUserAvatar(user.getAvatar());  
72 - commentDO.setSpuId(spuDO.getId());  
73 - commentDO.setSpuName(spuDO.getName()); 87 + if (user != null) {
  88 + commentDO.setUserId(user.getId());
  89 + commentDO.setUserNickname(user.getNickname());
  90 + commentDO.setUserAvatar(user.getAvatar());
  91 + }
  92 + if (spuDO != null) {
  93 + commentDO.setSpuId(spuDO.getId());
  94 + commentDO.setSpuName(spuDO.getName());
  95 + }
74 return commentDO; 96 return commentDO;
75 } 97 }
76 98
@@ -78,7 +100,8 @@ public interface ProductCommentConvert { @@ -78,7 +100,8 @@ public interface ProductCommentConvert {
78 @Mapping(target = "orderId", constant = "0L") 100 @Mapping(target = "orderId", constant = "0L")
79 @Mapping(target = "orderItemId", constant = "0L") 101 @Mapping(target = "orderItemId", constant = "0L")
80 @Mapping(target = "anonymous", expression = "java(Boolean.FALSE)") 102 @Mapping(target = "anonymous", expression = "java(Boolean.FALSE)")
81 - @Mapping(target = "scores", expression = "java(convertScores(createReq.getDescriptionScores(), createReq.getBenefitScores()))") 103 + @Mapping(target = "scores",
  104 + expression = "java(convertScores(createReq.getDescriptionScores(), createReq.getBenefitScores()))")
82 ProductCommentDO convert(ProductCommentCreateReqVO createReq); 105 ProductCommentDO convert(ProductCommentCreateReqVO createReq);
83 106
84 List<AppProductCommentRespVO> convertList02(List<ProductCommentDO> list); 107 List<AppProductCommentRespVO> convertList02(List<ProductCommentDO> list);
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
@@ -18,8 +18,10 @@ import org.mapstruct.factory.Mappers; @@ -18,8 +18,10 @@ import org.mapstruct.factory.Mappers;
18 18
19 import java.util.ArrayList; 19 import java.util.ArrayList;
20 import java.util.List; 20 import java.util.List;
  21 +import java.util.Map;
21 22
22 import static cn.hutool.core.util.ObjectUtil.defaultIfNull; 23 import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
  24 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
23 25
24 /** 26 /**
25 * 商品 SPU Convert 27 * 商品 SPU Convert
@@ -107,4 +109,16 @@ public interface ProductSpuConvert { @@ -107,4 +109,16 @@ public interface ProductSpuConvert {
107 return detailRespVO; 109 return detailRespVO;
108 } 110 }
109 111
  112 + default List<ProductSpuDetailRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) {
  113 + List<ProductSpuDetailRespVO> vos = new ArrayList<>(spus.size());
  114 + Map<Long, List<ProductSkuDO>> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId);
  115 + // TODO @puhui999:可以直接使用 CollUtils.convertList
  116 + spus.forEach(spu -> {
  117 + ProductSpuDetailRespVO detailRespVO = convert03(spu);
  118 + detailRespVO.setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId())));
  119 + vos.add(detailRespVO);
  120 + });
  121 + return vos;
  122 + }
  123 +
110 } 124 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
@@ -26,6 +26,7 @@ public interface ProductCommentMapper extends BaseMapperX&lt;ProductCommentDO&gt; { @@ -26,6 +26,7 @@ public interface ProductCommentMapper extends BaseMapperX&lt;ProductCommentDO&gt; {
26 } 26 }
27 27
28 static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) { 28 static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) {
  29 + // TODO @puhui999:是不是不用 apply 拉?直接用 mybatis 的方法就好啦
29 // 构建好评查询语句:好评计算 总评 >= 4 30 // 构建好评查询语句:好评计算 总评 >= 4
30 if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) { 31 if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) {
31 queryWrapper.apply("scores >= 4"); 32 queryWrapper.apply("scores >= 4");
@@ -51,11 +52,11 @@ public interface ProductCommentMapper extends BaseMapperX&lt;ProductCommentDO&gt; { @@ -51,11 +52,11 @@ public interface ProductCommentMapper extends BaseMapperX&lt;ProductCommentDO&gt; {
51 return selectPage(reqVO, queryWrapper); 52 return selectPage(reqVO, queryWrapper);
52 } 53 }
53 54
54 - default ProductCommentDO selectByUserIdAndOrderItemIdAndSpuId(Long userId, Long orderItemId, Long spuId) { 55 + default ProductCommentDO selectByUserIdAndOrderItemIdAndSpuId(Long userId, Long orderItemId, Long skuId) {
55 return selectOne(new LambdaQueryWrapperX<ProductCommentDO>() 56 return selectOne(new LambdaQueryWrapperX<ProductCommentDO>()
56 .eq(ProductCommentDO::getUserId, userId) 57 .eq(ProductCommentDO::getUserId, userId)
57 .eq(ProductCommentDO::getOrderItemId, orderItemId) 58 .eq(ProductCommentDO::getOrderItemId, orderItemId)
58 - .eq(ProductCommentDO::getSpuId, spuId)); 59 + .eq(ProductCommentDO::getSpuId, skuId));
59 } 60 }
60 61
61 default Long selectCountBySpuId(Long spuId, Boolean visible, Integer type) { 62 default Long selectCountBySpuId(Long spuId, Boolean visible, Integer type) {
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java
@@ -54,7 +54,7 @@ public interface ProductCommentService { @@ -54,7 +54,7 @@ public interface ProductCommentService {
54 * @param visible 是否可见 54 * @param visible 是否可见
55 * @return 商品评价分页 55 * @return 商品评价分页
56 */ 56 */
57 - PageResult<AppProductCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible); 57 + PageResult<ProductCommentDO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible);
58 58
59 /** 59 /**
60 * 创建商品评论 60 * 创建商品评论
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
@@ -81,7 +81,7 @@ public class ProductCommentServiceImpl implements ProductCommentService { @@ -81,7 +81,7 @@ public class ProductCommentServiceImpl implements ProductCommentService {
81 @Transactional(rollbackFor = Exception.class) 81 @Transactional(rollbackFor = Exception.class)
82 public void createComment(ProductCommentCreateReqVO createReqVO) { 82 public void createComment(ProductCommentCreateReqVO createReqVO) {
83 // 校验评论 83 // 校验评论
84 - validateComment(createReqVO.getSpuId(), createReqVO.getUserId(), createReqVO.getOrderItemId()); 84 + validateComment(createReqVO.getSkuId(), createReqVO.getUserId(), createReqVO.getOrderItemId());
85 85
86 ProductCommentDO commentDO = ProductCommentConvert.INSTANCE.convert(createReqVO); 86 ProductCommentDO commentDO = ProductCommentConvert.INSTANCE.convert(createReqVO);
87 productCommentMapper.insert(commentDO); 87 productCommentMapper.insert(commentDO);
@@ -108,11 +108,11 @@ public class ProductCommentServiceImpl implements ProductCommentService { @@ -108,11 +108,11 @@ public class ProductCommentServiceImpl implements ProductCommentService {
108 return commentDO.getId(); 108 return commentDO.getId();
109 } 109 }
110 110
111 - private void validateComment(Long spuId, Long userId, Long orderItemId) { 111 + private void validateComment(Long skuId, Long userId, Long orderItemId) {
112 // 判断当前订单的当前商品用户是否评价过 112 // 判断当前订单的当前商品用户是否评价过
113 - ProductCommentDO exist = productCommentMapper.selectByUserIdAndOrderItemIdAndSpuId(userId, orderItemId, spuId); 113 + ProductCommentDO exist = productCommentMapper.selectByUserIdAndOrderItemIdAndSpuId(userId, orderItemId, skuId);
114 if (null != exist) { 114 if (null != exist) {
115 - throw exception(ORDER_SPU_COMMENT_EXISTS); 115 + throw exception(COMMENT_ORDER_EXISTS);
116 } 116 }
117 } 117 }
118 118
@@ -141,23 +141,17 @@ public class ProductCommentServiceImpl implements ProductCommentService { @@ -141,23 +141,17 @@ public class ProductCommentServiceImpl implements ProductCommentService {
141 productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.MEDIOCRE_COMMENT), 141 productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.MEDIOCRE_COMMENT),
142 // 查询商品 id = spuId 的所有差评数量 142 // 查询商品 id = spuId 的所有差评数量
143 productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.NEGATIVE_COMMENT) 143 productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.NEGATIVE_COMMENT)
144 - ).setScores(3.0); // TODO @puhui999:这里要实现下;; 144 + );
145 } 145 }
146 146
147 @Override 147 @Override
148 public List<AppProductCommentRespVO> getCommentList(Long spuId, Integer count) { 148 public List<AppProductCommentRespVO> getCommentList(Long spuId, Integer count) {
149 - // 校验商品 spu 是否存在  
150 - // TODO @puhui 这里校验可以去掉哈。  
151 - ProductSpuDO spuDO = validateSpu(spuId);  
152 - return ProductCommentConvert.INSTANCE.convertList02(productCommentMapper.selectCommentList(spuDO.getId(), count).getList()); 149 + return ProductCommentConvert.INSTANCE.convertList02(productCommentMapper.selectCommentList(spuId, count).getList());
153 } 150 }
154 151
155 - // TODO @puhui 可以放到 controller 去 convert 哈  
156 @Override 152 @Override
157 - public PageResult<AppProductCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {  
158 - // TODO @puhui 可以放到 controller 去 convert 哈  
159 - return ProductCommentConvert.INSTANCE.convertPage02(  
160 - productCommentMapper.selectPage(pageVO, visible)); 153 + public PageResult<ProductCommentDO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {
  154 + return productCommentMapper.selectPage(pageVO, visible);
161 } 155 }
162 156
163 @Override 157 @Override
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
@@ -90,7 +90,7 @@ public interface ProductSkuService { @@ -90,7 +90,7 @@ public interface ProductSkuService {
90 * @param spuIds spu 编码集合 90 * @param spuIds spu 编码集合
91 * @return 商品 sku 集合 91 * @return 商品 sku 集合
92 */ 92 */
93 - List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds); 93 + List<ProductSkuDO> getSkuListBySpuId(Collection<Long> spuIds);
94 94
95 /** 95 /**
96 * 通过 spuId 删除 sku 信息 96 * 通过 spuId 删除 sku 信息
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -148,7 +148,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { @@ -148,7 +148,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
148 } 148 }
149 149
150 @Override 150 @Override
151 - public List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds) { 151 + public List<ProductSkuDO> getSkuListBySpuId(Collection<Long> spuIds) {
152 return productSkuMapper.selectListBySpuId(spuIds); 152 return productSkuMapper.selectListBySpuId(spuIds);
153 } 153 }
154 154
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
@@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen
10 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; 10 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
11 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; 11 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
12 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO; 12 import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
13 -import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;  
14 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; 13 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
15 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; 14 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
16 import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; 15 import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
@@ -128,7 +127,7 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { @@ -128,7 +127,7 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
128 productCommentPageReqVO.setSpuId(spuId); 127 productCommentPageReqVO.setSpuId(spuId);
129 productCommentPageReqVO.setSpuName("感冒药"); 128 productCommentPageReqVO.setSpuName("感冒药");
130 productCommentPageReqVO.setScores(ProductCommentScoresEnum.FOUR.getScores()); 129 productCommentPageReqVO.setScores(ProductCommentScoresEnum.FOUR.getScores());
131 - productCommentPageReqVO.setReplied(Boolean.TRUE); 130 + productCommentPageReqVO.setReplyStatus(Boolean.TRUE);
132 131
133 PageResult<ProductCommentDO> commentPage = productCommentService.getCommentPage(productCommentPageReqVO); 132 PageResult<ProductCommentDO> commentPage = productCommentService.getCommentPage(productCommentPageReqVO);
134 PageResult<ProductCommentRespVO> result = ProductCommentConvert.INSTANCE.convertPage(productCommentMapper.selectPage(productCommentPageReqVO)); 133 PageResult<ProductCommentRespVO> result = ProductCommentConvert.INSTANCE.convertPage(productCommentMapper.selectPage(productCommentPageReqVO));
@@ -138,15 +137,15 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { @@ -138,15 +137,15 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
138 assertEquals(8, all.getTotal()); 137 assertEquals(8, all.getTotal());
139 138
140 // 测试获取所有商品分页评论数据 139 // 测试获取所有商品分页评论数据
141 - PageResult<AppProductCommentRespVO> result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE); 140 + PageResult<ProductCommentDO> result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE);
142 assertEquals(7, result1.getTotal()); 141 assertEquals(7, result1.getTotal());
143 142
144 // 测试获取所有商品分页中评数据 143 // 测试获取所有商品分页中评数据
145 - PageResult<AppProductCommentRespVO> result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE); 144 + PageResult<ProductCommentDO> result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
146 assertEquals(2, result2.getTotal()); 145 assertEquals(2, result2.getTotal());
147 146
148 // 测试获取指定 spuId 商品分页中评数据 147 // 测试获取指定 spuId 商品分页中评数据
149 - PageResult<AppProductCommentRespVO> result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE); 148 + PageResult<ProductCommentDO> result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
150 assertEquals(2, result3.getTotal()); 149 assertEquals(2, result3.getTotal());
151 150
152 // 测试分页 tab count 151 // 测试分页 tab count
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.combination;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;
  4 +
  5 +import javax.validation.Valid;
  6 +
  7 +// TODO @puhui999:CombinationRecordApi 分成活动、记录哈
  8 +// TODO @芋艿:后面也再撸撸这几个接口
  9 +/**
  10 + * 拼团活动 API 接口
  11 + *
  12 + * @author HUIHUI
  13 + */
  14 +public interface CombinationApi {
  15 +
  16 + /**
  17 + * 创建开团记录
  18 + *
  19 + * @param reqDTO 请求 DTO
  20 + */
  21 + void createRecord(@Valid CombinationRecordReqDTO reqDTO);
  22 +
  23 + /**
  24 + * 获取开团记录状态
  25 + *
  26 + * @param userId 用户编号
  27 + * @param orderId 订单编号
  28 + */
  29 + boolean validateRecordStatusIsSuccess(Long userId, Long orderId);
  30 +
  31 + /**
  32 + * 更新开团记录状态
  33 + *
  34 + * @param userId 用户编号
  35 + * @param orderId 订单编号
  36 + * @param status 状态值
  37 + */
  38 + void updateRecordStatus(Long userId, Long orderId, Integer status);
  39 +
  40 + /**
  41 + * 更新开团记录状态和开始时间
  42 + *
  43 + * @param userId 用户编号
  44 + * @param orderId 订单编号
  45 + * @param status 状态值
  46 + */
  47 + void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status);
  48 +
  49 +}
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.combination.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotEmpty;
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +// TODO @puhui999:CombinationRecordCreateReqDTO,这样更容易知道是创建噢
  9 +/**
  10 + * 拼团记录 Request DTO
  11 + *
  12 + * @author HUIHUI
  13 + */
  14 +@Data
  15 +public class CombinationRecordReqDTO {
  16 +
  17 + /**
  18 + * 拼团活动编号
  19 + */
  20 + @NotNull(message = "拼团活动编号不能为空")
  21 + private Long activityId;
  22 + /**
  23 + * spu 编号
  24 + */
  25 + @NotNull(message = "spu 编号不能为空")
  26 + private Long spuId;
  27 + /**
  28 + * sku 编号
  29 + */
  30 + @NotNull(message = "sku 编号不能为空")
  31 + private Long skuId;
  32 + /**
  33 + * 用户编号
  34 + */
  35 + @NotNull(message = "用户编号不能为空")
  36 + private Long userId;
  37 + /**
  38 + * 订单编号
  39 + */
  40 + @NotNull(message = "订单编号不能为空")
  41 + private Long orderId;
  42 + /**
  43 + * 团长编号
  44 + */
  45 + @NotNull(message = "团长编号不能为空")
  46 + private Long headId;
  47 + /**
  48 + * 商品名字
  49 + */
  50 + @NotEmpty(message = "商品名字不能为空")
  51 + private String spuName;
  52 + /**
  53 + * 商品图片
  54 + */
  55 + @NotEmpty(message = "商品图片不能为空")
  56 + private String picUrl;
  57 + /**
  58 + * 拼团商品单价
  59 + */
  60 + @NotNull(message = "拼团商品单价不能为空")
  61 + private Integer combinationPrice;
  62 + /**
  63 + * 用户昵称
  64 + */
  65 + @NotEmpty(message = "用户昵称不能为空")
  66 + private String nickname;
  67 + /**
  68 + * 用户头像
  69 + */
  70 + @NotEmpty(message = "用户头像不能为空")
  71 + private String avatar;
  72 + /**
  73 + * 开团状态:正在开团 拼团成功 拼团失败 TODO 等待支付
  74 + */
  75 + @NotNull(message = "开团状态不能为空")
  76 + private Integer status;
  77 +
  78 +}
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
4 4
5 /** 5 /**
6 * Promotion 错误码枚举类 6 * Promotion 错误码枚举类
7 - * 7 + * <p>
8 * promotion 系统,使用 1-013-000-000 段 8 * promotion 系统,使用 1-013-000-000 段
9 */ 9 */
10 public interface ErrorCodeConstants { 10 public interface ErrorCodeConstants {
@@ -42,8 +42,7 @@ public interface ErrorCodeConstants { @@ -42,8 +42,7 @@ public interface ErrorCodeConstants {
42 ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013006004, "满减送活动已关闭,不能重复关闭"); 42 ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013006004, "满减送活动已关闭,不能重复关闭");
43 ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013006005, "满减送活动已结束,不能关闭"); 43 ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013006005, "满减送活动已结束,不能关闭");
44 44
45 - // ========== Price 相关 1013007000 ============  
46 - ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1013007000, "支付价格计算异常,原因:价格小于等于 0"); 45 + // ========== TODO 空着 1013007000 ============
47 46
48 // ========== 秒杀活动 1013008000 ========== 47 // ========== 秒杀活动 1013008000 ==========
49 ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在"); 48 ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在");
@@ -58,5 +57,13 @@ public interface ErrorCodeConstants { @@ -58,5 +57,13 @@ public interface ErrorCodeConstants {
58 ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突"); 57 ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");
59 ErrorCode SECKILL_TIME_EQUAL = new ErrorCode(1013009002, "秒杀时段开始时间和结束时间不能相等"); 58 ErrorCode SECKILL_TIME_EQUAL = new ErrorCode(1013009002, "秒杀时段开始时间和结束时间不能相等");
60 ErrorCode SECKILL_START_TIME_BEFORE_END_TIME = new ErrorCode(1013009003, "秒杀时段开始时间不能在结束时间之后"); 59 ErrorCode SECKILL_START_TIME_BEFORE_END_TIME = new ErrorCode(1013009003, "秒杀时段开始时间不能在结束时间之后");
  60 + ErrorCode SECKILL_TIME_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭");
  61 +
  62 + // ========== 拼团活动 1013010000 ==========
  63 + ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
  64 + ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动");
  65 + ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010002, "拼团活动已关闭不能修改");
  66 + ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除");
  67 + ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013010004, "拼团不存在");
61 68
62 } 69 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/combination/CombinationRecordStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.enums.combination;
  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 HUIHUI
  13 + */
  14 +@AllArgsConstructor
  15 +@Getter
  16 +public enum CombinationRecordStatusEnum implements IntArrayValuable {
  17 +
  18 + WAITING(0, "未付款"),
  19 + IN_PROGRESS(1, "进行中"),
  20 + SUCCESS(2, "拼团成功"),
  21 + FAILED(3, "拼团失败");
  22 +
  23 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CombinationRecordStatusEnum::getStatus).toArray();
  24 +
  25 + /**
  26 + * 状态值
  27 + */
  28 + private final Integer status;
  29 + /**
  30 + * 状态名
  31 + */
  32 + private final String name;
  33 +
  34 + @Override
  35 + public int[] array() {
  36 + return ARRAYS;
  37 + }
  38 +
  39 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.combination;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;
  4 +import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
  5 +import org.springframework.stereotype.Service;
  6 +
  7 +import javax.annotation.Resource;
  8 +import java.time.LocalDateTime;
  9 +
  10 +/**
  11 + * 拼团活动 API 实现类
  12 + *
  13 + * @author HUIHUI
  14 + */
  15 +@Service
  16 +public class CombinationApiImpl implements CombinationApi {
  17 +
  18 + @Resource
  19 + private CombinationActivityService activityService;
  20 +
  21 + @Override
  22 + public void createRecord(CombinationRecordReqDTO reqDTO) {
  23 + activityService.createRecord(reqDTO);
  24 + }
  25 +
  26 + @Override
  27 + public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) {
  28 + return activityService.validateRecordStatusIsSuccess(userId, orderId);
  29 + }
  30 +
  31 + @Override
  32 + public void updateRecordStatus(Long userId, Long orderId, Integer status) {
  33 + activityService.updateRecordStatusByUserIdAndOrderId(userId, orderId, status);
  34 + }
  35 +
  36 + @Override
  37 + public void updateRecordStatusAndStartTime(Long userId, Long orderId, Integer status) {
  38 + activityService.updateRecordStatusAndStartTimeByUserIdAndOrderId(userId, orderId, status, LocalDateTime.now());
  39 + }
  40 +
  41 +
  42 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  6 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  7 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  8 +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
  9 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
  10 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.*;
  11 +import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
  12 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
  13 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;
  14 +import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
  15 +import io.swagger.v3.oas.annotations.Operation;
  16 +import io.swagger.v3.oas.annotations.Parameter;
  17 +import io.swagger.v3.oas.annotations.tags.Tag;
  18 +import org.springframework.security.access.prepost.PreAuthorize;
  19 +import org.springframework.validation.annotation.Validated;
  20 +import org.springframework.web.bind.annotation.*;
  21 +
  22 +import javax.annotation.Resource;
  23 +import javax.servlet.http.HttpServletResponse;
  24 +import javax.validation.Valid;
  25 +import java.io.IOException;
  26 +import java.util.Collection;
  27 +import java.util.List;
  28 +import java.util.Set;
  29 +
  30 +import static cn.hutool.core.collection.CollectionUtil.newArrayList;
  31 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  32 +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
  33 +
  34 +@Tag(name = "管理后台 - 拼团活动")
  35 +@RestController
  36 +@RequestMapping("/promotion/combination-activity")
  37 +@Validated
  38 +public class CombinationActivityController {
  39 +
  40 + @Resource
  41 + private CombinationActivityService combinationActivityService;
  42 + @Resource
  43 + private ProductSpuApi spuApi;
  44 +
  45 + @PostMapping("/create")
  46 + @Operation(summary = "创建拼团活动")
  47 + @PreAuthorize("@ss.hasPermission('promotion:combination-activity:create')")
  48 + public CommonResult<Long> createCombinationActivity(@Valid @RequestBody CombinationActivityCreateReqVO createReqVO) {
  49 + return success(combinationActivityService.createCombinationActivity(createReqVO));
  50 + }
  51 +
  52 + @PutMapping("/update")
  53 + @Operation(summary = "更新拼团活动")
  54 + @PreAuthorize("@ss.hasPermission('promotion:combination-activity:update')")
  55 + public CommonResult<Boolean> updateCombinationActivity(@Valid @RequestBody CombinationActivityUpdateReqVO updateReqVO) {
  56 + combinationActivityService.updateCombinationActivity(updateReqVO);
  57 + return success(true);
  58 + }
  59 +
  60 + @DeleteMapping("/delete")
  61 + @Operation(summary = "删除拼团活动")
  62 + @Parameter(name = "id", description = "编号", required = true)
  63 + @PreAuthorize("@ss.hasPermission('promotion:combination-activity:delete')")
  64 + public CommonResult<Boolean> deleteCombinationActivity(@RequestParam("id") Long id) {
  65 + combinationActivityService.deleteCombinationActivity(id);
  66 + return success(true);
  67 + }
  68 +
  69 + @GetMapping("/get")
  70 + @Operation(summary = "获得拼团活动")
  71 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  72 + @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
  73 + public CommonResult<CombinationActivityRespVO> getCombinationActivity(@RequestParam("id") Long id) {
  74 + CombinationActivityDO activity = combinationActivityService.getCombinationActivity(id);
  75 + List<CombinationProductDO> products = combinationActivityService.getProductsByActivityIds(newArrayList(id));
  76 + return success(CombinationActivityConvert.INSTANCE.convert(activity, products));
  77 + }
  78 +
  79 + @GetMapping("/list")
  80 + @Operation(summary = "获得拼团活动列表")
  81 + @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
  82 + @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
  83 + public CommonResult<List<CombinationActivityRespVO>> getCombinationActivityList(@RequestParam("ids") Collection<Long> ids) {
  84 + List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(ids);
  85 + return success(CombinationActivityConvert.INSTANCE.convertList(list));
  86 + }
  87 +
  88 + @GetMapping("/page")
  89 + @Operation(summary = "获得拼团活动分页")
  90 + @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
  91 + public CommonResult<PageResult<CombinationActivityRespVO>> getCombinationActivityPage(
  92 + @Valid CombinationActivityPageReqVO pageVO) {
  93 + PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(pageVO);
  94 + // TODO @puhui999:可以不一定 aIds,直接批量查询结果出来;下面也是类似;
  95 + Set<Long> aIds = CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getId);
  96 + List<CombinationProductDO> products = combinationActivityService.getProductsByActivityIds(aIds);
  97 + Set<Long> spuIds = CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getSpuId);
  98 + List<ProductSpuRespDTO> spus = spuApi.getSpuList(spuIds);
  99 + return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult, products, spus));
  100 + }
  101 +
  102 + @GetMapping("/export-excel")
  103 + @Operation(summary = "导出拼团活动 Excel")
  104 + @PreAuthorize("@ss.hasPermission('promotion:combination-activity:export')")
  105 + @OperateLog(type = EXPORT)
  106 + public void exportCombinationActivityExcel(@Valid CombinationActivityExportReqVO exportReqVO,
  107 + HttpServletResponse response) throws IOException {
  108 + List<CombinationActivityDO> list = combinationActivityService.getCombinationActivityList(exportReqVO);
  109 + // 导出 Excel
  110 + List<CombinationActivityExcelVO> datas = CombinationActivityConvert.INSTANCE.convertList02(list);
  111 + ExcelUtils.write(response, "拼团活动.xls", "数据", CombinationActivityExcelVO.class, datas);
  112 + }
  113 +
  114 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import org.springframework.format.annotation.DateTimeFormat;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +import java.time.LocalDateTime;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  11 +
  12 +/**
  13 + * 拼团活动 Base VO,提供给添加、修改、详细的子 VO 使用
  14 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  15 + */
  16 +@Data
  17 +public class CombinationActivityBaseVO {
  18 +
  19 + @Schema(description = "拼团名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "越拼越省钱")
  20 + @NotNull(message = "拼团名称不能为空")
  21 + private String name;
  22 +
  23 + @Schema(description = "商品 SPU 编号,关联 ProductSpuDO 的 id", example = "[1,2,3]")
  24 + @NotNull(message = "拼团商品不能为空")
  25 + private Long spuId;
  26 +
  27 + @Schema(description = "总限购数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "16218")
  28 + @NotNull(message = "总限购数量不能为空")
  29 + private Integer totalLimitCount;
  30 +
  31 + @Schema(description = "单次限购数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "28265")
  32 + @NotNull(message = "单次限购数量不能为空")
  33 + private Integer singleLimitCount;
  34 +
  35 + // TODO @puhui999:是不是弄成 2 个字段会好点哈。开始、结束
  36 + @Schema(description = "活动时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
  37 + @NotNull(message = "活动时间不能为空")
  38 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  39 + private LocalDateTime[] activityTime;
  40 +
  41 + @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "25222")
  42 + @NotNull(message = "开团人数不能为空")
  43 + private Integer userSize;
  44 +
  45 + @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED)
  46 + @NotNull(message = "限制时长不能为空")
  47 + private Integer limitDuration;
  48 +
  49 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import javax.validation.Valid;
  10 +import java.util.List;
  11 +
  12 +@Schema(description = "管理后台 - 拼团活动创建 Request VO")
  13 +@Data
  14 +@EqualsAndHashCode(callSuper = true)
  15 +@ToString(callSuper = true)
  16 +public class CombinationActivityCreateReqVO extends CombinationActivityBaseVO {
  17 +
  18 + @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
  19 + @Valid
  20 + private List<CombinationProductCreateReqVO> products;
  21 +
  22 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExcelVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
  2 +
  3 +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
  4 +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
  5 +import com.alibaba.excel.annotation.ExcelProperty;
  6 +import lombok.Data;
  7 +
  8 +import java.time.LocalDateTime;
  9 +
  10 +// TODO @puhui999:如无必要,导出都可以删除哈
  11 +/**
  12 + * 拼团活动 Excel VO
  13 + *
  14 + * @author HUIHUI
  15 + */
  16 +@Data
  17 +public class CombinationActivityExcelVO {
  18 +
  19 + @ExcelProperty("活动编号")
  20 + private Long id;
  21 +
  22 + @ExcelProperty("拼团名称")
  23 + private String name;
  24 +
  25 + @ExcelProperty("商品 SPU 编号关联 ProductSpuDO 的 id")
  26 + private Long spuId;
  27 +
  28 + @ExcelProperty("总限购数量")
  29 + private Integer totalLimitCount;
  30 +
  31 + @ExcelProperty("单次限购数量")
  32 + private Integer singleLimitCount;
  33 +
  34 + @ExcelProperty("开始时间")
  35 + private LocalDateTime startTime;
  36 +
  37 + @ExcelProperty("结束时间")
  38 + private LocalDateTime endTime;
  39 +
  40 + @ExcelProperty("开团人数")
  41 + private Integer userSize;
  42 +
  43 + @ExcelProperty("开团组数")
  44 + private Integer totalNum;
  45 +
  46 + @ExcelProperty("成团组数")
  47 + private Integer successNum;
  48 +
  49 + @ExcelProperty("参与人数")
  50 + private Integer orderUserCount;
  51 +
  52 + @ExcelProperty("虚拟成团")
  53 + private Integer virtualGroup;
  54 +
  55 + @ExcelProperty(value = "活动状态:0开启 1关闭", converter = DictConvert.class)
  56 + @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
  57 + private Integer status;
  58 +
  59 + @ExcelProperty("限制时长(小时)")
  60 + private Integer limitDuration;
  61 +
  62 + @ExcelProperty("创建时间")
  63 + private LocalDateTime createTime;
  64 +
  65 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExportReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import org.springframework.format.annotation.DateTimeFormat;
  6 +
  7 +import java.time.LocalDateTime;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  10 +
  11 +// TODO @puhui999:如无必要,导出都可以删除哈
  12 +@Schema(description = "管理后台 - 拼团活动 Excel 导出 Request VO,参数和 CombinationActivityPageReqVO 是一致的")
  13 +@Data
  14 +public class CombinationActivityExportReqVO {
  15 +
  16 + @Schema(description = "拼团名称", example = "赵六")
  17 + private String name;
  18 +
  19 + @Schema(description = "商品 SPU 编号关联 ProductSpuDO 的 id", example = "14016")
  20 + private Long spuId;
  21 +
  22 + @Schema(description = "总限购数量", example = "16218")
  23 + private Integer totalLimitCount;
  24 +
  25 + @Schema(description = "单次限购数量", example = "28265")
  26 + private Integer singleLimitCount;
  27 +
  28 + @Schema(description = "开始时间")
  29 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  30 + private LocalDateTime[] startTime;
  31 +
  32 + @Schema(description = "结束时间")
  33 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  34 + private LocalDateTime[] endTime;
  35 +
  36 + @Schema(description = "开团人数")
  37 + private Integer userSize;
  38 +
  39 + @Schema(description = "开团组数")
  40 + private Integer totalNum;
  41 +
  42 + @Schema(description = "成团组数")
  43 + private Integer successNum;
  44 +
  45 + @Schema(description = "参与人数", example = "25222")
  46 + private Integer orderUserCount;
  47 +
  48 + @Schema(description = "虚拟成团")
  49 + private Integer virtualGroup;
  50 +
  51 + @Schema(description = "活动状态:0开启 1关闭", example = "0")
  52 + private Integer status;
  53 +
  54 + @Schema(description = "限制时长(小时)")
  55 + private Integer limitDuration;
  56 +
  57 + @Schema(description = "创建时间")
  58 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  59 + private LocalDateTime[] createTime;
  60 +
  61 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +import org.springframework.format.annotation.DateTimeFormat;
  9 +
  10 +import java.time.LocalDateTime;
  11 +
  12 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  13 +
  14 +@Schema(description = "管理后台 - 拼团活动分页 Request VO")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +@ToString(callSuper = true)
  18 +public class CombinationActivityPageReqVO extends PageParam {
  19 +
  20 + @Schema(description = "拼团名称", example = "赵六")
  21 + private String name;
  22 +
  23 + @Schema(description = "商品 SPU 编号关联 ProductSpuDO 的 id", example = "14016")
  24 + private Long spuId;
  25 +
  26 + @Schema(description = "总限购数量", example = "16218")
  27 + private Integer totalLimitCount;
  28 +
  29 + @Schema(description = "单次限购数量", example = "28265")
  30 + private Integer singleLimitCount;
  31 +
  32 + @Schema(description = "开始时间")
  33 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  34 + private LocalDateTime[] startTime;
  35 +
  36 + @Schema(description = "结束时间")
  37 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  38 + private LocalDateTime[] endTime;
  39 +
  40 + @Schema(description = "开团人数")
  41 + private Integer userSize;
  42 +
  43 + @Schema(description = "开团组数")
  44 + private Integer totalNum;
  45 +
  46 + @Schema(description = "成团组数")
  47 + private Integer successNum;
  48 +
  49 + @Schema(description = "参与人数", example = "25222")
  50 + private Integer orderUserCount;
  51 +
  52 + @Schema(description = "虚拟成团")
  53 + private Integer virtualGroup;
  54 +
  55 + @Schema(description = "活动状态:0开启 1关闭", example = "0")
  56 + private Integer status;
  57 +
  58 + @Schema(description = "限制时长(小时)")
  59 + private Integer limitDuration;
  60 +
  61 + @Schema(description = "创建时间")
  62 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  63 + private LocalDateTime[] createTime;
  64 +
  65 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import javax.validation.Valid;
  10 +import javax.validation.constraints.NotNull;
  11 +import java.time.LocalDateTime;
  12 +import java.util.List;
  13 +
  14 +@Schema(description = "管理后台 - 拼团活动 Response VO")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +@ToString(callSuper = true)
  18 +public class CombinationActivityRespVO extends CombinationActivityBaseVO {
  19 +
  20 + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
  21 + private String spuName;
  22 +
  23 + @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
  24 + private String picUrl;
  25 +
  26 + @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")
  27 + private Long id;
  28 +
  29 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  30 + private LocalDateTime createTime;
  31 +
  32 + @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED)
  33 + @NotNull(message = "开团人数不能为空")
  34 + private Integer userSize;
  35 +
  36 + @Schema(description = "开团组数", requiredMode = Schema.RequiredMode.REQUIRED)
  37 + @NotNull(message = "开团组数不能为空")
  38 + private Integer totalNum;
  39 +
  40 + @Schema(description = "成团组数", requiredMode = Schema.RequiredMode.REQUIRED)
  41 + @NotNull(message = "成团组数不能为空")
  42 + private Integer successNum;
  43 +
  44 + @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED)
  45 + @NotNull(message = "虚拟成团不能为空")
  46 + private Integer virtualGroup;
  47 +
  48 + @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
  49 + @NotNull(message = "活动状态不能为空")
  50 + private Integer status;
  51 +
  52 + @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
  53 + @Valid
  54 + private List<CombinationProductRespVO> products;
  55 +
  56 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import javax.validation.Valid;
  10 +import javax.validation.constraints.NotNull;
  11 +import java.util.List;
  12 +
  13 +@Schema(description = "管理后台 - 拼团活动更新 Request VO")
  14 +@Data
  15 +@EqualsAndHashCode(callSuper = true)
  16 +@ToString(callSuper = true)
  17 +public class CombinationActivityUpdateReqVO extends CombinationActivityBaseVO {
  18 +
  19 + @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")
  20 + @NotNull(message = "活动编号不能为空")
  21 + private Long id;
  22 +
  23 + @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
  24 + @Valid
  25 + private List<CombinationProductUpdateReqVO> products;
  26 +
  27 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +/**
  9 + * 拼团商品 Base VO,提供给添加、修改、详细的子 VO 使用
  10 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  11 + */
  12 +@Data
  13 +public class CombinationProductBaseVO {
  14 +
  15 + @Schema(description = "商品 spuId", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
  16 + @NotNull(message = "商品 spuId 不能为空")
  17 + private Long spuId;
  18 +
  19 + @Schema(description = "商品 skuId", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
  20 + @NotNull(message = "商品 skuId 不能为空")
  21 + private Long skuId;
  22 +
  23 + @Schema(description = "拼团价格,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "27682")
  24 + @NotNull(message = "拼团价格,单位分不能为空")
  25 + private Integer activePrice;
  26 +
  27 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +@Schema(description = "管理后台 - 拼团商品创建 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class CombinationProductCreateReqVO extends CombinationProductBaseVO {
  13 +
  14 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExcelVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
  2 +
  3 +import com.alibaba.excel.annotation.ExcelProperty;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +// TODO @puhui999:可以考虑删除 excel 导出哈
  9 +/**
  10 + * 拼团商品 Excel VO
  11 + *
  12 + * @author HUIHUI
  13 + */
  14 +@Data
  15 +public class CombinationProductExcelVO {
  16 +
  17 + @ExcelProperty("编号")
  18 + private Long id;
  19 +
  20 + @ExcelProperty("拼团活动编号")
  21 + private Long activityId;
  22 +
  23 + @ExcelProperty("商品 SPU 编号")
  24 + private Long spuId;
  25 +
  26 + @ExcelProperty("商品 SKU 编号")
  27 + private Long skuId;
  28 +
  29 + @ExcelProperty("拼团商品状态")
  30 + private Integer activityStatus;
  31 +
  32 + @ExcelProperty("活动开始时间点")
  33 + private LocalDateTime activityStartTime;
  34 +
  35 + @ExcelProperty("活动结束时间点")
  36 + private LocalDateTime activityEndTime;
  37 +
  38 + @ExcelProperty("拼团价格,单位分")
  39 + private Integer activePrice;
  40 +
  41 + @ExcelProperty("创建时间")
  42 + private LocalDateTime createTime;
  43 +
  44 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExportReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import org.springframework.format.annotation.DateTimeFormat;
  6 +
  7 +import java.time.LocalDateTime;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  10 +
  11 +// TODO @puhui999:可以考虑删除 excel 导出哈
  12 +@Schema(description = "管理后台 - 拼团商品 Excel 导出 Request VO,参数和 CombinationProductPageReqVO 是一致的")
  13 +@Data
  14 +public class CombinationProductExportReqVO {
  15 +
  16 + @Schema(description = "拼团活动编号", example = "6829")
  17 + private Long activityId;
  18 +
  19 + @Schema(description = "商品 SPU 编号", example = "18731")
  20 + private Long spuId;
  21 +
  22 + @Schema(description = "商品 SKU 编号", example = "31675")
  23 + private Long skuId;
  24 +
  25 + @Schema(description = "拼团商品状态", example = "2")
  26 + private Integer activityStatus;
  27 +
  28 + @Schema(description = "活动开始时间点")
  29 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  30 + private LocalDateTime[] activityStartTime;
  31 +
  32 + @Schema(description = "活动结束时间点")
  33 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  34 + private LocalDateTime[] activityEndTime;
  35 +
  36 + @Schema(description = "拼团价格,单位分", example = "27682")
  37 + private Integer activePrice;
  38 +
  39 + @Schema(description = "创建时间")
  40 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  41 + private LocalDateTime[] createTime;
  42 +
  43 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +import org.springframework.format.annotation.DateTimeFormat;
  9 +
  10 +import java.time.LocalDateTime;
  11 +
  12 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  13 +
  14 +@Schema(description = "管理后台 - 拼团商品分页 Request VO")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +@ToString(callSuper = true)
  18 +public class CombinationProductPageReqVO extends PageParam {
  19 +
  20 + @Schema(description = "拼团活动编号", example = "6829")
  21 + private Long activityId;
  22 +
  23 + @Schema(description = "商品 SPU 编号", example = "18731")
  24 + private Long spuId;
  25 +
  26 + @Schema(description = "商品 SKU 编号", example = "31675")
  27 + private Long skuId;
  28 +
  29 + @Schema(description = "拼团商品状态", example = "2")
  30 + private Integer activityStatus;
  31 +
  32 + @Schema(description = "活动开始时间点")
  33 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  34 + private LocalDateTime[] activityStartTime;
  35 +
  36 + @Schema(description = "活动结束时间点")
  37 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  38 + private LocalDateTime[] activityEndTime;
  39 +
  40 + @Schema(description = "拼团价格,单位分", example = "27682")
  41 + private Integer activePrice;
  42 +
  43 + @Schema(description = "创建时间")
  44 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  45 + private LocalDateTime[] createTime;
  46 +
  47 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +import java.time.LocalDateTime;
  9 +
  10 +@Schema(description = "管理后台 - 拼团商品 Response VO")
  11 +@Data
  12 +@EqualsAndHashCode(callSuper = true)
  13 +@ToString(callSuper = true)
  14 +public class CombinationProductRespVO extends CombinationProductBaseVO {
  15 +
  16 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28322")
  17 + private Long id;
  18 +
  19 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  20 + private LocalDateTime createTime;
  21 +
  22 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +@Schema(description = "管理后台 - 拼团商品更新 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class CombinationProductUpdateReqVO extends CombinationProductBaseVO {
  13 +
  14 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
@@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill; @@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
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.framework.common.util.collection.CollectionUtils;
  6 +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
  7 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
5 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.*; 8 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.*;
6 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert; 9 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
7 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; 10 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
@@ -18,6 +21,7 @@ import javax.annotation.Resource; @@ -18,6 +21,7 @@ import javax.annotation.Resource;
18 import javax.validation.Valid; 21 import javax.validation.Valid;
19 import java.util.Collection; 22 import java.util.Collection;
20 import java.util.List; 23 import java.util.List;
  24 +import java.util.Set;
21 25
22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 26 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
23 27
@@ -29,6 +33,8 @@ public class SeckillActivityController { @@ -29,6 +33,8 @@ public class SeckillActivityController {
29 33
30 @Resource 34 @Resource
31 private SeckillActivityService seckillActivityService; 35 private SeckillActivityService seckillActivityService;
  36 + @Resource
  37 + private ProductSpuApi spuApi;
32 38
33 @PostMapping("/create") 39 @PostMapping("/create")
34 @Operation(summary = "创建秒杀活动") 40 @Operation(summary = "创建秒杀活动")
@@ -69,11 +75,8 @@ public class SeckillActivityController { @@ -69,11 +75,8 @@ public class SeckillActivityController {
69 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") 75 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
70 public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) { 76 public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
71 SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id); 77 SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id);
72 - if (seckillActivity == null) {  
73 - return success(null);  
74 - }  
75 - List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id);  
76 - return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity,seckillProducts)); 78 + List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id);
  79 + return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity, seckillProducts));
77 } 80 }
78 81
79 @GetMapping("/list") 82 @GetMapping("/list")
@@ -90,7 +93,11 @@ public class SeckillActivityController { @@ -90,7 +93,11 @@ public class SeckillActivityController {
90 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") 93 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
91 public CommonResult<PageResult<SeckillActivityRespVO>> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) { 94 public CommonResult<PageResult<SeckillActivityRespVO>> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) {
92 PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(pageVO); 95 PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(pageVO);
93 - return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult)); 96 + Set<Long> aIds = CollectionUtils.convertSet(pageResult.getList(), SeckillActivityDO::getId);
  97 + List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(aIds);
  98 + Set<Long> spuIds = CollectionUtils.convertSet(pageResult.getList(), SeckillActivityDO::getSpuId);
  99 + List<ProductSpuRespDTO> spuList = spuApi.getSpuList(spuIds);
  100 + return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, seckillProducts, spuList));
94 } 101 }
95 102
96 } 103 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
@@ -19,11 +19,6 @@ import java.util.List; @@ -19,11 +19,6 @@ import java.util.List;
19 19
20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
21 21
22 -/**  
23 - * 管理后台 - 秒杀时段相关接口  
24 - *  
25 - * @author HUIHUI  
26 - */  
27 @Tag(name = "管理后台 - 秒杀时段") 22 @Tag(name = "管理后台 - 秒杀时段")
28 @RestController 23 @RestController
29 @RequestMapping("/promotion/seckill-config") 24 @RequestMapping("/promotion/seckill-config")
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java
@@ -20,10 +20,9 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -20,10 +20,9 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
20 @Data 20 @Data
21 public class SeckillActivityBaseVO { 21 public class SeckillActivityBaseVO {
22 22
23 - // TODO @puhui999:对应单 spuId 哈  
24 @Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]") 23 @Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]")
25 @NotNull(message = "秒杀活动商品不能为空") 24 @NotNull(message = "秒杀活动商品不能为空")
26 - private List<Long> spuIds; 25 + private Long spuId;
27 26
28 @Schema(description = "秒杀活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促") 27 @Schema(description = "秒杀活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
29 @NotNull(message = "秒杀活动名称不能为空") 28 @NotNull(message = "秒杀活动名称不能为空")
@@ -56,8 +55,4 @@ public class SeckillActivityBaseVO { @@ -56,8 +55,4 @@ public class SeckillActivityBaseVO {
56 @Schema(description = "单次限够数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "31683") 55 @Schema(description = "单次限够数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "31683")
57 private Integer singleLimitCount; 56 private Integer singleLimitCount;
58 57
59 - // TODO @puhui999:这个应该是计算出来的字段,只返回,create 和 update 不用哈  
60 - @Schema(description = "秒杀总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")  
61 - private Integer totalStock;  
62 -  
63 } 58 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java
@@ -6,26 +6,46 @@ import lombok.Data; @@ -6,26 +6,46 @@ import lombok.Data;
6 import lombok.EqualsAndHashCode; 6 import lombok.EqualsAndHashCode;
7 import lombok.ToString; 7 import lombok.ToString;
8 8
  9 +import java.time.LocalDateTime;
9 import java.util.List; 10 import java.util.List;
10 11
11 -/**  
12 - * 管理后台 - 秒杀活动 Response VO  
13 - *  
14 - * @author HUIHUI  
15 - */  
16 @Schema(description = "管理后台 - 秒杀活动 Response VO") 12 @Schema(description = "管理后台 - 秒杀活动 Response VO")
17 @Data 13 @Data
18 @EqualsAndHashCode(callSuper = true) 14 @EqualsAndHashCode(callSuper = true)
19 @ToString(callSuper = true) 15 @ToString(callSuper = true)
20 public class SeckillActivityRespVO extends SeckillActivityBaseVO { 16 public class SeckillActivityRespVO extends SeckillActivityBaseVO {
21 17
  18 + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
  19 + private String spuName;
  20 +
  21 + @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
  22 + private String picUrl;
  23 +
22 @Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 24 @Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
23 private Long id; 25 private Long id;
24 26
25 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) 27 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
26 - private List<SeckillProductRespVO> products; // TODO puhui: 考虑是否去除 28 + private List<SeckillProductRespVO> products;
27 29
28 @Schema(description = "活动状态 开启:0 禁用:1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") 30 @Schema(description = "活动状态 开启:0 禁用:1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
29 private Integer status; 31 private Integer status;
30 32
  33 + @Schema(description = "订单实付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22354")
  34 + private Integer totalPrice;
  35 +
  36 + @Schema(description = "秒杀库存", example = "10")
  37 + private Integer stock;
  38 +
  39 + @Schema(description = "秒杀总库存", example = "20")
  40 + private Integer totalStock;
  41 +
  42 + @Schema(description = "新增订单数", example = "20")
  43 + private Integer orderCount;
  44 +
  45 + @Schema(description = "付款人数", example = "20")
  46 + private Integer userCount;
  47 +
  48 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  49 + private LocalDateTime createTime;
  50 +
31 } 51 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
2 2
  3 +import com.fasterxml.jackson.annotation.JsonIgnore;
3 import io.swagger.v3.oas.annotations.media.Schema; 4 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 5 import lombok.Data;
5 6
  7 +import javax.validation.constraints.AssertTrue;
6 import javax.validation.constraints.NotNull; 8 import javax.validation.constraints.NotNull;
  9 +import java.time.LocalTime;
  10 +import java.util.List;
7 11
8 /** 12 /**
9 * 秒杀时段 Base VO,提供给添加、修改、详细的子 VO 使用 13 * 秒杀时段 Base VO,提供给添加、修改、详细的子 VO 使用
@@ -26,12 +30,24 @@ public class SeckillConfigBaseVO { @@ -26,12 +30,24 @@ public class SeckillConfigBaseVO {
26 @NotNull(message = "结束时间点不能为空") 30 @NotNull(message = "结束时间点不能为空")
27 private String endTime; 31 private String endTime;
28 32
29 - @Schema(description = "秒杀主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn")  
30 - @NotNull(message = "秒杀主图不能为空")  
31 - private String picUrl; 33 + @Schema(description = "秒杀轮播图", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png]")
  34 + @NotNull(message = "秒杀轮播图不能为空")
  35 + private List<String> sliderPicUrls;
32 36
33 @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") 37 @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
34 @NotNull(message = "状态不能为空") 38 @NotNull(message = "状态不能为空")
35 private Integer status; 39 private Integer status;
36 40
  41 + @AssertTrue(message = "秒杀时段开始时间和结束时间不能相等")
  42 + @JsonIgnore
  43 + public boolean isValidStartTimeValid() {
  44 + return !LocalTime.parse(startTime).equals(LocalTime.parse(endTime));
  45 + }
  46 +
  47 + @AssertTrue(message = "秒杀时段开始时间不能在结束时间之后")
  48 + @JsonIgnore
  49 + public boolean isValidEndTimeValid() {
  50 + return !LocalTime.parse(startTime).isAfter(LocalTime.parse(endTime));
  51 + }
  52 +
37 } 53 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java
@@ -6,12 +6,6 @@ import lombok.Data; @@ -6,12 +6,6 @@ import lombok.Data;
6 import lombok.EqualsAndHashCode; 6 import lombok.EqualsAndHashCode;
7 import lombok.ToString; 7 import lombok.ToString;
8 8
9 -// TODO @puhui:VO 上不写注释,已经有注解啦。  
10 -/**  
11 - * 管理后台 - 秒杀时段分页 Request VO  
12 - *  
13 - * @author HUIHUI  
14 - */  
15 @Schema(description = "管理后台 - 秒杀时段分页 Request VO") 9 @Schema(description = "管理后台 - 秒杀时段分页 Request VO")
16 @Data 10 @Data
17 @EqualsAndHashCode(callSuper = true) 11 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java
@@ -14,11 +14,6 @@ import javax.validation.constraints.NotNull; @@ -14,11 +14,6 @@ import javax.validation.constraints.NotNull;
14 @Data 14 @Data
15 public class SeckillProductBaseVO { 15 public class SeckillProductBaseVO {
16 16
17 - // TODO @puhui:spuId 不用传递;因为一个秒杀活动只对应一个 SPU 哈;  
18 - @Schema(description = "商品spu_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")  
19 - @NotNull(message = "商品spu_id不能为空")  
20 - private Long spuId;  
21 -  
22 @Schema(description = "商品sku_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563") 17 @Schema(description = "商品sku_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
23 @NotNull(message = "商品sku_id不能为空") 18 @NotNull(message = "商品sku_id不能为空")
24 private Long skuId; 19 private Long skuId;
@@ -31,5 +26,4 @@ public class SeckillProductBaseVO { @@ -31,5 +26,4 @@ public class SeckillProductBaseVO {
31 @NotNull(message = "秒杀库存不能为空") 26 @NotNull(message = "秒杀库存不能为空")
32 private Integer stock; 27 private Integer stock;
33 28
34 -  
35 } 29 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
2 2
3 -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;  
4 -import lombok.*;  
5 -import java.util.*;  
6 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
7 -import javax.validation.constraints.*;  
8 -  
9 -/**  
10 - * 管理后台 - 秒杀参与商品创建 Request VO  
11 - *  
12 - * @author HUIHUI  
13 - */ 4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
14 @Schema(description = "管理后台 - 秒杀参与商品创建 Request VO") 7 @Schema(description = "管理后台 - 秒杀参与商品创建 Request VO")
15 @Data 8 @Data
16 @EqualsAndHashCode(callSuper = true) 9 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
2 2
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 -import lombok.*; 4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
5 import java.time.LocalDateTime; 8 import java.time.LocalDateTime;
6 9
7 -/**  
8 - * 管理后台 - 秒杀参与商品 Response VO  
9 - *  
10 - * @author HUIHUI  
11 - */  
12 @Schema(description = "管理后台 - 秒杀参与商品 Response VO") 10 @Schema(description = "管理后台 - 秒杀参与商品 Response VO")
13 @Data 11 @Data
14 @EqualsAndHashCode(callSuper = true) 12 @EqualsAndHashCode(callSuper = true)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
2 2
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 -import lombok.*;  
5 -import javax.validation.constraints.*; 4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
6 7
7 -/**  
8 - * 管理后台 - 秒杀参与商品更新 Request VO  
9 - *  
10 - * @author HUIHUI  
11 - */  
12 @Schema(description = "管理后台 - 秒杀参与商品更新 Request VO") 8 @Schema(description = "管理后台 - 秒杀参与商品更新 Request VO")
13 @Data 9 @Data
14 @EqualsAndHashCode(callSuper = true) 10 @EqualsAndHashCode(callSuper = true)
15 @ToString(callSuper = true) 11 @ToString(callSuper = true)
16 public class SeckillProductUpdateReqVO extends SeckillProductBaseVO { 12 public class SeckillProductUpdateReqVO extends SeckillProductBaseVO {
17 13
18 - @Schema(description = "秒杀参与商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "256")  
19 - @NotNull(message = "秒杀参与商品编号不能为空")  
20 - private Long id;  
21 -  
22 } 14 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.convert.combination;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
  6 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;
  7 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
  8 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExcelVO;
  9 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO;
  10 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
  11 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
  12 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO;
  13 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
  14 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
  15 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;
  16 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO;
  17 +import org.mapstruct.Mapper;
  18 +import org.mapstruct.Mapping;
  19 +import org.mapstruct.Mappings;
  20 +import org.mapstruct.Named;
  21 +import org.mapstruct.factory.Mappers;
  22 +
  23 +import java.time.LocalDateTime;
  24 +import java.util.ArrayList;
  25 +import java.util.List;
  26 +import java.util.Map;
  27 +
  28 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  29 +
  30 +/**
  31 + * 拼团活动 Convert
  32 + *
  33 + * @author HUIHUI
  34 + */
  35 +@Mapper
  36 +public interface CombinationActivityConvert {
  37 +
  38 + CombinationActivityConvert INSTANCE = Mappers.getMapper(CombinationActivityConvert.class);
  39 +
  40 + @Mappings({
  41 + @Mapping(target = "startTime", expression = "java(bean.getActivityTime()[0])"),
  42 + @Mapping(target = "endTime", expression = "java(bean.getActivityTime()[1])")
  43 + })
  44 + CombinationActivityDO convert(CombinationActivityCreateReqVO bean);
  45 +
  46 + @Mappings({
  47 + @Mapping(target = "startTime", expression = "java(bean.getActivityTime()[0])"),
  48 + @Mapping(target = "endTime", expression = "java(bean.getActivityTime()[1])")
  49 + })
  50 + CombinationActivityDO convert(CombinationActivityUpdateReqVO bean);
  51 +
  52 + @Named("mergeTime")
  53 + default LocalDateTime[] mergeTime(LocalDateTime startTime, LocalDateTime endTime) {
  54 + // TODO 有点怪第一次这样写 hh
  55 + LocalDateTime[] localDateTime = new LocalDateTime[2];
  56 + localDateTime[0] = startTime;
  57 + localDateTime[1] = endTime;
  58 + return localDateTime;
  59 + }
  60 +
  61 + @Mappings({
  62 + @Mapping(target = "activityTime", expression = "java(mergeTime(bean.getStartTime(),bean.getEndTime()))")
  63 + })
  64 + CombinationActivityRespVO convert(CombinationActivityDO bean);
  65 +
  66 + CombinationProductRespVO convert(CombinationProductDO bean);
  67 +
  68 + default CombinationActivityRespVO convert(CombinationActivityDO bean, List<CombinationProductDO> productDOs) {
  69 + CombinationActivityRespVO respVO = convert(bean);
  70 + respVO.setProducts(convertList2(productDOs));
  71 + return respVO;
  72 + }
  73 +
  74 + List<CombinationActivityRespVO> convertList(List<CombinationActivityDO> list);
  75 +
  76 + PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page);
  77 +
  78 + default PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page,
  79 + List<CombinationProductDO> productList,
  80 + List<ProductSpuRespDTO> spuList) {
  81 + // TODO @puhui999:c -> c 可以去掉哈
  82 + Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId, c -> c);
  83 + PageResult<CombinationActivityRespVO> pageResult = convertPage(page);
  84 + pageResult.getList().forEach(item -> {
  85 + // TODO @puhui999:最好 MapUtils.findAndThen,万一没找到呢,啊哈哈。
  86 + item.setSpuName(spuMap.get(item.getSpuId()).getName());
  87 + item.setPicUrl(spuMap.get(item.getSpuId()).getPicUrl());
  88 + item.setProducts(convertList2(productList));
  89 + });
  90 + return pageResult;
  91 + }
  92 +
  93 + List<CombinationProductRespVO> convertList2(List<CombinationProductDO> productDOs);
  94 +
  95 + List<CombinationActivityExcelVO> convertList02(List<CombinationActivityDO> list);
  96 +
  97 + @Mappings({
  98 + @Mapping(target = "id", ignore = true),
  99 + @Mapping(target = "activityId", source = "activityDO.id"),
  100 + @Mapping(target = "spuId", source = "activityDO.spuId"),
  101 + @Mapping(target = "skuId", source = "vo.skuId"),
  102 + @Mapping(target = "activePrice", source = "vo.activePrice"),
  103 + @Mapping(target = "activityStartTime", source = "activityDO.startTime"),
  104 + @Mapping(target = "activityEndTime", source = "activityDO.endTime")
  105 + })
  106 + CombinationProductDO convert(CombinationActivityDO activityDO, CombinationProductBaseVO vo);
  107 +
  108 + default List<CombinationProductDO> convertList(CombinationActivityDO activityDO, List<? extends CombinationProductBaseVO> products) {
  109 + List<CombinationProductDO> list = new ArrayList<>();
  110 + products.forEach(sku -> {
  111 + CombinationProductDO productDO = convert(activityDO, sku);
  112 + // TODO 状态设置
  113 + productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());
  114 + list.add(productDO);
  115 + });
  116 + return list;
  117 + }
  118 +
  119 + // TODO @puhui999:这个方法的参数,调整成 productDOs、vos、activityDO;因为 productDOs 是主角;
  120 + // 然后,这个方法,感觉不是为了 convert,而是为了补全;
  121 + default List<CombinationProductDO> convertList1(CombinationActivityDO activityDO,
  122 + List<CombinationProductUpdateReqVO> vos,
  123 + List<CombinationProductDO> productDOs) {
  124 + Map<Long, Long> longMap = convertMap(productDOs, CombinationProductDO::getSkuId, CombinationProductDO::getId);
  125 + List<CombinationProductDO> list = new ArrayList<>();
  126 + vos.forEach(sku -> {
  127 + CombinationProductDO productDO = convert(activityDO, sku);
  128 + productDO.setId(longMap.get(sku.getSkuId()));
  129 + // TODO @puhui999:是是不是用 activityDO 的状态;
  130 + productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());
  131 + list.add(productDO);
  132 + });
  133 + return list;
  134 + }
  135 +
  136 + CombinationRecordDO convert(CombinationRecordReqDTO reqDTO);
  137 +
  138 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
1 package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
2 2
3 -import cn.hutool.core.util.ObjectUtil;  
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  6 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
6 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; 7 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
7 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO; 8 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO;
8 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO; 9 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO;
9 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; 10 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
10 -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductCreateReqVO; 11 +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
  12 +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductRespVO;
  13 +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO;
11 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; 14 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
12 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; 15 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
13 import org.mapstruct.Mapper; 16 import org.mapstruct.Mapper;
  17 +import org.mapstruct.Mapping;
  18 +import org.mapstruct.Mappings;
14 import org.mapstruct.factory.Mappers; 19 import org.mapstruct.factory.Mappers;
15 20
16 import java.util.ArrayList; 21 import java.util.ArrayList;
17 import java.util.List; 22 import java.util.List;
  23 +import java.util.Map;
18 24
19 /** 25 /**
20 * 秒杀活动 Convert 26 * 秒杀活动 Convert
@@ -26,8 +32,6 @@ public interface SeckillActivityConvert { @@ -26,8 +32,6 @@ public interface SeckillActivityConvert {
26 32
27 SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class); 33 SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class);
28 34
29 - SeckillProductDO convert(SeckillProductCreateReqVO product);  
30 -  
31 SeckillActivityDO convert(SeckillActivityCreateReqVO bean); 35 SeckillActivityDO convert(SeckillActivityCreateReqVO bean);
32 36
33 SeckillActivityDO convert(SeckillActivityUpdateReqVO bean); 37 SeckillActivityDO convert(SeckillActivityUpdateReqVO bean);
@@ -38,53 +42,61 @@ public interface SeckillActivityConvert { @@ -38,53 +42,61 @@ public interface SeckillActivityConvert {
38 42
39 PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page); 43 PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
40 44
41 - SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts);  
42 -  
43 -  
44 - /**  
45 - * 比较两个秒杀商品对象是否相等  
46 - *  
47 - * @param productDO 数据库中的商品  
48 - * @param productVO 前端传入的商品  
49 - * @return 是否匹配  
50 - */  
51 - default boolean isEquals(SeckillProductDO productDO, SeckillProductCreateReqVO productVO) {  
52 - return ObjectUtil.equals(productDO.getSpuId(), 1) // TODO puhui:再看看  
53 - && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())  
54 - && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice());  
55 - //&& ObjectUtil.equals(productDO.getQuota(), productVO.getQuota())  
56 - //&& ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount()); 45 + default PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page, List<SeckillProductDO> seckillProducts, List<ProductSpuRespDTO> spuList) {
  46 + Map<Long, ProductSpuRespDTO> spuMap = CollectionUtils.convertMap(spuList, ProductSpuRespDTO::getId, c -> c);
  47 + PageResult<SeckillActivityRespVO> pageResult = convertPage(page);
  48 + pageResult.getList().forEach(item -> {
  49 + item.setSpuName(spuMap.get(item.getSpuId()).getName());
  50 + item.setPicUrl(spuMap.get(item.getSpuId()).getPicUrl());
  51 + item.setProducts(convertList2(seckillProducts));
  52 + });
  53 + return pageResult;
57 } 54 }
58 55
59 - /**  
60 - * 比较两个秒杀商品对象是否相等  
61 - *  
62 - * @param productDO 商品1  
63 - * @param productVO 商品2  
64 - * @return 是否匹配  
65 - */  
66 - default boolean isEquals(SeckillProductDO productDO, SeckillProductDO productVO) {  
67 - return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId())  
68 - && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())  
69 - && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice());  
70 - //&& ObjectUtil.equals(productDO.getQuota(), productVO.getQuota())  
71 - //&& ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount()); 56 + SeckillActivityDetailRespVO convert1(SeckillActivityDO seckillActivity);
  57 +
  58 + default SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts) {
  59 + SeckillActivityDetailRespVO respVO = convert1(seckillActivity);
  60 + respVO.setProducts(convertList2(seckillProducts));
  61 + return respVO;
72 } 62 }
73 63
74 - default List<SeckillProductDO> convertList(SeckillActivityDO seckillActivity, List<SeckillProductCreateReqVO> products) { 64 + @Mappings({
  65 + @Mapping(target = "id", ignore = true),
  66 + @Mapping(target = "activityId", source = "activityDO.id"),
  67 + @Mapping(target = "configIds", source = "activityDO.configIds"),
  68 + @Mapping(target = "spuId", source = "activityDO.spuId"),
  69 + @Mapping(target = "skuId", source = "vo.skuId"),
  70 + @Mapping(target = "seckillPrice", source = "vo.seckillPrice"),
  71 + @Mapping(target = "stock", source = "vo.stock"),
  72 + @Mapping(target = "activityStartTime", source = "activityDO.startTime"),
  73 + @Mapping(target = "activityEndTime", source = "activityDO.endTime")
  74 + })
  75 + SeckillProductDO convert(SeckillActivityDO activityDO, SeckillProductBaseVO vo);
  76 +
  77 + default List<SeckillProductDO> convertList(SeckillActivityDO activityDO, List<? extends SeckillProductBaseVO> products) {
75 List<SeckillProductDO> list = new ArrayList<>(); 78 List<SeckillProductDO> list = new ArrayList<>();
76 products.forEach(sku -> { 79 products.forEach(sku -> {
77 - SeckillProductDO productDO = new SeckillProductDO();  
78 - productDO.setActivityId(seckillActivity.getId());  
79 - productDO.setConfigIds(seckillActivity.getConfigIds());  
80 - productDO.setSpuId(sku.getSpuId());  
81 - productDO.setSkuId(sku.getSkuId());  
82 - productDO.setSeckillPrice(sku.getSeckillPrice());  
83 - productDO.setStock(sku.getStock()); 80 + SeckillProductDO productDO = convert(activityDO, sku);
  81 + productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());
  82 + list.add(productDO);
  83 + });
  84 + return list;
  85 + }
  86 +
  87 + // TODO @puhui999:同拼团那个 convert 想通的情况哈。
  88 + default List<SeckillProductDO> convertList1(SeckillActivityDO activityDO, List<SeckillProductUpdateReqVO> vos, List<SeckillProductDO> productDOs) {
  89 + Map<Long, Long> longMap = CollectionUtils.convertMap(productDOs, SeckillProductDO::getSkuId, SeckillProductDO::getId);
  90 + List<SeckillProductDO> list = new ArrayList<>();
  91 + vos.forEach(sku -> {
  92 + SeckillProductDO productDO = convert(activityDO, sku);
  93 + productDO.setId(longMap.get(sku.getSkuId()));
84 productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus()); 94 productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());
85 - productDO.setActivityStartTime(seckillActivity.getStartTime());  
86 - productDO.setActivityEndTime(seckillActivity.getEndTime()); 95 + list.add(productDO);
87 }); 96 });
88 return list; 97 return list;
89 } 98 }
  99 +
  100 + List<SeckillProductRespVO> convertList2(List<SeckillProductDO> productDOs);
  101 +
90 } 102 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationActivityDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import com.baomidou.mybatisplus.annotation.KeySequence;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import lombok.*;
  9 +
  10 +import java.time.LocalDateTime;
  11 +
  12 +// TODO @puhui999:是不是应该在 combination 哈?
  13 +/**
  14 + * 拼团活动 DO
  15 + *
  16 + * @author HUIHUI
  17 + */
  18 +@TableName("promotion_combination_activity")
  19 +@KeySequence("promotion_combination_activity_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  20 +@Data
  21 +@EqualsAndHashCode(callSuper = true)
  22 +@ToString(callSuper = true)
  23 +@Builder
  24 +@NoArgsConstructor
  25 +@AllArgsConstructor
  26 +public class CombinationActivityDO extends BaseDO {
  27 +
  28 + /**
  29 + * 活动编号
  30 + */
  31 + @TableId
  32 + private Long id;
  33 + /**
  34 + * 拼团名称
  35 + */
  36 + private String name;
  37 + /**
  38 + * 商品 SPU 编号
  39 + *
  40 + * 关联 ProductSpuDO 的 id
  41 + */
  42 + private Long spuId;
  43 + /**
  44 + * 总限购数量
  45 + */
  46 + private Integer totalLimitCount;
  47 + /**
  48 + * 单次限购数量
  49 + */
  50 + private Integer singleLimitCount;
  51 + /**
  52 + * 开始时间
  53 + */
  54 + private LocalDateTime startTime;
  55 + /**
  56 + * 结束时间
  57 + */
  58 + private LocalDateTime endTime;
  59 + /**
  60 + * 几人团
  61 + */
  62 + private Integer userSize;
  63 + /**
  64 + * 开团组数
  65 + */
  66 + private Integer totalNum;
  67 + /**
  68 + * 成团组数
  69 + */
  70 + private Integer successNum;
  71 + /**
  72 + * 参与人数
  73 + */
  74 + private Integer orderUserCount;
  75 + /**
  76 + * 虚拟成团
  77 + */
  78 + private Integer virtualGroup;
  79 + /**
  80 + * 活动状态:0开启 1关闭
  81 + *
  82 + * 枚举 {@link CommonStatusEnum}
  83 + */
  84 + private Integer status;
  85 + /**
  86 + * 限制时长(小时)
  87 + */
  88 + private Integer limitDuration;
  89 +
  90 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationProductDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.KeySequence;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.*;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * 拼团商品 DO
  13 + *
  14 + * @author HUIHUI
  15 + */
  16 +@TableName("promotion_combination_product")
  17 +@KeySequence("promotion_combination_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  18 +@Data
  19 +@EqualsAndHashCode(callSuper = true)
  20 +@ToString(callSuper = true)
  21 +@Builder
  22 +@NoArgsConstructor
  23 +@AllArgsConstructor
  24 +public class CombinationProductDO extends BaseDO {
  25 +
  26 + /**
  27 + * 编号
  28 + */
  29 + @TableId
  30 + private Long id;
  31 + /**
  32 + * 拼团活动编号
  33 + */
  34 + private Long activityId;
  35 + /**
  36 + * 商品 SPU 编号
  37 + */
  38 + private Long spuId;
  39 + /**
  40 + * 商品 SKU 编号
  41 + */
  42 + private Long skuId;
  43 + /**
  44 + * 拼团商品状态
  45 + */
  46 + private Integer activityStatus;
  47 + /**
  48 + * 活动开始时间点
  49 + */
  50 + private LocalDateTime activityStartTime;
  51 + /**
  52 + * 活动结束时间点
  53 + */
  54 + private LocalDateTime activityEndTime;
  55 + /**
  56 + * 拼团价格,单位分
  57 + */
  58 + private Integer activePrice;
  59 +
  60 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationRecordDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
  5 +import com.baomidou.mybatisplus.annotation.KeySequence;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import lombok.*;
  9 +
  10 +import java.time.LocalDateTime;
  11 +
  12 +/**
  13 + * 拼团记录 DO
  14 + *
  15 + * @author HUIHUI
  16 + */
  17 +@TableName("promotion_combination_record")
  18 +@KeySequence("promotion_combination_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  19 +@Data
  20 +@EqualsAndHashCode(callSuper = true)
  21 +@ToString(callSuper = true)
  22 +@Builder
  23 +@NoArgsConstructor
  24 +@AllArgsConstructor
  25 +public class CombinationRecordDO extends BaseDO {
  26 +
  27 + @TableId
  28 + private Long id;
  29 + /**
  30 + * 拼团活动编号
  31 + */
  32 + private Long activityId;
  33 + /**
  34 + * SPU 编号
  35 + */
  36 + private Long spuId;
  37 + /**
  38 + * SKU 编号
  39 + */
  40 + private Long skuId;
  41 + /**
  42 + * 用户编号
  43 + */
  44 + private Long userId;
  45 + /**
  46 + * 订单编号
  47 + */
  48 + private Long orderId;
  49 + /**
  50 + * 团长编号
  51 + *
  52 + * 关联 {@link CombinationRecordDO#getUserId()}
  53 + */
  54 + private Long headId;
  55 + /**
  56 + * 商品名字
  57 + */
  58 + private String spuName;
  59 + /**
  60 + * 商品图片
  61 + */
  62 + private String picUrl;
  63 + /**
  64 + * 拼团商品单价
  65 + */
  66 + private Integer combinationPrice;
  67 + /**
  68 + * 用户昵称
  69 + */
  70 + private String nickname;
  71 + /**
  72 + * 用户头像
  73 + */
  74 + private String avatar;
  75 + /**
  76 + * 开团状态
  77 + *
  78 + * 关联 {@link CombinationRecordStatusEnum}
  79 + */
  80 + private Integer status;
  81 + /**
  82 + * 是否虚拟成团
  83 + */
  84 + private Boolean virtualGroup;
  85 + /**
  86 + * 过期时间,单位:小时
  87 + *
  88 + * 关联 {@link CombinationActivityDO#getLimitDuration()}
  89 + */
  90 + private Integer expireTime;
  91 + /**
  92 + * 开始时间 (订单付款后开始的时间)
  93 + */
  94 + private LocalDateTime startTime;
  95 + /**
  96 + * 结束时间(成团时间/失败时间)
  97 + */
  98 + private LocalDateTime endTime;
  99 + /**
  100 + * 开团需要人数
  101 + *
  102 + * 关联 {@link CombinationActivityDO#getUserSize()}
  103 + */
  104 + private Integer userSize;
  105 + /**
  106 + * 已加入拼团人数
  107 + */
  108 + private Integer userCount;
  109 +
  110 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java
@@ -34,8 +34,7 @@ public class SeckillActivityDO extends BaseDO { @@ -34,8 +34,7 @@ public class SeckillActivityDO extends BaseDO {
34 /** 34 /**
35 * 秒杀活动商品 35 * 秒杀活动商品
36 */ 36 */
37 - @TableField(typeHandler = LongListTypeHandler.class)  
38 - private List<Long> spuIds; 37 + private Long spuId;
39 /** 38 /**
40 * 秒杀活动名称 39 * 秒杀活动名称
41 */ 40 */
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java
@@ -47,11 +47,11 @@ public class SeckillProductDO extends BaseDO { @@ -47,11 +47,11 @@ public class SeckillProductDO extends BaseDO {
47 @TableField(typeHandler = LongListTypeHandler.class) 47 @TableField(typeHandler = LongListTypeHandler.class)
48 private List<Long> configIds; 48 private List<Long> configIds;
49 /** 49 /**
50 - * 商品 spu_id 50 + * 商品 SPU 编号
51 */ 51 */
52 private Long spuId; 52 private Long spuId;
53 /** 53 /**
54 - * 商品 sku_id 54 + * 商品 SKU 编号
55 */ 55 */
56 private Long skuId; 56 private Long skuId;
57 /** 57 /**
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java
@@ -3,22 +3,27 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig; @@ -3,22 +3,27 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig;
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 import com.baomidou.mybatisplus.annotation.KeySequence; 5 import com.baomidou.mybatisplus.annotation.KeySequence;
  6 +import com.baomidou.mybatisplus.annotation.TableField;
6 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
8 -import lombok.Data;  
9 -import lombok.EqualsAndHashCode;  
10 -import lombok.ToString; 9 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
  10 +import lombok.*;
  11 +
  12 +import java.util.List;
11 13
12 /** 14 /**
13 * 秒杀时段 DO 15 * 秒杀时段 DO
14 * 16 *
15 * @author 芋道源码 17 * @author 芋道源码
16 */ 18 */
17 -@TableName("promotion_seckill_config") 19 +@TableName(value = "promotion_seckill_config", autoResultMap = true)
18 @KeySequence("promotion_seckill_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 20 @KeySequence("promotion_seckill_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
19 @Data 21 @Data
20 @EqualsAndHashCode(callSuper = true) 22 @EqualsAndHashCode(callSuper = true)
21 @ToString(callSuper = true) 23 @ToString(callSuper = true)
  24 +@Builder
  25 +@NoArgsConstructor
  26 +@AllArgsConstructor
22 public class SeckillConfigDO extends BaseDO { 27 public class SeckillConfigDO extends BaseDO {
23 28
24 /** 29 /**
@@ -38,11 +43,11 @@ public class SeckillConfigDO extends BaseDO { @@ -38,11 +43,11 @@ public class SeckillConfigDO extends BaseDO {
38 * 结束时间点 43 * 结束时间点
39 */ 44 */
40 private String endTime; 45 private String endTime;
41 - // TODO puhui999:应该是轮播图; private List<String> sliderPicUrls;  
42 /** 46 /**
43 - * 秒杀主图 47 + * 秒杀轮播图
44 */ 48 */
45 - private String picUrl; 49 + @TableField(typeHandler = JacksonTypeHandler.class)
  50 + private List<String> sliderPicUrls;
46 /** 51 /**
47 * 状态 52 * 状态
48 * 53 *
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationActivityMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;
  7 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
  8 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +
  11 +import java.util.List;
  12 +
  13 +// TODO @puhui999:是不是应该在 combination 哈?
  14 +/**
  15 + * 拼团活动 Mapper
  16 + *
  17 + * @author HUIHUI
  18 + */
  19 +@Mapper
  20 +public interface CombinationActivityMapper extends BaseMapperX<CombinationActivityDO> {
  21 +
  22 + default PageResult<CombinationActivityDO> selectPage(CombinationActivityPageReqVO reqVO) {
  23 + return selectPage(reqVO, new LambdaQueryWrapperX<CombinationActivityDO>()
  24 + .likeIfPresent(CombinationActivityDO::getName, reqVO.getName())
  25 + .orderByDesc(CombinationActivityDO::getId));
  26 + }
  27 +
  28 + default List<CombinationActivityDO> selectList(CombinationActivityExportReqVO reqVO) {
  29 + return selectList(new LambdaQueryWrapperX<CombinationActivityDO>()
  30 + .likeIfPresent(CombinationActivityDO::getName, reqVO.getName())
  31 + .eqIfPresent(CombinationActivityDO::getStatus, reqVO.getStatus())
  32 + .orderByDesc(CombinationActivityDO::getId));
  33 + }
  34 +
  35 + default List<CombinationActivityDO> selectListByStatus(Integer status) {
  36 + return selectList(CombinationActivityDO::getStatus, status);
  37 + }
  38 +
  39 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationProductMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductExportReqVO;
  7 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductPageReqVO;
  8 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +
  11 +import java.util.Collection;
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * 拼团商品 Mapper
  16 + *
  17 + * @author HUIHUI
  18 + */
  19 +@Mapper
  20 +public interface CombinationProductMapper extends BaseMapperX<CombinationProductDO> {
  21 +
  22 + default PageResult<CombinationProductDO> selectPage(CombinationProductPageReqVO reqVO) {
  23 + return selectPage(reqVO, new LambdaQueryWrapperX<CombinationProductDO>()
  24 + .eqIfPresent(CombinationProductDO::getActivityId, reqVO.getActivityId())
  25 + .eqIfPresent(CombinationProductDO::getSpuId, reqVO.getSpuId())
  26 + .eqIfPresent(CombinationProductDO::getSkuId, reqVO.getSkuId())
  27 + .eqIfPresent(CombinationProductDO::getActivityStatus, reqVO.getActivityStatus())
  28 + .betweenIfPresent(CombinationProductDO::getActivityStartTime, reqVO.getActivityStartTime())
  29 + .betweenIfPresent(CombinationProductDO::getActivityEndTime, reqVO.getActivityEndTime())
  30 + .eqIfPresent(CombinationProductDO::getActivePrice, reqVO.getActivePrice())
  31 + .betweenIfPresent(CombinationProductDO::getCreateTime, reqVO.getCreateTime())
  32 + .orderByDesc(CombinationProductDO::getId));
  33 + }
  34 +
  35 + default List<CombinationProductDO> selectList(CombinationProductExportReqVO reqVO) {
  36 + return selectList(new LambdaQueryWrapperX<CombinationProductDO>()
  37 + .eqIfPresent(CombinationProductDO::getActivityId, reqVO.getActivityId())
  38 + .eqIfPresent(CombinationProductDO::getSpuId, reqVO.getSpuId())
  39 + .eqIfPresent(CombinationProductDO::getSkuId, reqVO.getSkuId())
  40 + .eqIfPresent(CombinationProductDO::getActivityStatus, reqVO.getActivityStatus())
  41 + .betweenIfPresent(CombinationProductDO::getActivityStartTime, reqVO.getActivityStartTime())
  42 + .betweenIfPresent(CombinationProductDO::getActivityEndTime, reqVO.getActivityEndTime())
  43 + .eqIfPresent(CombinationProductDO::getActivePrice, reqVO.getActivePrice())
  44 + .betweenIfPresent(CombinationProductDO::getCreateTime, reqVO.getCreateTime())
  45 + .orderByDesc(CombinationProductDO::getId));
  46 + }
  47 +
  48 + default List<CombinationProductDO> selectListByActivityIds(Collection<Long> ids) {
  49 + return selectList(CombinationProductDO::getActivityId, ids);
  50 + }
  51 +
  52 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationRecordMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  5 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO;
  6 +import org.apache.ibatis.annotations.Mapper;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * 拼团记录 Mapper
  12 + *
  13 + * @author HUIHUI
  14 + */
  15 +@Mapper
  16 +public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO> {
  17 +
  18 + default CombinationRecordDO selectRecord(Long userId, Long orderId) {
  19 + return selectOne(CombinationRecordDO::getUserId, userId,
  20 + CombinationRecordDO::getOrderId, orderId);
  21 + }
  22 +
  23 + default List<CombinationRecordDO> selectListByHeadIdAndStatus(Long headId, Integer status) {
  24 + return selectList(new LambdaQueryWrapperX<CombinationRecordDO>()
  25 + .eq(CombinationRecordDO::getHeadId, headId)
  26 + .eq(CombinationRecordDO::getStatus, status));
  27 + }
  28 +
  29 + default List<CombinationRecordDO> selectListByStatus(Integer status) {
  30 + return selectList(CombinationRecordDO::getStatus, status);
  31 + }
  32 +
  33 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
@@ -21,6 +21,10 @@ public interface SeckillProductMapper extends BaseMapperX&lt;SeckillProductDO&gt; { @@ -21,6 +21,10 @@ public interface SeckillProductMapper extends BaseMapperX&lt;SeckillProductDO&gt; {
21 return selectList(SeckillProductDO::getActivityId, id); 21 return selectList(SeckillProductDO::getActivityId, id);
22 } 22 }
23 23
  24 + default List<SeckillProductDO> selectListByActivityId(Collection<Long> ids) {
  25 + return selectList(SeckillProductDO::getActivityId, ids);
  26 + }
  27 +
24 default List<SeckillProductDO> selectListBySkuIds(Collection<Long> skuIds) { 28 default List<SeckillProductDO> selectListBySkuIds(Collection<Long> skuIds) {
25 return selectList(SeckillProductDO::getSkuId, skuIds); 29 return selectList(SeckillProductDO::getSkuId, skuIds);
26 } 30 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java
@@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.Seck @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.Seck
7 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO; 7 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
8 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
9 9
  10 +import java.util.List;
  11 +
10 @Mapper 12 @Mapper
11 public interface SeckillConfigMapper extends BaseMapperX<SeckillConfigDO> { 13 public interface SeckillConfigMapper extends BaseMapperX<SeckillConfigDO> {
12 14
@@ -17,4 +19,8 @@ public interface SeckillConfigMapper extends BaseMapperX&lt;SeckillConfigDO&gt; { @@ -17,4 +19,8 @@ public interface SeckillConfigMapper extends BaseMapperX&lt;SeckillConfigDO&gt; {
17 .orderByDesc(SeckillConfigDO::getId)); 19 .orderByDesc(SeckillConfigDO::getId));
18 } 20 }
19 21
  22 + default List<SeckillConfigDO> selectListByStatus(Integer status) {
  23 + return selectList(SeckillConfigDO::getStatus, status);
  24 + }
  25 +
20 } 26 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.combination;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;
  5 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
  6 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;
  7 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
  8 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
  9 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
  10 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;
  11 +
  12 +import javax.validation.Valid;
  13 +import java.time.LocalDateTime;
  14 +import java.util.Collection;
  15 +import java.util.List;
  16 +
  17 +/**
  18 + * 拼团活动 Service 接口
  19 + *
  20 + * @author HUIHUI
  21 + */
  22 +public interface CombinationActivityService {
  23 +
  24 + /**
  25 + * 创建拼团活动
  26 + *
  27 + * @param createReqVO 创建信息
  28 + * @return 编号
  29 + */
  30 + Long createCombinationActivity(@Valid CombinationActivityCreateReqVO createReqVO);
  31 +
  32 + /**
  33 + * 更新拼团活动
  34 + *
  35 + * @param updateReqVO 更新信息
  36 + */
  37 + void updateCombinationActivity(@Valid CombinationActivityUpdateReqVO updateReqVO);
  38 +
  39 + /**
  40 + * 删除拼团活动
  41 + *
  42 + * @param id 编号
  43 + */
  44 + void deleteCombinationActivity(Long id);
  45 +
  46 + /**
  47 + * 获得拼团活动
  48 + *
  49 + * @param id 编号
  50 + * @return 拼团活动
  51 + */
  52 + CombinationActivityDO getCombinationActivity(Long id);
  53 +
  54 + /**
  55 + * 获得拼团活动列表
  56 + *
  57 + * @param ids 编号
  58 + * @return 拼团活动列表
  59 + */
  60 + List<CombinationActivityDO> getCombinationActivityList(Collection<Long> ids);
  61 +
  62 + /**
  63 + * 获得拼团活动分页
  64 + *
  65 + * @param pageReqVO 分页查询
  66 + * @return 拼团活动分页
  67 + */
  68 + PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO);
  69 +
  70 + /**
  71 + * 获得拼团活动列表, 用于 Excel 导出
  72 + *
  73 + * @param exportReqVO 查询条件
  74 + * @return 拼团活动列表
  75 + */
  76 + List<CombinationActivityDO> getCombinationActivityList(CombinationActivityExportReqVO exportReqVO);
  77 +
  78 + /**
  79 + * 获得拼团活动商品列表
  80 + *
  81 + * @param ids 拼团活动 ids
  82 + * @return 拼团活动的商品列表
  83 + */
  84 + List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids);
  85 +
  86 + // TODO @puhui999:拆一个 CombinationRecordService 里,方法名可以简洁成 updateRecordStatusByOrderId;service 方法可以稍微简单一点,如果是 update 方法
  87 + /**
  88 + * 更新拼团状态
  89 + *
  90 + * @param userId 用户编号
  91 + * @param orderId 订单编号
  92 + * @param status 状态
  93 + */
  94 + void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status);
  95 +
  96 + /**
  97 + * 更新拼团状态和开始时间
  98 + *
  99 + * @param userId 用户编号
  100 + * @param orderId 订单编号
  101 + * @param status 状态
  102 + * @param startTime 开始时间
  103 + */
  104 + void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime);
  105 +
  106 + // TODO @puhui999:拆一个 CombinationRecordService 里
  107 + /**
  108 + * 创建拼团记录
  109 + *
  110 + * @param reqDTO 创建信息
  111 + */
  112 + void createRecord(CombinationRecordReqDTO reqDTO);
  113 +
  114 + /**
  115 + * 获得拼团状态
  116 + *
  117 + * @param userId 用户编号
  118 + * @param orderId 订单编号
  119 + * @return 拼团状态
  120 + */
  121 + boolean validateRecordStatusIsSuccess(Long userId, Long orderId);
  122 +
  123 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.combination;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.collection.CollectionUtil;
  5 +import cn.hutool.core.util.ObjectUtil;
  6 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  7 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  8 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  9 +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
  10 +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
  11 +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
  12 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
  13 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordReqDTO;
  14 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
  15 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityExportReqVO;
  16 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
  17 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
  18 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO;
  19 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
  20 +import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
  21 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationActivityDO;
  22 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationProductDO;
  23 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.combinationactivity.CombinationRecordDO;
  24 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationActivityMapper;
  25 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationProductMapper;
  26 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.combinationactivity.CombinationRecordMapper;
  27 +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
  28 +import org.springframework.stereotype.Service;
  29 +import org.springframework.transaction.annotation.Transactional;
  30 +import org.springframework.validation.annotation.Validated;
  31 +
  32 +import javax.annotation.Resource;
  33 +import java.time.LocalDateTime;
  34 +import java.util.Collection;
  35 +import java.util.List;
  36 +import java.util.Set;
  37 +
  38 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  39 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
  40 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
  41 +import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence;
  42 +
  43 +/**
  44 + * 拼团活动 Service 实现类
  45 + *
  46 + * @author HUIHUI
  47 + */
  48 +@Service
  49 +@Validated
  50 +public class CombinationActivityServiceImpl implements CombinationActivityService {
  51 +
  52 + @Resource
  53 + private CombinationActivityMapper combinationActivityMapper;
  54 + @Resource
  55 + private CombinationRecordMapper recordMapper;
  56 + @Resource
  57 + private CombinationProductMapper combinationProductMapper;
  58 + @Resource
  59 + private ProductSpuApi productSpuApi;
  60 + @Resource
  61 + private ProductSkuApi productSkuApi;
  62 +
  63 + @Override
  64 + public Long createCombinationActivity(CombinationActivityCreateReqVO createReqVO) {
  65 + // 校验商品 SPU 是否存在是否参加的别的活动
  66 + validateProductCombinationConflict(createReqVO.getSpuId(), null);
  67 + // 获取所选 spu下的所有 sku
  68 + List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(createReqVO.getSpuId()));
  69 + // 校验商品 sku 是否存在
  70 + validateProductSkuExistence(skus, createReqVO.getProducts(), CombinationProductCreateReqVO::getSkuId);
  71 +
  72 + // TODO 艿艿 有个小问题:现在有活动时间和限制时长,活动时间的结束时间早于设置的限制时间怎么算状态比如:
  73 + // 活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时,那么活动时间结束就结束还是加时到满两小时
  74 + // 插入拼团活动
  75 + CombinationActivityDO activityDO = CombinationActivityConvert.INSTANCE.convert(createReqVO);
  76 + // TODO 营销相关属性初始化
  77 + activityDO.setTotalNum(0);
  78 + activityDO.setSuccessNum(0);
  79 + activityDO.setOrderUserCount(0);
  80 + activityDO.setVirtualGroup(0);
  81 + activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  82 + combinationActivityMapper.insert(activityDO);
  83 + // 插入商品
  84 + List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(activityDO, createReqVO.getProducts());
  85 + combinationProductMapper.insertBatch(productDOs);
  86 + // 返回
  87 + return activityDO.getId();
  88 + }
  89 +
  90 + private void validateProductCombinationConflict(Long spuId, Long activityId) {
  91 + // 校验商品 spu 是否存在
  92 + List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(CollUtil.newArrayList(spuId));
  93 + if (CollUtil.isEmpty(spuList)) {
  94 + throw exception(SPU_NOT_EXISTS);
  95 + }
  96 + // 查询所有开启的拼团活动
  97 + List<CombinationActivityDO> activityDOs = combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
  98 + // 更新时排除自己
  99 + if (activityId != null) {
  100 + activityDOs.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
  101 + }
  102 + // 过滤出所有 spuIds 有交集的活动
  103 + List<CombinationActivityDO> doList = CollectionUtils.convertList(activityDOs, c -> c, s -> ObjectUtil.equal(s.getId(), spuId));
  104 + if (CollUtil.isNotEmpty(doList)) {
  105 + throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS);
  106 + }
  107 + }
  108 +
  109 + @Override
  110 + public void updateCombinationActivity(CombinationActivityUpdateReqVO updateReqVO) {
  111 + // 校验存在
  112 + CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId());
  113 + // 校验状态
  114 + if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
  115 + throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
  116 + }
  117 + // 校验商品冲突
  118 + validateProductCombinationConflict(updateReqVO.getSpuId(), updateReqVO.getId());
  119 + // 获取所选 spu下的所有 sku
  120 + List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(updateReqVO.getSpuId()));
  121 + // 校验商品 sku 是否存在
  122 + validateProductSkuExistence(skus, updateReqVO.getProducts(), CombinationProductUpdateReqVO::getSkuId);
  123 +
  124 + // 更新
  125 + CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO);
  126 + combinationActivityMapper.updateById(updateObj);
  127 + // 更新商品
  128 + updateCombinationProduct(updateObj, updateReqVO.getProducts());
  129 + }
  130 +
  131 + /**
  132 + * 更新秒杀商品
  133 + * TODO 更新商品要不要封装成通用方法
  134 + *
  135 + * @param updateObj DO
  136 + * @param products 商品配置
  137 + */
  138 + private void updateCombinationProduct(CombinationActivityDO updateObj, List<CombinationProductUpdateReqVO> products) {
  139 + List<CombinationProductDO> combinationProductDOs = combinationProductMapper.selectListByActivityIds(CollUtil.newArrayList(updateObj.getId()));
  140 + // 数据库中的活动商品
  141 + Set<Long> convertSet = CollectionUtils.convertSet(combinationProductDOs, CombinationProductDO::getSkuId);
  142 + // 前端传过来的活动商品
  143 + Set<Long> convertSet1 = CollectionUtils.convertSet(products, CombinationProductUpdateReqVO::getSkuId);
  144 + // 删除后台存在的前端不存在的商品
  145 + List<Long> d = CollectionUtils.filterList(convertSet, item -> !convertSet1.contains(item));
  146 + if (CollUtil.isNotEmpty(d)) {
  147 + combinationProductMapper.deleteBatchIds(d);
  148 + }
  149 + // 前端存在的后端不存在的商品
  150 + List<Long> c = CollectionUtils.filterList(convertSet1, item -> !convertSet.contains(item));
  151 + if (CollUtil.isNotEmpty(c)) {
  152 + List<CombinationProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> c.contains(item.getSkuId()));
  153 + List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(updateObj, vos);
  154 + combinationProductMapper.insertBatch(productDOs);
  155 + }
  156 + // 更新已存在的商品
  157 + List<Long> u = CollectionUtils.filterList(convertSet1, convertSet::contains);
  158 + if (CollUtil.isNotEmpty(u)) {
  159 + List<CombinationProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> u.contains(item.getSkuId()));
  160 + List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList1(updateObj, vos, combinationProductDOs);
  161 + combinationProductMapper.updateBatch(productDOs);
  162 + }
  163 + }
  164 +
  165 + @Override
  166 + public void deleteCombinationActivity(Long id) {
  167 + // 校验存在
  168 + CombinationActivityDO activityDO = validateCombinationActivityExists(id);
  169 + // 校验状态
  170 + if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
  171 + throw exception(COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
  172 + }
  173 +
  174 + // 删除
  175 + combinationActivityMapper.deleteById(id);
  176 + }
  177 +
  178 + private CombinationActivityDO validateCombinationActivityExists(Long id) {
  179 + CombinationActivityDO activityDO = combinationActivityMapper.selectById(id);
  180 + if (activityDO == null) {
  181 + throw exception(COMBINATION_ACTIVITY_NOT_EXISTS);
  182 + }
  183 + return activityDO;
  184 + }
  185 +
  186 + @Override
  187 + public CombinationActivityDO getCombinationActivity(Long id) {
  188 + return validateCombinationActivityExists(id);
  189 + }
  190 +
  191 + @Override
  192 + public List<CombinationActivityDO> getCombinationActivityList(Collection<Long> ids) {
  193 + return combinationActivityMapper.selectBatchIds(ids);
  194 + }
  195 +
  196 + @Override
  197 + public PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO) {
  198 + return combinationActivityMapper.selectPage(pageReqVO);
  199 + }
  200 +
  201 + @Override
  202 + public List<CombinationActivityDO> getCombinationActivityList(CombinationActivityExportReqVO exportReqVO) {
  203 + return combinationActivityMapper.selectList(exportReqVO);
  204 + }
  205 +
  206 + @Override
  207 + public List<CombinationProductDO> getProductsByActivityIds(Collection<Long> ids) {
  208 + return combinationProductMapper.selectListByActivityIds(ids);
  209 + }
  210 +
  211 + @Override
  212 + public void updateRecordStatusByUserIdAndOrderId(Long userId, Long orderId, Integer status) {
  213 + // 校验拼团是否存在
  214 + CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);
  215 +
  216 + // 更新状态
  217 + recordDO.setStatus(status);
  218 + recordMapper.updateById(recordDO);
  219 + }
  220 +
  221 + @Override
  222 + @Transactional(rollbackFor = Exception.class)
  223 + public void updateRecordStatusAndStartTimeByUserIdAndOrderId(Long userId, Long orderId, Integer status, LocalDateTime startTime) {
  224 + CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);
  225 + // 更新状态
  226 + recordDO.setStatus(status);
  227 + // 更新开始时间
  228 + recordDO.setStartTime(startTime);
  229 + recordMapper.updateById(recordDO);
  230 +
  231 + // 更新拼团参入人数
  232 + List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), status);
  233 + if (CollUtil.isNotEmpty(recordDOs)) {
  234 + recordDOs.forEach(item -> {
  235 + item.setUserCount(recordDOs.size());
  236 + // 校验拼团是否满足要求
  237 + if (recordDOs.size() >= recordDO.getUserSize()) {
  238 + item.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus());
  239 + }
  240 + });
  241 + }
  242 + recordMapper.updateBatch(recordDOs);
  243 + }
  244 +
  245 + private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) {
  246 + // 校验拼团是否存在
  247 + CombinationRecordDO recordDO = recordMapper.selectRecord(userId, orderId);
  248 + if (recordDO == null) {
  249 + throw exception(COMBINATION_RECORD_NOT_EXISTS);
  250 + }
  251 + return recordDO;
  252 + }
  253 +
  254 + @Override
  255 + public void createRecord(CombinationRecordReqDTO reqDTO) {
  256 + // 校验拼团活动
  257 + CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId());
  258 + // TODO @puhui999:需要校验下,它当前是不是已经参加了该拼团;
  259 + // TODO @puhui999: 父拼团是否存在,是否已经满了
  260 +
  261 + CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
  262 + record.setVirtualGroup(false);
  263 + // TODO @puhui999:过期时间,应该是 Date 哈;
  264 + record.setExpireTime(activity.getLimitDuration());
  265 + record.setUserSize(activity.getUserSize());
  266 + recordMapper.insert(record);
  267 + }
  268 +
  269 + @Override
  270 + public boolean validateRecordStatusIsSuccess(Long userId, Long orderId) {
  271 + CombinationRecordDO record = validateCombinationRecord(userId, orderId);
  272 + // TODO @puhui999:可以搞个 getRecrod 方法,然后业务通过 CombinationRecordStatusEnum.isSuccess 方法校验
  273 + return ObjectUtil.equal(record.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus());
  274 + }
  275 +
  276 + // TODO @puhui999:status 传入进来搞哈;
  277 + /**
  278 + * APP 端获取开团记录
  279 + *
  280 + * @return 开团记录
  281 + */
  282 + public List<CombinationRecordDO> getRecordList() {
  283 + return recordMapper.selectListByStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
  284 + }
  285 +
  286 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java
@@ -79,4 +79,12 @@ public interface SeckillActivityService { @@ -79,4 +79,12 @@ public interface SeckillActivityService {
79 */ 79 */
80 List<SeckillProductDO> getSeckillProductListByActivityId(Long id); 80 List<SeckillProductDO> getSeckillProductListByActivityId(Long id);
81 81
  82 + /**
  83 + * 通过活动编号获取活动商品
  84 + *
  85 + * @param ids 活动编号
  86 + * @return 活动商品列表
  87 + */
  88 + List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> ids);
  89 +
82 } 90 }