diff --git a/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml
index e2f19275e..b67e542cf 100644
--- a/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml
+++ b/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml
@@ -34,16 +34,12 @@
com.github.binarywang
-
wx-java-mp-spring-boot-starter
- 4.5.0
com.github.binarywang
wx-java-miniapp-spring-boot-starter
- 4.5.0
-
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml
index 14a7eaf30..fb89d2673 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml
@@ -64,9 +64,8 @@
com.github.yulichang
- mybatis-plus-join-boot-starter
+ mybatis-plus-join-boot-starter
-
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
index 614469e92..9c41683b0 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
@@ -6,10 +6,10 @@ import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.toolkit.Db;
-import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
@@ -17,10 +17,8 @@ import java.util.List;
/**
* 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力
- *
- * 为什么继承 MPJBaseMapper 接口?支持 MyBatis Plus 多表 Join 的能力。
*/
-public interface BaseMapperX extends MPJBaseMapper {
+public interface BaseMapperX extends BaseMapper {
default PageResult selectPage(PageParam pageParam, @Param("ew") Wrapper queryWrapper) {
// MyBatis Plus 查询
@@ -46,18 +44,6 @@ public interface BaseMapperX extends MPJBaseMapper {
return selectOne(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2));
}
- default T selectOne(SFunction field1, Object value1, SFunction field2, Object value2,
- SFunction field3, Object value3) {
- return selectOne(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2)
- .eq(field3, value3));
- }
-
- default T selectOne(SFunction field1, Object value1, SFunction field2, Object value2,
- SFunction field3, Object value3, SFunction field4, Object value4) {
- return selectOne(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2)
- .eq(field3, value3).eq(field4, value4));
- }
-
default Long selectCount() {
return selectCount(new QueryWrapper());
}
@@ -117,26 +103,15 @@ public interface BaseMapperX extends MPJBaseMapper {
update(update, new QueryWrapper<>());
}
- /**
- * 根据ID 批量更新,适合大量数据更新
- *
- * @param entities 实体们
- */
default void updateBatch(Collection entities) {
Db.updateBatchById(entities);
}
-
default void updateBatch(Collection entities, int size) {
Db.updateBatchById(entities, size);
}
- /**
- * 批量修改插入, 会根据实体的主键是否为空,更新还是修改。默认为 1000
- *
- * @param entities 实体们
- */
- default void saveOrUpdateBatch(Collection entities){
- Db.saveOrUpdateBatch(entities);
+ default void saveOrUpdateBatch(Collection collection) {
+ Db.saveOrUpdateBatch(collection);
}
}
diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
index 082d84756..78aa328ad 100644
--- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
+++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
@@ -60,7 +60,7 @@ public class YudaoWebSecurityConfigurerAdapter {
/**
* 自定义的权限映射 Bean 们
*
- * @see #configure(HttpSecurity)
+ * @see #filterChain(HttpSecurity)
*/
@Resource
private List authorizeRequestsCustomizers;
@@ -79,7 +79,7 @@ public class YudaoWebSecurityConfigurerAdapter {
/**
* 配置 URL 的安全配置
- *
+ *
* anyRequest | 匹配所有请求路径
* access | SpringEl表达式结果为true时可以访问
* anonymous | 匿名可以访问
@@ -141,7 +141,6 @@ public class YudaoWebSecurityConfigurerAdapter {
// 添加 Token Filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
-
return httpSecurity.build();
}
diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbAndRedisUnitTest.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbAndRedisUnitTest.java
index 059070d9d..f5de235f6 100644
--- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbAndRedisUnitTest.java
+++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbAndRedisUnitTest.java
@@ -40,6 +40,7 @@ public class BaseDbAndRedisUnitTest {
// Redis 配置类
RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer
+// RedisAutoConfiguration.class, // Spring Redis 自动配置类
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
RedissonAutoConfiguration.class, // Redisson 自动高配置类
})
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
index c9dc5a2d9..56f9aeaa6 100644
--- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
@@ -21,6 +21,7 @@ public class YudaoJacksonAutoConfiguration {
@Bean
public BeanPostProcessor objectMapperBeanPostProcessor() {
return new BeanPostProcessor() {
+
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof ObjectMapper)) {
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java
index 32acb33cc..2481d2b74 100644
--- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java
@@ -52,7 +52,8 @@ public class YudaoSwaggerAutoConfiguration {
// 接口信息
.info(buildInfo(properties))
// 接口安全配置
- .components(new Components().securitySchemes(securitySchemas));
+ .components(new Components().securitySchemes(securitySchemas))
+ .addSecurityItem(new SecurityRequirement().addList(HttpHeaders.AUTHORIZATION));
securitySchemas.keySet().forEach(key -> openAPI.addSecurityItem(new SecurityRequirement().addList(key)));
return openAPI;
}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
index 885b03143..74b2ceb34 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
@@ -47,7 +47,7 @@ public class BpmTaskController {
@Parameter(name = "processInstanceId", description = "流程实例的编号", required = true)
@PreAuthorize("@ss.hasPermission('bpm:task:query')")
public CommonResult> getTaskListByProcessInstanceId(
- @RequestParam("processInstanceId") String processInstanceId) {
+ @RequestParam("processInstanceId") String processInstanceId) {
return success(taskService.getTaskListByProcessInstanceId(processInstanceId));
}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
index 709a86a50..b85c4e533 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
@@ -17,12 +17,9 @@ import org.flowable.task.api.Task;
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
- *
- * @return
- */
- public static T copy(Object source, Class 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 List copyList(List source, Class target) {
- if (null == source || source.isEmpty()) {
- return Collections.emptyList();
- }
- return source.stream().map(e -> copy(e, target)).collect(Collectors.toList());
- }
-
default List convertList1(List tasks,
- Map processInstanceMap, Map userMap) {
+ Map processInstanceMap,
+ Map userMap) {
return CollectionUtils.convertList(tasks, task -> {
BpmTaskTodoPageItemRespVO respVO = convert1(task);
ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId());
@@ -104,11 +73,13 @@ public interface BpmTaskConvert {
BpmTaskDonePageItemRespVO convert2(HistoricTaskInstance bean);
- @Mappings({@Mapping(source = "processInstance.id", target = "id"),
- @Mapping(source = "processInstance.name", target = "name"),
- @Mapping(source = "processInstance.startUserId", target = "startUserId"),
- @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
- @Mapping(source = "startUser.nickname", target = "startUserNickname")})
+ @Mappings({
+ @Mapping(source = "processInstance.id", target = "id"),
+ @Mapping(source = "processInstance.name", target = "name"),
+ @Mapping(source = "processInstance.startUserId", target = "startUserId"),
+ @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
+ @Mapping(source = "startUser.nickname", target = "startUserNickname")
+ })
BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser);
default List convertList3(List tasks,
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java
deleted file mode 100644
index 02e67e8d3..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmActivityDO.java
+++ /dev/null
@@ -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;
-}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
index 508af962d..5d6c265c5 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
@@ -15,8 +15,8 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.PostApi;
@@ -89,7 +89,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
@Override
public List getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId,
- String taskDefinitionKey) {
+ String taskDefinitionKey) {
return taskRuleMapper.selectListByProcessDefinitionId(processDefinitionId, taskDefinitionKey);
}
@@ -128,14 +128,14 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
validTaskAssignRuleOptions(reqVO.getType(), reqVO.getOptions());
// 校验是否已经配置
BpmTaskAssignRuleDO existRule =
- taskRuleMapper.selectListByModelIdAndTaskDefinitionKey(reqVO.getModelId(), reqVO.getTaskDefinitionKey());
+ taskRuleMapper.selectListByModelIdAndTaskDefinitionKey(reqVO.getModelId(), reqVO.getTaskDefinitionKey());
if (existRule != null) {
throw exception(TASK_ASSIGN_RULE_EXISTS, reqVO.getModelId(), reqVO.getTaskDefinitionKey());
}
// 存储
BpmTaskAssignRuleDO rule = BpmTaskAssignRuleConvert.INSTANCE.convert(reqVO)
- .setProcessDefinitionId(BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL); // 只有流程模型,才允许新建
+ .setProcessDefinitionId(BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL); // 只有流程模型,才允许新建
taskRuleMapper.insert(rule);
return rule.getId();
}
@@ -169,14 +169,14 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
// 遍历,匹配对应的规则
Map processInstanceRuleMap =
- CollectionUtils.convertMap(processInstanceRules, BpmTaskAssignRuleRespVO::getTaskDefinitionKey);
+ CollectionUtils.convertMap(processInstanceRules, BpmTaskAssignRuleRespVO::getTaskDefinitionKey);
for (BpmTaskAssignRuleRespVO modelRule : modelRules) {
BpmTaskAssignRuleRespVO processInstanceRule = processInstanceRuleMap.get(modelRule.getTaskDefinitionKey());
if (processInstanceRule == null) {
return false;
}
if (!ObjectUtil.equals(modelRule.getType(), processInstanceRule.getType()) || !ObjectUtil.equal(
- modelRule.getOptions(), processInstanceRule.getOptions())) {
+ modelRule.getOptions(), processInstanceRule.getOptions())) {
return false;
}
}
@@ -192,7 +192,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
// 开始复制
List newRules = BpmTaskAssignRuleConvert.INSTANCE.convertList2(rules);
newRules.forEach(rule -> rule.setProcessDefinitionId(toProcessDefinitionId).setId(null).setCreateTime(null)
- .setUpdateTime(null));
+ .setUpdateTime(null));
taskRuleMapper.insertBatch(newRules);
}
@@ -215,7 +215,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) {
roleApi.validRoleList(options);
} else if (ObjectUtils.equalsAny(type, BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(),
- BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType())) {
+ BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType())) {
deptApi.validateDeptList(options);
} else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.POST.getType())) {
postApi.validPostList(options);
@@ -225,7 +225,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
userGroupService.validUserGroups(options);
} else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) {
dictDataApi.validateDictDataList(DictTypeConstants.TASK_ASSIGN_SCRIPT,
- CollectionUtils.convertSet(options, String::valueOf));
+ CollectionUtils.convertSet(options, String::valueOf));
} else {
throw new IllegalArgumentException(format("未知的规则类型({})", type));
}
@@ -298,7 +298,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
}
private Set calculateTaskCandidateUsersByPost(BpmTaskAssignRuleDO rule) {
- List users = adminUserApi.getUsersByPostIds(rule.getOptions());
+ List users = adminUserApi.getUserListByPostIds(rule.getOptions());
return convertSet(users, AdminUserRespDTO::getId);
}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
index dfe145aea..56115d79b 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
@@ -1 +1 @@
-package cn.iocoder.yudao.module.bpm.service.task;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
/**
* 流程实例 Service 实现类
*
* ProcessDefinition & ProcessInstance & Execution & Task 的关系:
* 1.
*
* HistoricProcessInstance & ProcessInstance 的关系:
* 1.
*
* 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
*
* @author 芋道源码
*/
@Service
@Validated
@Slf4j
public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
@Resource
private RuntimeService runtimeService;
@Resource
private BpmProcessInstanceExtMapper processInstanceExtMapper;
@Resource
@Lazy // 解决循环依赖
private BpmTaskService taskService;
@Resource
private BpmProcessDefinitionService processDefinitionService;
@Resource
private HistoryService historyService;
@Resource
private AdminUserApi adminUserApi;
@Resource
private DeptApi deptApi;
@Resource
private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher;
@Resource
private BpmMessageService messageService;
@Override
public ProcessInstance getProcessInstance(String id) {
return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult();
}
@Override
public List getProcessInstances(Set ids) {
return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
}
@Override
public PageResult getMyProcessInstancePage(Long userId,
BpmProcessInstanceMyPageReqVO pageReqVO) {
// 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页
PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return new PageResult<>(pageResult.getTotal());
}
// 获得流程 Task Map
List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId);
Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds);
// 转换返回
return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap);
}
@Override
@Transactional(rollbackFor = Exception.class)
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
// 发起流程
return createProcessInstance0(userId, definition, createReqVO.getVariables(), null);
}
@Override
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
// 发起流程
return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey());
}
@Override
public BpmProcessInstanceRespVO getProcessInstanceVO(String id) {
// 获得流程实例
HistoricProcessInstance processInstance = getHistoricProcessInstance(id);
if (processInstance == null) {
return null;
}
BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id);
Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id);
// 获得流程定义
ProcessDefinition processDefinition = processDefinitionService
.getProcessDefinition(processInstance.getProcessDefinitionId());
Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId());
BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt(
processInstance.getProcessDefinitionId());
Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id);
String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId());
// 获得 User
AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId()));
DeptRespDTO dept = null;
if (startUser != null) {
dept = deptApi.getDept(startUser.getDeptId());
}
// 拼接结果
return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt,
processDefinition, processDefinitionExt, bpmnXml, startUser, dept);
}
@Override
public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
// 校验流程实例存在
ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
if (instance == null) {
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
}
// 只能取消自己的
if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
}
// 通过删除流程实例,实现流程实例的取消,
// 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询
deleteProcessInstance(cancelReqVO.getId(),
BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason()));
}
/**
* 获得历史的流程实例
*
* @param id 流程实例的编号
* @return 历史的流程实例
*/
@Override
public HistoricProcessInstance getHistoricProcessInstance(String id) {
return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
}
@Override
public List getHistoricProcessInstances(Set ids) {
return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list();
}
@Override
public void createProcessInstanceExt(ProcessInstance instance) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId());
// 插入 BpmProcessInstanceExtDO 对象
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(instance.getId())
.setProcessDefinitionId(definition.getId())
.setName(instance.getProcessDefinitionName())
.setStartUserId(Long.valueOf(instance.getStartUserId()))
.setCategory(definition.getCategory())
.setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus())
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
processInstanceExtMapper.insert(instanceExtDO);
}
@Override
public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) {
// 判断是否为 Reject 不通过。如果是,则不进行更新.
// 因为,updateProcessInstanceExtReject 方法,已经进行更新了
if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) {
return;
}
// 需要主动查询,因为 instance 只有 id 属性
// 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId());
// 更新拓展表
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(event.getProcessInstanceId())
.setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.CANCEL.getResult());
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
@Override
public void updateProcessInstanceExtComplete(ProcessInstance instance) {
// 需要主动查询,因为 instance 只有 id 属性
// 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId());
// 更新拓展表
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(instance.getProcessInstanceId())
.setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程被通过的消息
messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateProcessInstanceExtReject(String id, String reason) {
// 需要主动查询,因为 instance 只有 id 属性
ProcessInstance processInstance = getProcessInstance(id);
// 删除流程实例,以实现驳回任务时,取消整个审批流程
deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason)));
// 更新 status + result
// 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法,
// 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id)
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.REJECT.getResult());
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程被不通过的消息
messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
private void deleteProcessInstance(String id, String reason) {
runtimeService.deleteProcessInstance(id, reason);
}
private String createProcessInstance0(Long userId, ProcessDefinition definition,
Map variables, String businessKey) {
// 校验流程定义
if (definition == null) {
throw exception(PROCESS_DEFINITION_NOT_EXISTS);
}
if (definition.isSuspended()) {
throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
}
// 创建流程实例
ProcessInstance instance = runtimeService.createProcessInstanceBuilder()
.processDefinitionId(definition.getId())
.businessKey(businessKey)
.name(definition.getName().trim())
.variables(variables)
.start();
// 设置流程名字
runtimeService.setProcessInstanceName(instance.getId(), definition.getName());
// 补全流程实例的拓展表
processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId())
.setFormVariables(variables));
return instance.getId();
}
}
\ No newline at end of file
+package cn.iocoder.yudao.module.bpm.service.task;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
/**
* 流程实例 Service 实现类
*
* ProcessDefinition & ProcessInstance & Execution & Task 的关系:
* 1.
*
* HistoricProcessInstance & ProcessInstance 的关系:
* 1.
*
* 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
*
* @author 芋道源码
*/
@Service
@Validated
@Slf4j
public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
@Resource
private RuntimeService runtimeService;
@Resource
private BpmProcessInstanceExtMapper processInstanceExtMapper;
@Resource
@Lazy // 解决循环依赖
private BpmTaskService taskService;
@Resource
private BpmProcessDefinitionService processDefinitionService;
@Resource
private HistoryService historyService;
@Resource
private AdminUserApi adminUserApi;
@Resource
private DeptApi deptApi;
@Resource
private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher;
@Resource
private BpmMessageService messageService;
@Override
public ProcessInstance getProcessInstance(String id) {
return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult();
}
@Override
public List getProcessInstances(Set ids) {
return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
}
@Override
public PageResult getMyProcessInstancePage(Long userId,
BpmProcessInstanceMyPageReqVO pageReqVO) {
// 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页
PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return new PageResult<>(pageResult.getTotal());
}
// 获得流程 Task Map
List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId);
Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds);
// 转换返回
return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap);
}
@Override
@Transactional(rollbackFor = Exception.class)
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
// 发起流程
return createProcessInstance0(userId, definition, createReqVO.getVariables(), null);
}
@Override
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
// 发起流程
return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey());
}
@Override
public BpmProcessInstanceRespVO getProcessInstanceVO(String id) {
// 获得流程实例
HistoricProcessInstance processInstance = getHistoricProcessInstance(id);
if (processInstance == null) {
return null;
}
BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id);
Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id);
// 获得流程定义
ProcessDefinition processDefinition = processDefinitionService
.getProcessDefinition(processInstance.getProcessDefinitionId());
Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId());
BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt(
processInstance.getProcessDefinitionId());
Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id);
String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId());
// 获得 User
AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId()));
DeptRespDTO dept = null;
if (startUser != null) {
dept = deptApi.getDept(startUser.getDeptId());
}
// 拼接结果
return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt,
processDefinition, processDefinitionExt, bpmnXml, startUser, dept);
}
@Override
public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
// 校验流程实例存在
ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
if (instance == null) {
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
}
// 只能取消自己的
if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
}
// 通过删除流程实例,实现流程实例的取消,
// 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询
deleteProcessInstance(cancelReqVO.getId(),
BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason()));
}
/**
* 获得历史的流程实例
*
* @param id 流程实例的编号
* @return 历史的流程实例
*/
@Override
public HistoricProcessInstance getHistoricProcessInstance(String id) {
return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
}
@Override
public List getHistoricProcessInstances(Set ids) {
return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list();
}
@Override
public void createProcessInstanceExt(ProcessInstance instance) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId());
// 插入 BpmProcessInstanceExtDO 对象
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(instance.getId())
.setProcessDefinitionId(definition.getId())
.setName(instance.getProcessDefinitionName())
.setStartUserId(Long.valueOf(instance.getStartUserId()))
.setCategory(definition.getCategory())
.setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus())
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
processInstanceExtMapper.insert(instanceExtDO);
}
@Override
public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) {
// 判断是否为 Reject 不通过。如果是,则不进行更新.
// 因为,updateProcessInstanceExtReject 方法,已经进行更新了
if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) {
return;
}
// 需要主动查询,因为 instance 只有 id 属性
// 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId());
// 更新拓展表
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(event.getProcessInstanceId())
.setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.CANCEL.getResult());
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
@Override
public void updateProcessInstanceExtComplete(ProcessInstance instance) {
// 需要主动查询,因为 instance 只有 id 属性
// 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId());
// 更新拓展表
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
.setProcessInstanceId(instance.getProcessInstanceId())
.setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程被通过的消息
messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateProcessInstanceExtReject(String id, String reason) {
// 需要主动查询,因为 instance 只有 id 属性
ProcessInstance processInstance = getProcessInstance(id);
// 删除流程实例,以实现驳回任务时,取消整个审批流程
deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason)));
// 更新 status + result
// 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法,
// 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的
BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id)
.setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
.setResult(BpmProcessInstanceResultEnum.REJECT.getResult());
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程被不通过的消息
messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
}
private void deleteProcessInstance(String id, String reason) {
runtimeService.deleteProcessInstance(id, reason);
}
private String createProcessInstance0(Long userId, ProcessDefinition definition,
Map variables, String businessKey) {
// 校验流程定义
if (definition == null) {
throw exception(PROCESS_DEFINITION_NOT_EXISTS);
}
if (definition.isSuspended()) {
throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
}
// 创建流程实例
ProcessInstance instance = runtimeService.createProcessInstanceBuilder()
.processDefinitionId(definition.getId())
.businessKey(businessKey)
.name(definition.getName().trim())
.variables(variables)
.start();
// 设置流程名字
runtimeService.setProcessInstanceName(instance.getId(), definition.getName());
// 补全流程实例的拓展表
processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId())
.setFormVariables(variables));
return instance.getId();
}
}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java
index 4e88b9c58..f46278083 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java
@@ -40,6 +40,8 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
// mock 方法(startUser)
AdminUserRespDTO startUser = randomPojo(AdminUserRespDTO.class, o -> o.setDeptId(10L));
when(adminUserApi.getUser(eq(1L))).thenReturn(startUser);
+ // mock 方法(getStartUserDept)没有部门
+ when(deptApi.getDept(eq(10L))).thenReturn(null);
// 调用
Set result = script.calculateTaskCandidateUsers(execution);
@@ -56,7 +58,9 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
when(adminUserApi.getUser(eq(1L))).thenReturn(startUser);
DeptRespDTO startUserDept = randomPojo(DeptRespDTO.class, o -> o.setId(10L).setParentId(100L)
.setLeaderUserId(20L));
+ // mock 方法(getDept)
when(deptApi.getDept(eq(10L))).thenReturn(startUserDept);
+ when(deptApi.getDept(eq(100L))).thenReturn(null);
// 调用
Set result = script.calculateTaskCandidateUsers(execution);
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImplTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImplTest.java
index a00bbbf86..7408b5425 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImplTest.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImplTest.java
@@ -120,7 +120,7 @@ public class BpmTaskAssignRuleServiceImplTest extends BaseDbUnitTest {
// mock 方法
List users = CollectionUtils.convertList(asSet(11L, 22L),
id -> new AdminUserRespDTO().setId(id));
- when(adminUserApi.getUsersByPostIds(eq(rule.getOptions()))).thenReturn(users);
+ when(adminUserApi.getUserListByPostIds(eq(rule.getOptions()))).thenReturn(users);
mockGetUserMap(asSet(11L, 22L));
// 调用
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java
index 36541f1ab..f67d2201a 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java
@@ -23,10 +23,10 @@ import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgn
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.USER_GROUP_NOT_EXISTS;
/**
-* {@link BpmUserGroupServiceImpl} 的单元测试类
-*
-* @author 芋道源码
-*/
+ * {@link BpmUserGroupServiceImpl} 的单元测试类
+ *
+ * @author 芋道源码
+ */
@Import(BpmUserGroupServiceImpl.class)
public class BpmUserGroupServiceTest extends BaseDbUnitTest {
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenPreviewRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenPreviewRespVO.java
index b349b1769..ffd924a0c 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenPreviewRespVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenPreviewRespVO.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
-@Schema(description = "管理后台 - 代码生成预览 Response VO,注意,每个文件都是一个该对象")
+@Schema(description = "管理后台 - 代码生成预览 Response VO,注意,每个文件都是一个该对象")
@Data
public class CodegenPreviewRespVO {
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java
index d0b2d046a..c46d9fa35 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java
@@ -70,7 +70,7 @@ public class CodegenColumnBaseVO {
@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;
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java
index 76c8d6844..ede10fccd 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java
@@ -12,7 +12,7 @@ import javax.validation.constraints.NotNull;
@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;
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java
index ece0a9eac..032a9d82f 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java
@@ -17,13 +17,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@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]")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java
index f0f4b4ff3..78d289a5b 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java
@@ -15,10 +15,10 @@ public class ConfigExportReqVO {
@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]")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java
index 8f87d6ee9..8caec39d1 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java
@@ -17,13 +17,13 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@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]")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java
index cf8b1e3ac..8c3d51e7e 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java
@@ -21,7 +21,7 @@ public class ConfigRespVO extends ConfigBaseVO {
@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 = "时间戳格式")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java
index f3132e970..496e32237 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java
@@ -14,7 +14,7 @@ import java.util.Map;
@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;
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java
index 9d254adb1..f2314a469 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigPageReqVO.java
@@ -23,8 +23,8 @@ public class FileConfigPageReqVO extends PageParam {
@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;
}
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java
index 178317126..c64556728 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java
@@ -18,7 +18,7 @@ public class FileConfigRespVO extends FileConfigBaseVO {
@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;
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
index fa8b84eef..21c117867 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
@@ -17,14 +17,14 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@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;
}
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java
index 670c30f5c..332833519 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java
@@ -12,13 +12,13 @@ import lombok.ToString;
@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;
}
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java
index 1119c7daf..5a74d38db 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java
@@ -43,7 +43,7 @@ public class JobLogBaseVO {
@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;
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java
index 6f5c7f69f..3156e2bc3 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java
@@ -8,14 +8,14 @@ import java.time.LocalDateTime;
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;
}
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java
index 84bf9ca34..1d3d49600 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java
@@ -20,7 +20,7 @@ public class JobLogPageReqVO extends PageParam {
@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;
}
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java
index 5830193ba..daa3e72b7 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java
@@ -24,7 +24,7 @@ public class ApiAccessLogBaseVO {
@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;
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java
index 8894b82f8..8010e3586 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
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")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java
index daf2c616e..c17c11122 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java
@@ -26,11 +26,11 @@ public class ApiAccessLogPageReqVO extends PageParam {
@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")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java
index dbc386729..792f2d7c0 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java
@@ -8,7 +8,7 @@ import java.time.LocalDateTime;
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 {
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java
index 8e10484e3..f219499ff 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java
@@ -7,7 +7,7 @@ import org.springframework.format.annotation.DateTimeFormat;
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 {
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java
index 17fb5cea3..9e8933520 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java
@@ -57,7 +57,7 @@ public class DatabaseTableServiceImpl implements DatabaseTableService {
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);
// 按照名字排序
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java
index 70f2ebc5d..f476b5a72 100755
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java
@@ -79,7 +79,7 @@ public class TestDemoServiceImpl implements TestDemoService {
@Override
public PageResult getTestDemoPage(TestDemoPageReqVO pageReqVO) {
- testDemoMapper.selectList2();
+// testDemoMapper.selectList2();
return testDemoMapper.selectPage(pageReqVO);
}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
index 21fcf7d96..2ed262cde 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
@@ -30,14 +30,13 @@ public interface ProductSkuApi {
*/
List getSkuList(Collection ids);
- // TODO puhui999:入参用 Collection 更通用
/**
* 批量查询 SKU 数组
*
* @param spuIds SPU 编号列表
* @return SKU 数组
*/
- List getSkuListBySpuId(List spuIds);
+ List getSkuListBySpuId(Collection spuIds);
/**
* 更新 SKU 库存
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
index d97a2613f..1f2670d76 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
@@ -45,10 +45,8 @@ public interface ErrorCodeConstants {
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, "该商品已经被收藏");
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
index 4a8425f61..bd0258efa 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
@@ -43,7 +43,7 @@ public class ProductSkuApiImpl implements ProductSkuApi {
}
@Override
- public List getSkuListBySpuId(List spuIds) {
+ public List getSkuListBySpuId(Collection spuIds) {
if (CollUtil.isEmpty(spuIds)) {
return Collections.emptyList();
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java
index c2e791a44..24d6a5456 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentBaseVO.java
@@ -26,23 +26,10 @@ public class ProductCommentBaseVO {
@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;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java
index f6e913fea..3791f572e 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java
@@ -35,9 +35,8 @@ public class ProductCommentPageReqVO extends PageParam {
@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)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java
index a75e9ec0c..9205e34cc 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentRespVO.java
@@ -5,6 +5,7 @@ import lombok.Data;
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;
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
index 0df57ca4f..e1c70f01c 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
@@ -21,6 +21,7 @@ import javax.annotation.Resource;
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> getSpuList(@RequestParam("spuIds") Collection spuIds) {
+ return success(ProductSpuConvert.INSTANCE.convertForSpuDetailRespListVO(
+ productSpuService.getSpuList(spuIds), productSkuService.getSkuListBySpuId(spuIds)));
+ }
+
@GetMapping("/page")
@Operation(summary = "获得商品 SPU 分页")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
index b2fef56e2..baf6adfab 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuCreateReqVO.java
@@ -9,11 +9,6 @@ import lombok.ToString;
import javax.validation.Valid;
import java.util.List;
-/**
- * 商品 SPU 创建 Request VO
- *
- * @author HUIHUI
- */
@Schema(description = "管理后台 - 商品 SPU 创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
index eff229c9d..1be96632d 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
@@ -8,12 +8,6 @@ import lombok.ToString;
import java.util.List;
-/**
- * 商品 SPU 详细 Response VO
- * 包括关联的 SKU 等信息
- *
- * @author HUIHUI
- */
@Schema(description = "管理后台 - 商品 SPU 详细 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuExportReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuExportReqVO.java
index f1da656d1..3b3dccd7e 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuExportReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuExportReqVO.java
@@ -10,12 +10,7 @@ import java.time.LocalDateTime;
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
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
index d428164dd..81cff4210 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
@@ -11,11 +11,6 @@ import java.time.LocalDateTime;
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)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
index 346614ad0..bd35d5b9a 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
@@ -7,11 +7,6 @@ import lombok.ToString;
import java.time.LocalDateTime;
-/**
- * 商品 SPU Response VO
- *
- * @author HUIHUI
- */
@Schema(description = "管理后台 - 商品 SPU Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java
index 1c943a912..7d9d0d05d 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java
@@ -4,11 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;
-/**
- * 商品 SPU 精简 Response VO
- * TODO 商品 SPU 精简 VO 暂时没有使用到,用到的时候再按需添加\修改属性
- * @author HUIHUI
- */
@Schema(description = "管理后台 - 商品 SPU 精简 Response VO")
@Data
@ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java
index c7c424fa0..bb69eb4cf 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java
@@ -12,11 +12,6 @@ import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
-/**
- * 商品 SPU 更新 Request VO
- *
- * @author HUIHUI
- */
@Schema(description = "管理后台 - 商品 SPU 更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java
index 57bda636c..e36e68466 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateStatusReqVO.java
@@ -7,11 +7,6 @@ import lombok.Data;
import javax.validation.constraints.NotNull;
-/**
- * 商品 SPU Status 更新 Request VO
- *
- * @author HUIHUI
- */
@Schema(description = "管理后台 - 商品 SPU Status 更新 Request VO")
@Data
public class ProductSpuUpdateStatusReqVO{
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java
index 1bcd4a138..86df8f4bd 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppProductCommentController.java
@@ -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> getCommentList(@RequestParam("spuId") Long spuId,
- @RequestParam(value = "count", defaultValue = "10") Integer count) {
+ public CommonResult> getCommentList(
+ @RequestParam("spuId") Long spuId,
+ @RequestParam(value = "count", defaultValue = "10") Integer count) {
return success(productCommentService.getCommentList(spuId, count));
}
@GetMapping("/page")
@Operation(summary = "获得商品评价分页")
public CommonResult> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
- PageResult page = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
- // TODO @puhui CollUtils 有简化 convertmap 和 list 的方法
- Set skuIds = page.getList().stream().map(AppProductCommentRespVO::getSkuId).collect(Collectors.toSet());
+ // TODO @puhui999:写到 convert 里,可以更简洁哈。
+ PageResult commentDOPage = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
+ Set skuIds = CollectionUtils.convertSet(commentDOPage.getList(), ProductCommentDO::getSkuId);
List skuList = productSkuService.getSkuList(skuIds);
- Map skuDOMap = new HashMap<>(skuIds.size());
+ Map 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 skuProperties = ProductCommentConvert.INSTANCE.convertList01(productSkuDO.getProperties());
- item.setSkuProperties(skuProperties);
- }
- });
+ PageResult page = ProductCommentConvert.INSTANCE.convertPage02(commentDOPage, skuDOMap);
return success(page);
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java
index d13a2b0ac..2ea3af496 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java
@@ -10,11 +10,6 @@ import javax.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.List;
-/**
- * 用户 App - 商品评价详情 Response VO
- *
- * @author HUIHUI
- */
@Schema(description = "用户 App - 商品评价详情 Response VO")
@Data
@ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java
index 170a3f0f4..4e195209c 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java
@@ -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 convertList(List list);
- List convertList01(List properties);
-
PageResult convertPage(PageResult page);
- PageResult convertPage02(PageResult pageResult);
+ PageResult convertPage01(PageResult pageResult);
+
+ default PageResult convertPage02(PageResult pageResult,
+ Map skuMap) {
+ PageResult 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 convertList01(List 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 convertList02(List list);
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
index aaad240a4..5149b699c 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
@@ -18,8 +18,10 @@ import org.mapstruct.factory.Mappers;
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 convertForSpuDetailRespListVO(List spus, List skus) {
+ List vos = new ArrayList<>(spus.size());
+ Map> 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;
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
index 1426073a5..d6df94207 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
@@ -26,6 +26,7 @@ public interface ProductCommentMapper extends BaseMapperX {
}
static void appendTabQuery(LambdaQueryWrapperX 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 {
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()
.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) {
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java
index 7f615677c..2c2b35197 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java
@@ -54,7 +54,7 @@ public interface ProductCommentService {
* @param visible 是否可见
* @return 商品评价分页
*/
- PageResult getCommentPage(AppCommentPageReqVO pageVO, Boolean visible);
+ PageResult getCommentPage(AppCommentPageReqVO pageVO, Boolean visible);
/**
* 创建商品评论
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
index b0822e96c..97a3d1562 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
@@ -81,7 +81,7 @@ public class ProductCommentServiceImpl implements ProductCommentService {
@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 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 getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {
- // TODO @puhui 可以放到 controller 去 convert 哈
- return ProductCommentConvert.INSTANCE.convertPage02(
- productCommentMapper.selectPage(pageVO, visible));
+ public PageResult getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {
+ return productCommentMapper.selectPage(pageVO, visible);
}
@Override
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
index 4c106d1bc..fbc9830bf 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
@@ -90,7 +90,7 @@ public interface ProductSkuService {
* @param spuIds spu 编码集合
* @return 商品 sku 集合
*/
- List getSkuListBySpuId(List spuIds);
+ List getSkuListBySpuId(Collection spuIds);
/**
* 通过 spuId 删除 sku 信息
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
index 3f77fbe8d..7c6c5030e 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -148,7 +148,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
}
@Override
- public List getSkuListBySpuId(List spuIds) {
+ public List getSkuListBySpuId(Collection spuIds) {
return productSkuMapper.selectListBySpuId(spuIds);
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
index 8d3a3d5b8..2f55af837 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
@@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen
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 commentPage = productCommentService.getCommentPage(productCommentPageReqVO);
PageResult result = ProductCommentConvert.INSTANCE.convertPage(productCommentMapper.selectPage(productCommentPageReqVO));
@@ -138,15 +137,15 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
assertEquals(8, all.getTotal());
// 测试获取所有商品分页评论数据
- PageResult result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE);
+ PageResult result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE);
assertEquals(7, result1.getTotal());
// 测试获取所有商品分页中评数据
- PageResult result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
+ PageResult result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
assertEquals(2, result2.getTotal());
// 测试获取指定 spuId 商品分页中评数据
- PageResult result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
+ PageResult result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
assertEquals(2, result3.getTotal());
// 测试分页 tab count
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java
new file mode 100644
index 000000000..ae1cf7f18
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java
@@ -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);
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordReqDTO.java
new file mode 100644
index 000000000..122a9a89a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordReqDTO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
index 945709697..a504d810c 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* Promotion 错误码枚举类
- *
+ *
* 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, "拼团不存在");
}
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/combination/CombinationRecordStatusEnum.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/combination/CombinationRecordStatusEnum.java
new file mode 100644
index 000000000..ee9fc4144
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/combination/CombinationRecordStatusEnum.java
@@ -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;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java
new file mode 100644
index 000000000..ea3cdc35a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java
@@ -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());
+ }
+
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java
new file mode 100644
index 000000000..53fa9dedf
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java
@@ -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 createCombinationActivity(@Valid @RequestBody CombinationActivityCreateReqVO createReqVO) {
+ return success(combinationActivityService.createCombinationActivity(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新拼团活动")
+ @PreAuthorize("@ss.hasPermission('promotion:combination-activity:update')")
+ public CommonResult 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 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 getCombinationActivity(@RequestParam("id") Long id) {
+ CombinationActivityDO activity = combinationActivityService.getCombinationActivity(id);
+ List 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> getCombinationActivityList(@RequestParam("ids") Collection ids) {
+ List list = combinationActivityService.getCombinationActivityList(ids);
+ return success(CombinationActivityConvert.INSTANCE.convertList(list));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得拼团活动分页")
+ @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')")
+ public CommonResult> getCombinationActivityPage(
+ @Valid CombinationActivityPageReqVO pageVO) {
+ PageResult pageResult = combinationActivityService.getCombinationActivityPage(pageVO);
+ // TODO @puhui999:可以不一定 aIds,直接批量查询结果出来;下面也是类似;
+ Set aIds = CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getId);
+ List products = combinationActivityService.getProductsByActivityIds(aIds);
+ Set spuIds = CollectionUtils.convertSet(pageResult.getList(), CombinationActivityDO::getSpuId);
+ List 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 list = combinationActivityService.getCombinationActivityList(exportReqVO);
+ // 导出 Excel
+ List datas = CombinationActivityConvert.INSTANCE.convertList02(list);
+ ExcelUtils.write(response, "拼团活动.xls", "数据", CombinationActivityExcelVO.class, datas);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java
new file mode 100644
index 000000000..4ca519fed
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java
new file mode 100644
index 000000000..ea7879e4e
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java
@@ -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 products;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExcelVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExcelVO.java
new file mode 100644
index 000000000..c4a91c515
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExcelVO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExportReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExportReqVO.java
new file mode 100644
index 000000000..a5cbbd9db
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityExportReqVO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityPageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityPageReqVO.java
new file mode 100644
index 000000000..bcd06fdc8
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityPageReqVO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java
new file mode 100644
index 000000000..eea1f624d
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java
@@ -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 products;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java
new file mode 100644
index 000000000..c4f8cf0c3
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java
@@ -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 products;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java
new file mode 100644
index 000000000..fac9cddd0
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java
new file mode 100644
index 000000000..ee805bccc
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java
@@ -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 {
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExcelVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExcelVO.java
new file mode 100644
index 000000000..dae0bce7e
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExcelVO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExportReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExportReqVO.java
new file mode 100644
index 000000000..65a1d08e8
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductExportReqVO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductPageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductPageReqVO.java
new file mode 100644
index 000000000..02bcc070c
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductPageReqVO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductRespVO.java
new file mode 100644
index 000000000..eeac5c3b5
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductRespVO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java
new file mode 100644
index 000000000..5fab798da
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java
@@ -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 {
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
index ba750b296..0631bfc11 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
@@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
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 getSeckillActivity(@RequestParam("id") Long id) {
SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id);
- if (seckillActivity == null) {
- return success(null);
- }
- List seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id);
- return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity,seckillProducts));
+ List 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> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) {
PageResult pageResult = seckillActivityService.getSeckillActivityPage(pageVO);
- return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult));
+ Set aIds = CollectionUtils.convertSet(pageResult.getList(), SeckillActivityDO::getId);
+ List seckillProducts = seckillActivityService.getSeckillProductListByActivityId(aIds);
+ Set spuIds = CollectionUtils.convertSet(pageResult.getList(), SeckillActivityDO::getSpuId);
+ List spuList = spuApi.getSpuList(spuIds);
+ return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, seckillProducts, spuList));
}
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
index 628c6d1c2..671b1f61b 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
@@ -19,11 +19,6 @@ import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-/**
- * 管理后台 - 秒杀时段相关接口
- *
- * @author HUIHUI
- */
@Tag(name = "管理后台 - 秒杀时段")
@RestController
@RequestMapping("/promotion/seckill-config")
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java
index ac1126d8c..504d4a057 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java
@@ -20,10 +20,9 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Data
public class SeckillActivityBaseVO {
- // TODO @puhui999:对应单 spuId 哈
@Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]")
@NotNull(message = "秒杀活动商品不能为空")
- private List 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;
-
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java
index 64f5c301a..ad78a9464 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java
@@ -6,26 +6,46 @@ import lombok.Data;
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 products; // TODO puhui: 考虑是否去除
+ private List 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;
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java
index 27b69b2b1..78a1c51df 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigBaseVO.java
@@ -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 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));
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java
index e49a02837..92211385a 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigPageReqVO.java
@@ -6,12 +6,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
-// TODO @puhui:VO 上不写注释,已经有注解啦。
-/**
- * 管理后台 - 秒杀时段分页 Request VO
- *
- * @author HUIHUI
- */
@Schema(description = "管理后台 - 秒杀时段分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java
index 4dba74fe1..a11d78930 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java
@@ -14,11 +14,6 @@ import javax.validation.constraints.NotNull;
@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;
-
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java
index 9b06f98f6..8ee4884ea 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java
@@ -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)
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java
index bb33fab58..96b7eec4c 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductRespVO.java
@@ -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)
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java
index 3f964255a..5fdccf8d0 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java
@@ -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;
-
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
new file mode 100644
index 000000000..61644c9c9
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
@@ -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 productDOs) {
+ CombinationActivityRespVO respVO = convert(bean);
+ respVO.setProducts(convertList2(productDOs));
+ return respVO;
+ }
+
+ List convertList(List list);
+
+ PageResult convertPage(PageResult page);
+
+ default PageResult convertPage(PageResult page,
+ List productList,
+ List spuList) {
+ // TODO @puhui999:c -> c 可以去掉哈
+ Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId, c -> c);
+ PageResult 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 convertList2(List productDOs);
+
+ List convertList02(List 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 convertList(CombinationActivityDO activityDO, List extends CombinationProductBaseVO> products) {
+ List 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 convertList1(CombinationActivityDO activityDO,
+ List vos,
+ List productDOs) {
+ Map longMap = convertMap(productDOs, CombinationProductDO::getSkuId, CombinationProductDO::getId);
+ List 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);
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
index 7d62b4f2d..e8667870e 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
@@ -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 convertPage(PageResult page);
- SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List 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 convertPage(PageResult page, List seckillProducts, List spuList) {
+ Map spuMap = CollectionUtils.convertMap(spuList, ProductSpuRespDTO::getId, c -> c);
+ PageResult 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 seckillProducts) {
+ SeckillActivityDetailRespVO respVO = convert1(seckillActivity);
+ respVO.setProducts(convertList2(seckillProducts));
+ return respVO;
}
- default List convertList(SeckillActivityDO seckillActivity, List 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 convertList(SeckillActivityDO activityDO, List extends SeckillProductBaseVO> products) {
List 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 convertList1(SeckillActivityDO activityDO, List vos, List productDOs) {
+ Map longMap = CollectionUtils.convertMap(productDOs, SeckillProductDO::getSkuId, SeckillProductDO::getId);
+ List 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 convertList2(List productDOs);
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationActivityDO.java
new file mode 100644
index 000000000..c5c08bbd9
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationActivityDO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationProductDO.java
new file mode 100644
index 000000000..5c4744ee9
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationProductDO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationRecordDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationRecordDO.java
new file mode 100644
index 000000000..3ab41b9ba
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/combinationactivity/CombinationRecordDO.java
@@ -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;
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java
index be6663592..a8c7eb265 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java
@@ -34,8 +34,7 @@ public class SeckillActivityDO extends BaseDO {
/**
* 秒杀活动商品
*/
- @TableField(typeHandler = LongListTypeHandler.class)
- private List spuIds;
+ private Long spuId;
/**
* 秒杀活动名称
*/
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java
index cdf206bd9..d3994dfd5 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java
@@ -47,11 +47,11 @@ public class SeckillProductDO extends BaseDO {
@TableField(typeHandler = LongListTypeHandler.class)
private List configIds;
/**
- * 商品 spu_id
+ * 商品 SPU 编号
*/
private Long spuId;
/**
- * 商品 sku_id
+ * 商品 SKU 编号
*/
private Long skuId;
/**
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java
index f8fe41a18..fdaf193a4 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillconfig/SeckillConfigDO.java
@@ -3,22 +3,27 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig;
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 sliderPicUrls;
/**
- * 秒杀主图
+ * 秒杀轮播图
*/
- private String picUrl;
+ @TableField(typeHandler = JacksonTypeHandler.class)
+ private List sliderPicUrls;
/**
* 状态
*
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationActivityMapper.java
new file mode 100644
index 000000000..12c3cf28a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationActivityMapper.java
@@ -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 {
+
+ default PageResult selectPage(CombinationActivityPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .likeIfPresent(CombinationActivityDO::getName, reqVO.getName())
+ .orderByDesc(CombinationActivityDO::getId));
+ }
+
+ default List selectList(CombinationActivityExportReqVO reqVO) {
+ return selectList(new LambdaQueryWrapperX()
+ .likeIfPresent(CombinationActivityDO::getName, reqVO.getName())
+ .eqIfPresent(CombinationActivityDO::getStatus, reqVO.getStatus())
+ .orderByDesc(CombinationActivityDO::getId));
+ }
+
+ default List selectListByStatus(Integer status) {
+ return selectList(CombinationActivityDO::getStatus, status);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationProductMapper.java
new file mode 100644
index 000000000..ced6de6d4
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationProductMapper.java
@@ -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 {
+
+ default PageResult selectPage(CombinationProductPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .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 selectList(CombinationProductExportReqVO reqVO) {
+ return selectList(new LambdaQueryWrapperX()
+ .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 selectListByActivityIds(Collection ids) {
+ return selectList(CombinationProductDO::getActivityId, ids);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationRecordMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationRecordMapper.java
new file mode 100644
index 000000000..440767472
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/combinationactivity/CombinationRecordMapper.java
@@ -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 {
+
+ default CombinationRecordDO selectRecord(Long userId, Long orderId) {
+ return selectOne(CombinationRecordDO::getUserId, userId,
+ CombinationRecordDO::getOrderId, orderId);
+ }
+
+ default List selectListByHeadIdAndStatus(Long headId, Integer status) {
+ return selectList(new LambdaQueryWrapperX()
+ .eq(CombinationRecordDO::getHeadId, headId)
+ .eq(CombinationRecordDO::getStatus, status));
+ }
+
+ default List selectListByStatus(Integer status) {
+ return selectList(CombinationRecordDO::getStatus, status);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
index fd6d87bdf..625769901 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
@@ -21,6 +21,10 @@ public interface SeckillProductMapper extends BaseMapperX {
return selectList(SeckillProductDO::getActivityId, id);
}
+ default List selectListByActivityId(Collection