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