diff --git a/pom.xml b/pom.xml index 4634d345e..86dfebcc3 100644 --- a/pom.xml +++ b/pom.xml @@ -15,12 +15,12 @@ yudao-module-system yudao-module-infra - yudao-module-member + - yudao-module-pay - yudao-module-mall + + diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java index 91f534788..b0279a43d 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java @@ -290,7 +290,7 @@ public class CollectionUtils { return valueFunc.apply(t); } - public static > V getSumValue(List from, Function valueFunc, + public static > V getSumValue(Collection from, Function valueFunc, BinaryOperator accumulator) { return getSumValue(from, valueFunc, accumulator, null); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJobAspect.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJobAspect.java index ce9eb1631..de409a4a3 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJobAspect.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJobAspect.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.tenant.core.job; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; @@ -44,7 +45,8 @@ public class TenantJobAspect { // TODO 芋艿:先通过 parallel 实现并行;1)多个租户,是一条执行日志;2)异常的情况 TenantUtils.execute(tenantId, () -> { try { - joinPoint.proceed(); + Object result = joinPoint.proceed(); + results.put(tenantId, StrUtil.toStringOrNull(result)); } catch (Throwable e) { log.error("[execute][租户({}) 执行 Job 发生异常", tenantId, e); results.put(tenantId, ExceptionUtil.getRootCauseMessage(e)); diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java index e2ed4c314..68cdf65ad 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java @@ -11,7 +11,6 @@ import com.mzt.logapi.service.ILogRecordService; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; import java.util.List; @@ -29,7 +28,6 @@ public class LogRecordServiceImpl implements ILogRecordService { private OperateLogApi operateLogApi; @Override - @Async public void record(LogRecord logRecord) { OperateLogCreateReqDTO reqDTO = new OperateLogCreateReqDTO(); try { @@ -42,7 +40,7 @@ public class LogRecordServiceImpl implements ILogRecordService { fillRequestFields(reqDTO); // 2. 异步记录日志 - operateLogApi.createOperateLog(reqDTO); + operateLogApi.createOperateLogAsync(reqDTO); } catch (Throwable ex) { // 由于 @Async 异步调用,这里打印下日志,更容易跟进 log.error("[record][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex); diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java index d1f7453b6..cf76036c8 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java @@ -2,15 +2,10 @@ package cn.iocoder.yudao.framework.apilog.config; import cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter; import cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor; -import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; -import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkServiceImpl; -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkServiceImpl; import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration; import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; -import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; import jakarta.servlet.Filter; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -23,18 +18,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @AutoConfiguration(after = YudaoWebAutoConfiguration.class) public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer { - @Bean - @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") - public ApiAccessLogFrameworkService apiAccessLogFrameworkService(ApiAccessLogApi apiAccessLogApi) { - return new ApiAccessLogFrameworkServiceImpl(apiAccessLogApi); - } - - @Bean - @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") - public ApiErrorLogFrameworkService apiErrorLogFrameworkService(ApiErrorLogApi apiErrorLogApi) { - return new ApiErrorLogFrameworkServiceImpl(apiErrorLogApi); - } - /** * 创建 ApiAccessLogFilter Bean,记录 API 请求日志 */ @@ -42,8 +25,8 @@ public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer { @ConditionalOnProperty(prefix = "yudao.access-log", value = "enable", matchIfMissing = true) // 允许使用 yudao.access-log.enable=false 禁用访问日志 public FilterRegistrationBean apiAccessLogFilter(WebProperties webProperties, @Value("${spring.application.name}") String applicationName, - ApiAccessLogFrameworkService apiAccessLogFrameworkService) { - ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogFrameworkService); + ApiAccessLogApi apiAccessLogApi) { + ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogApi); return createFilterBean(filter, WebFilterOrderEnum.API_ACCESS_LOG_FILTER); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java index 479a5fb9f..d798b7044 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java @@ -9,7 +9,6 @@ import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum; -import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -18,6 +17,7 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.Operation; @@ -36,7 +36,7 @@ import java.time.temporal.ChronoUnit; import java.util.Iterator; import java.util.Map; -import static cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor.*; +import static cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor.ATTRIBUTE_HANDLER_METHOD; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; /** @@ -53,12 +53,12 @@ public class ApiAccessLogFilter extends ApiRequestFilter { private final String applicationName; - private final ApiAccessLogFrameworkService apiAccessLogFrameworkService; + private final ApiAccessLogApi apiAccessLogApi; - public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogFrameworkService apiAccessLogFrameworkService) { + public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogApi apiAccessLogApi) { super(webProperties); this.applicationName = applicationName; - this.apiAccessLogFrameworkService = apiAccessLogFrameworkService; + this.apiAccessLogApi = apiAccessLogApi; } @Override @@ -91,7 +91,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter { if (!enable) { return; } - apiAccessLogFrameworkService.createApiAccessLog(accessLog); + apiAccessLogApi.createApiAccessLogAsync(accessLog); } catch (Throwable th) { log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), toJsonString(accessLog), th); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java deleted file mode 100644 index 2f3c78f60..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.framework.apilog.core.service; - -import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; - -/** - * API 访问日志 Framework Service 接口 - * - * @author 芋道源码 - */ -public interface ApiAccessLogFrameworkService { - - /** - * 创建 API 访问日志 - * - * @param reqDTO API 访问日志 - */ - void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO); - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java deleted file mode 100644 index 934f8141c..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.framework.apilog.core.service; - -import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; -import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; - -/** - * API 访问日志 Framework Service 实现类 - * - * 基于 {@link ApiAccessLogApi} 服务,记录访问日志 - * - * @author 芋道源码 - */ -@RequiredArgsConstructor -@Slf4j -public class ApiAccessLogFrameworkServiceImpl implements ApiAccessLogFrameworkService { - - private final ApiAccessLogApi apiAccessLogApi; - - @Override - @Async - public void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO) { - try { - apiAccessLogApi.createApiAccessLog(reqDTO); - } catch (Throwable ex) { - // 由于 @Async 异步调用,这里打印下日志,更容易跟进 - log.error("[createApiAccessLog][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex); - } - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java deleted file mode 100644 index 33bebb711..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.framework.apilog.core.service; - -import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; - -/** - * API 错误日志 Framework Service 接口 - * - * @author 芋道源码 - */ -public interface ApiErrorLogFrameworkService { - - /** - * 创建 API 错误日志 - * - * @param reqDTO API 错误日志 - */ - void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO); - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java deleted file mode 100644 index e4e19fb32..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.framework.apilog.core.service; - -import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; -import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; - -/** - * API 错误日志 Framework Service 实现类 - * - * 基于 {@link ApiErrorLogApi} 服务,记录错误日志 - * - * @author 芋道源码 - */ -@RequiredArgsConstructor -@Slf4j -public class ApiErrorLogFrameworkServiceImpl implements ApiErrorLogFrameworkService { - - private final ApiErrorLogApi apiErrorLogApi; - - @Override - @Async - public void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO) { - try { - apiErrorLogApi.createApiErrorLog(reqDTO); - } catch (Throwable ex) { - // 由于 @Async 异步调用,这里打印下日志,更容易跟进 - log.error("[createApiErrorLog][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex); - } - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java index 1bdda5723..e3684dfac 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java @@ -1,12 +1,14 @@ package cn.iocoder.yudao.framework.web.config; -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter; import cn.iocoder.yudao.framework.web.core.filter.DemoFilter; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; +import jakarta.annotation.Resource; +import jakarta.servlet.Filter; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -25,9 +27,6 @@ import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import jakarta.annotation.Resource; -import jakarta.servlet.Filter; - @AutoConfiguration @EnableConfigurationProperties(WebProperties.class) public class YudaoWebAutoConfiguration implements WebMvcConfigurer { @@ -59,8 +58,9 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { } @Bean - public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogFrameworkService apiErrorLogFrameworkService) { - return new GlobalExceptionHandler(applicationName, apiErrorLogFrameworkService); + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogApi apiErrorLogApi) { + return new GlobalExceptionHandler(applicationName, apiErrorLogApi); } @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index 41646d7ef..6628f116c 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -5,7 +5,6 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.JakartaServletUtil; -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -14,6 +13,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import jakarta.servlet.http.HttpServletRequest; @@ -40,12 +40,7 @@ import java.time.LocalDateTime; import java.util.Map; import java.util.Set; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.FORBIDDEN; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.METHOD_NOT_ALLOWED; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_FOUND; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED; +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*; /** * 全局异常处理器,将 Exception 翻译成 CommonResult + 对应的异常编号 @@ -65,7 +60,7 @@ public class GlobalExceptionHandler { @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") private final String applicationName; - private final ApiErrorLogFrameworkService apiErrorLogFrameworkService; + private final ApiErrorLogApi apiErrorLogApi; /** * 处理所有异常,主要是提供给 Filter 使用 @@ -288,7 +283,7 @@ public class GlobalExceptionHandler { // 初始化 errorLog buildExceptionLog(errorLog, req, e); // 执行插入 errorLog - apiErrorLogFrameworkService.createApiErrorLog(errorLog); + apiErrorLogApi.createApiErrorLogAsync(errorLog); } catch (Throwable th) { log.error("[createExceptionLog][url({}) log({}) 发生异常]", req.getRequestURI(), JsonUtils.toJsonString(errorLog), th); } diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java index 0f08b7cf5..cabceb807 100644 --- a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate; import cn.iocoder.yudao.framework.websocket.core.handler.JsonWebSocketMessageHandler; import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener; import cn.iocoder.yudao.framework.websocket.core.security.LoginUserHandshakeInterceptor; +import cn.iocoder.yudao.framework.websocket.core.security.WebSocketAuthorizeRequestsCustomizer; import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageConsumer; import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageSender; import cn.iocoder.yudao.framework.websocket.core.sender.local.LocalWebSocketMessageSender; @@ -76,6 +77,11 @@ public class YudaoWebSocketAutoConfiguration { return new WebSocketSessionManagerImpl(); } + @Bean + public WebSocketAuthorizeRequestsCustomizer webSocketAuthorizeRequestsCustomizer(WebSocketProperties webSocketProperties) { + return new WebSocketAuthorizeRequestsCustomizer(webSocketProperties); + } + // ==================== Sender 相关 ==================== @Configuration diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java index 3fe5cc068..ec053b8d0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModel import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; import org.flowable.common.engine.impl.db.SuspensionState; import org.flowable.engine.repository.Deployment; @@ -55,7 +56,7 @@ public interface BpmModelConvert { BpmModelMetaInfoRespDTO metaInfo = buildMetaInfo(model); BpmModelRespVO modelVO = buildModel0(model, metaInfo, null, null, null, null); if (ArrayUtil.isNotEmpty(bpmnBytes)) { - modelVO.setBpmnXml(new String(bpmnBytes)); + modelVO.setBpmnXml(BpmnModelUtils.getBpmnXml(bpmnBytes)); } return modelVO; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java index bcf82d731..c046011b0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; import org.flowable.bpmn.converter.BpmnXMLConverter; @@ -108,7 +109,14 @@ public class BpmnModelUtils { return null; } BpmnXMLConverter converter = new BpmnXMLConverter(); - return new String(converter.convertToXML(model)); + return StrUtil.utf8Str(converter.convertToXML(model)); + } + + public static String getBpmnXml(byte[] bpmnBytes) { + if (ArrayUtil.isEmpty(bpmnBytes)) { + return null; + } + return StrUtil.utf8Str(bpmnBytes); } // ========== 遍历相关的方法 ========== diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java index 0c821c8c2..99bc09f0b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java @@ -92,7 +92,7 @@ public interface CrmReceivableMapper extends BaseMapperX { List> result = selectMaps(new QueryWrapper() .select("contract_id, SUM(price) AS total_price") .in("audit_status", CrmAuditStatusEnum.DRAFT.getStatus(), // 草稿 + 审批中 + 审批通过 - CrmAuditStatusEnum.PROCESS, CrmAuditStatusEnum.APPROVE.getStatus()) + CrmAuditStatusEnum.PROCESS.getStatus(), CrmAuditStatusEnum.APPROVE.getStatus()) .groupBy("contract_id") .in("contract_id", contractIds)); // 获得金额 diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiAccessLogApi.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiAccessLogApi.java index 0a28d2563..84f598959 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiAccessLogApi.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiAccessLogApi.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.api.logger; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; import jakarta.validation.Valid; +import org.springframework.scheduling.annotation.Async; /** * API 访问日志的 API 接口 @@ -18,4 +19,14 @@ public interface ApiAccessLogApi { */ void createApiAccessLog(@Valid ApiAccessLogCreateReqDTO createDTO); + /** + * 【异步】创建 API 访问日志 + * + * @param createDTO 访问日志 DTO + */ + @Async + default void createApiAccessLogAsync(ApiAccessLogCreateReqDTO createDTO) { + createApiAccessLog(createDTO); + } + } diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiErrorLogApi.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiErrorLogApi.java index 3544a8977..23ce3bd0d 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiErrorLogApi.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiErrorLogApi.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.api.logger; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; import jakarta.validation.Valid; +import org.springframework.scheduling.annotation.Async; /** * API 错误日志的 API 接口 @@ -18,4 +19,14 @@ public interface ApiErrorLogApi { */ void createApiErrorLog(@Valid ApiErrorLogCreateReqDTO createDTO); + /** + * 【异步】创建 API 异常日志 + * + * @param createDTO 异常日志 DTO + */ + @Async + default void createApiErrorLogAsync(ApiErrorLogCreateReqDTO createDTO) { + createApiErrorLog(createDTO); + } + } diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java index e9f39a81f..4cce820b7 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java @@ -22,7 +22,7 @@ public interface ErrorCodeConstants { ErrorCode JOB_CHANGE_STATUS_EQUALS = new ErrorCode(1_001_001_003, "定时任务已经处于该状态,无需修改"); ErrorCode JOB_UPDATE_ONLY_NORMAL_STATUS = new ErrorCode(1_001_001_004, "只有开启状态的任务,才可以修改"); ErrorCode JOB_CRON_EXPRESSION_VALID = new ErrorCode(1_001_001_005, "CRON 表达式不正确"); - ErrorCode JOB_HANDLER_BEAN_NOT_EXISTS = new ErrorCode(1_001_001_006, "定时任务的处理器 Bean 不存在"); + ErrorCode JOB_HANDLER_BEAN_NOT_EXISTS = new ErrorCode(1_001_001_006, "定时任务的处理器 Bean 不存在,注意 Bean 默认首字母小写"); ErrorCode JOB_HANDLER_BEAN_TYPE_ERROR = new ErrorCode(1_001_001_007, "定时任务的处理器 Bean 类型不正确,未实现 JobHandler 接口"); // ========== API 错误日志 1-001-002-000 ========== diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java index b7d2403dc..101781c48 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java @@ -14,7 +14,6 @@ public enum CodegenFrontTypeEnum { VUE2(10), // Vue2 Element UI 标准模版 VUE3(20), // Vue3 Element Plus 标准模版 - VUE3_SCHEMA(21), // Vue3 Element Plus Schema 模版 VUE3_VBEN(30), // Vue3 VBEN 模版 ; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java index 4e742539d..63e0c92ac 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java @@ -135,15 +135,6 @@ public class CodegenEngine { vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue")) .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("api/api.ts"), vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) - // Vue3 Schema 模版 - .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/data.ts"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) - .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) - .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Form.vue")) - .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) // Vue3 vben 模版 .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/data.ts"), vue3FilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) @@ -496,10 +487,6 @@ public class CodegenEngine { "src/" + path; } - private static String vue3SchemaTemplatePath(String path) { - return "codegen/vue3_schema/" + path + ".vm"; - } - private static String vue3VbenTemplatePath(String path) { return "codegen/vue3_vben/" + path + ".vm"; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java index cfc52d29d..2ebf06619 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.quartz.SchedulerException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -91,13 +92,15 @@ public class JobServiceImpl implements JobService { } private void validateJobHandlerExists(String handlerName) { - Object handler = SpringUtil.getBean(handlerName); - if (handler == null) { + try { + Object handler = SpringUtil.getBean(handlerName); + assert handler != null; + if (!(handler instanceof JobHandler)) { + throw exception(JOB_HANDLER_BEAN_TYPE_ERROR); + } + } catch (NoSuchBeanDefinitionException e) { throw exception(JOB_HANDLER_BEAN_NOT_EXISTS); } - if (!(handler instanceof JobHandler)) { - throw exception(JOB_HANDLER_BEAN_TYPE_ERROR); - } } @Override diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/api/api.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/api/api.ts.vm deleted file mode 100644 index 48cd5422b..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/api/api.ts.vm +++ /dev/null @@ -1,46 +0,0 @@ -import request from '@/config/axios' -#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}") - -export interface ${simpleClassName}VO { - #foreach ($column in $columns) - #if ($column.createOperation || $column.updateOperation) - #if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal") - ${column.javaField}: number - #elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime") - ${column.javaField}: Date - #else - ${column.javaField}: ${column.javaType.toLowerCase()} - #end - #end - #end -} - -// 查询${table.classComment}列表 -export const get${simpleClassName}Page = async (params) => { - return await request.get({ url: '${baseURL}/page', params }) -} - -// 查询${table.classComment}详情 -export const get${simpleClassName} = async (id: number) => { - return await request.get({ url: '${baseURL}/get?id=' + id }) -} - -// 新增${table.classComment} -export const create${simpleClassName} = async (data: ${simpleClassName}VO) => { - return await request.post({ url: '${baseURL}/create', data }) -} - -// 修改${table.classComment} -export const update${simpleClassName} = async (data: ${simpleClassName}VO) => { - return await request.put({ url: '${baseURL}/update', data }) -} - -// 删除${table.classComment} -export const delete${simpleClassName} = async (id: number) => { - return await request.delete({ url: '${baseURL}/delete?id=' + id }) -} - -// 导出${table.classComment} Excel -export const export${simpleClassName}Api = async (params) => { - return await request.download({ url: '${baseURL}/export-excel', params }) -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/data.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/data.ts.vm deleted file mode 100644 index ff4fa810a..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/data.ts.vm +++ /dev/null @@ -1,124 +0,0 @@ -import type { CrudSchema } from '@/hooks/web/useCrudSchemas' -import { dateFormatter } from '@/utils/formatTime' - -// 表单校验 -export const rules = reactive({ -#foreach ($column in $columns) -#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键 -#set($comment=$column.columnComment) - $column.javaField: [required], -#end -#end -}) - -// CrudSchema https://doc.iocoder.cn/vue3/crud-schema/ -const crudSchemas = reactive([ -#foreach($column in $columns) -#if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation) -#set ($dictType = $column.dictType) -#set ($javaField = $column.javaField) -#set ($javaType = $column.javaType) - { - label: '${column.columnComment}', - field: '${column.javaField}', -## ========= 字典部分 ========= - #if ("" != $dictType)## 有数据字典 - dictType: DICT_TYPE.$dictType.toUpperCase(), - #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") - dictClass: 'number', - #elseif ($javaType == "String") - dictClass: 'string', - #elseif ($javaType == "Boolean") - dictClass: 'boolean', - #end - #end -## ========= Table 表格部分 ========= - #if (!$column.listOperationResult) - isTable: false, - #else - #if ($column.htmlType == "datetime") - formatter: dateFormatter, - #end - #end -## ========= Search 表格部分 ========= - #if ($column.listOperation) - isSearch: true, - #if ($column.htmlType == "datetime") - search: { - component: 'DatePicker', - componentProps: { - valueFormat: 'YYYY-MM-DD HH:mm:ss', - type: 'daterange', - defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')] - } - }, - #end - #end -## ========= Form 表单部分 ========= - #if ((!$column.createOperation && !$column.updateOperation) || $column.primaryKey) - isForm: false, - #else - #if($column.htmlType == "imageUpload")## 图片上传 - form: { - component: 'UploadImg' - }, - #elseif($column.htmlType == "fileUpload")## 文件上传 - form: { - component: 'UploadFile' - }, - #elseif($column.htmlType == "editor")## 文本编辑器 - form: { - component: 'Editor', - componentProps: { - valueHtml: '', - height: 200 - } - }, - #elseif($column.htmlType == "select")## 下拉框 - form: { - component: 'SelectV2' - }, - #elseif($column.htmlType == "checkbox")## 多选框 - form: { - component: 'Checkbox' - }, - #elseif($column.htmlType == "radio")## 单选框 - form: { - component: 'Radio' - }, - #elseif($column.htmlType == "datetime")## 时间框 - form: { - component: 'DatePicker', - componentProps: { - type: 'datetime', - valueFormat: 'x' - } - }, - #elseif($column.htmlType == "textarea")## 文本框 - form: { - component: 'Input', - componentProps: { - type: 'textarea', - rows: 4 - }, - colProps: { - span: 24 - } - }, - #elseif(${javaType.toLowerCase()} == "long" || ${javaType.toLowerCase()} == "integer")## 文本框 - form: { - component: 'InputNumber', - value: 0 - }, - #end - #end - }, -#end -#end - { - label: '操作', - field: 'action', - isForm: false - } -]) -export const { allSchemas } = useCrudSchemas(crudSchemas) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/form.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/form.vue.vm deleted file mode 100644 index 52f20a2f5..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/form.vue.vm +++ /dev/null @@ -1,65 +0,0 @@ - - - - - 确 定 - 取 消 - - - - diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/index.vue.vm deleted file mode 100644 index 6e8f1403a..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/index.vue.vm +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - 新增 - - - - - - - - - - - 编辑 - - - 删除 - - - - - - - <${simpleClassName}Form ref="formRef" @success="getList" /> - - diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/data.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/data.ts.vm index 92d3b2d75..56f4e82ca 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/data.ts.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/data.ts.vm @@ -42,9 +42,17 @@ export const searchFormSchema: FormSchema[] = [ #foreach($column in $columns) #if ($column.listOperation) #set ($dictType=$column.dictType) + #set ($javaType = $column.javaType) #set ($javaField = $column.javaField) #set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set ($comment=$column.columnComment) + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") + #set ($dictMethod = "number") + #elseif ($javaType == "String") + #set ($dictMethod = "string") + #elseif ($javaType == "Boolean") + #set ($dictMethod = "boolean") + #end { label: '${comment}', field: '${javaField}', @@ -54,16 +62,16 @@ export const searchFormSchema: FormSchema[] = [ component: 'Select', componentProps: { #if ("" != $dictType)## 设置了 dictType 数据字典的情况 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase()), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else## 未设置 dictType 数据字典的情况 options: [], #end }, #elseif ($column.htmlType == "radio") - component: 'Radio', + component: 'RadioButtonGroup', componentProps: { #if ("" != $dictType)## 设置了 dictType 数据字典的情况 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase()), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else## 未设置 dictType 数据字典的情况 options: [], #end @@ -87,9 +95,17 @@ export const createFormSchema: FormSchema[] = [ #foreach($column in $columns) #if ($column.createOperation) #set ($dictType = $column.dictType) + #set ($javaType = $column.javaType) #set ($javaField = $column.javaField) #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set ($comment = $column.columnComment) + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") + #set ($dictMethod = "number") + #elseif ($javaType == "String") + #set ($dictMethod = "string") + #elseif ($javaType == "Boolean") + #set ($dictMethod = "boolean") + #end #if (!$column.primaryKey)## 忽略主键,不用在表单里 { label: '${comment}', @@ -117,7 +133,7 @@ export const createFormSchema: FormSchema[] = [ component: 'Select', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end @@ -126,7 +142,7 @@ export const createFormSchema: FormSchema[] = [ component: 'Checkbox', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end @@ -135,7 +151,7 @@ export const createFormSchema: FormSchema[] = [ component: 'RadioButtonGroup', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end @@ -166,9 +182,17 @@ export const updateFormSchema: FormSchema[] = [ #foreach($column in $columns) #if ($column.updateOperation) #set ($dictType = $column.dictType) +#set ($javaType = $column.javaType) #set ($javaField = $column.javaField) #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set ($comment = $column.columnComment) +#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") + #set ($dictMethod = "number") +#elseif ($javaType == "String") + #set ($dictMethod = "string") +#elseif ($javaType == "Boolean") + #set ($dictMethod = "boolean") +#end #if (!$column.primaryKey)## 忽略主键,不用在表单里 { label: '${comment}', @@ -196,7 +220,7 @@ export const updateFormSchema: FormSchema[] = [ component: 'Select', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end @@ -205,7 +229,7 @@ export const updateFormSchema: FormSchema[] = [ component: 'Checkbox', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end @@ -214,7 +238,7 @@ export const updateFormSchema: FormSchema[] = [ component: 'RadioButtonGroup', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java index e4e497dba..168f19ea0 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java @@ -4,10 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; -import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO; -import cn.iocoder.yudao.module.member.api.user.MemberUserApi; -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuRespVO; @@ -51,11 +47,6 @@ public class AppProductSpuController { @Resource private ProductBrowseHistoryService productBrowseHistoryService; - @Resource - private MemberLevelApi memberLevelApi; - @Resource - private MemberUserApi memberUserApi; - @GetMapping("/list-by-ids") @Operation(summary = "获得商品 SPU 列表") @Parameter(name = "ids", description = "编号列表", required = true) @@ -68,9 +59,6 @@ public class AppProductSpuController { // 拼接返回 list.forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount())); List voList = BeanUtils.toBean(list, AppProductSpuRespVO.class); - // 处理 vip 价格 - MemberLevelRespDTO memberLevel = getMemberLevel(); - voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel))); return success(voList); } @@ -85,9 +73,6 @@ public class AppProductSpuController { // 拼接返回 pageResult.getList().forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount())); PageResult voPageResult = BeanUtils.toBean(pageResult, AppProductSpuRespVO.class); - // 处理 vip 价格 - MemberLevelRespDTO memberLevel = getMemberLevel(); - voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel))); return success(voPageResult); } @@ -115,37 +100,7 @@ public class AppProductSpuController { spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()); AppProductSpuDetailRespVO spuVO = BeanUtils.toBean(spu, AppProductSpuDetailRespVO.class) .setSkus(BeanUtils.toBean(skus, AppProductSpuDetailRespVO.Sku.class)); - // 处理 vip 价格 - MemberLevelRespDTO memberLevel = getMemberLevel(); - spuVO.setVipPrice(calculateVipPrice(spuVO.getPrice(), memberLevel)); return success(spuVO); } - private MemberLevelRespDTO getMemberLevel() { - Long userId = getLoginUserId(); - if (userId == null) { - return null; - } - MemberUserRespDTO user = memberUserApi.getUser(userId); - if (user.getLevelId() == null || user.getLevelId() <= 0) { - return null; - } - return memberLevelApi.getMemberLevel(user.getLevelId()); - } - - /** - * 计算会员 VIP 优惠价格 - * - * @param price 原价 - * @param memberLevel 会员等级 - * @return 优惠价格 - */ - public Integer calculateVipPrice(Integer price, MemberLevelRespDTO memberLevel) { - if (memberLevel == null || memberLevel.getDiscountPercent() == null) { - return 0; - } - Integer newPrice = price * memberLevel.getDiscountPercent() / 100; - return price - newPrice; - } - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java index f1ee49b10..525f22453 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java @@ -46,9 +46,6 @@ public class AppProductSpuDetailRespVO { @Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Integer marketPrice; - @Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格 - private Integer vipPrice; - @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") private Integer stock; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java index df61090bb..04e9af9ea 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java @@ -38,9 +38,6 @@ public class AppProductSpuRespVO { @Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Integer marketPrice; - @Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格 - private Integer vipPrice; - @Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") private Integer stock; diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java index 942ededec..50dae948f 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.promotion.api.combination; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateRespDTO; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; - import jakarta.validation.Valid; /** @@ -33,13 +33,13 @@ public interface CombinationRecordApi { CombinationRecordCreateRespDTO createCombinationRecord(@Valid CombinationRecordCreateReqDTO reqDTO); /** - * 查询拼团记录是否成功 + * 基于订单编号,查询拼团记录 * * @param userId 用户编号 * @param orderId 订单编号 - * @return 拼团是否成功 + * @return 拼团记录 */ - boolean isCombinationRecordSuccess(Long userId, Long orderId); + CombinationRecordRespDTO getCombinationRecordByOrderId(Long userId, Long orderId); /** * 【下单前】校验是否满足拼团活动条件 diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordRespDTO.java new file mode 100644 index 000000000..82fe21257 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordRespDTO.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.promotion.api.combination.dto; + +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 拼团记录 Response DTO + * + * @author 芋道源码 + */ +@Data +public class CombinationRecordRespDTO { + + /** + * 编号,主键自增 + */ + private Long id; + + /** + * 拼团活动编号 + * + * 关联 CombinationActivityDO 的 id 字段 + */ + private Long activityId; + /** + * 拼团商品单价 + * + * 冗余 CombinationProductDO 的 combinationPrice 字段 + */ + private Integer combinationPrice; + /** + * SPU 编号 + */ + private Long spuId; + /** + * 商品名字 + */ + private String spuName; + /** + * 商品图片 + */ + private String picUrl; + /** + * SKU 编号 + */ + private Long skuId; + /** + * 购买的商品数量 + */ + private Integer count; + + /** + * 用户编号 + */ + private Long userId; + + /** + * 用户昵称 + */ + private String nickname; + /** + * 用户头像 + */ + private String avatar; + + /** + * 团长编号 + */ + private Long headId; + /** + * 开团状态 + * + * 关联 {@link CombinationRecordStatusEnum} + */ + private Integer status; + /** + * 订单编号 + */ + private Long orderId; + /** + * 开团需要人数 + * + * 关联 CombinationActivityDO 的 userSize 字段 + */ + private Integer userSize; + /** + * 已加入拼团人数 + */ + private Integer userCount; + /** + * 是否虚拟成团 + */ + private Boolean virtualGroup; + + /** + * 过期时间 + */ + private LocalDateTime expireTime; + /** + * 开始时间 (订单付款后开始的时间) + */ + private LocalDateTime startTime; + /** + * 结束时间(成团时间/失败时间) + */ + private LocalDateTime endTime; + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java index 789a4526d..10d4eb64c 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.api.coupon; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; import jakarta.validation.Valid; import java.util.List; @@ -15,6 +14,15 @@ import java.util.Map; */ public interface CouponApi { + /** + * 获得用户的优惠劵列表 + * + * @param userId 用户编号 + * @param status 优惠劵状态 + * @return 优惠劵列表 + */ + List getCouponListByUserId(Long userId, Integer status); + /** * 使用优惠劵 * @@ -29,14 +37,6 @@ public interface CouponApi { */ void returnUsedCoupon(Long id); - /** - * 校验优惠劵 - * - * @param validReqDTO 校验请求 - * @return 优惠劵 - */ - CouponRespDTO validateCoupon(@Valid CouponValidReqDTO validReqDTO); - /** * 【管理员】给指定用户批量发送优惠券 * diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java deleted file mode 100644 index f219b6fdd..000000000 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.promotion.api.coupon.dto; - -import lombok.Data; - -import jakarta.validation.constraints.NotNull; - -/** - * 优惠劵使用 Request DTO - * - * @author 芋道源码 - */ -@Data -public class CouponValidReqDTO { - - /** - * 优惠劵编号 - */ - @NotNull(message = "优惠劵编号不能为空") - private Long id; - - /** - * 用户编号 - */ - @NotNull(message = "用户编号不能为空") - private Long userId; - -} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java index b25f67d9f..bf8880f8c 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java @@ -13,11 +13,11 @@ import java.util.List; public interface DiscountActivityApi { /** - * 获得商品匹配的的限时折扣信息 + * 获得 skuId 商品匹配的的限时折扣信息 * * @param skuIds 商品 SKU 编号数组 * @return 限时折扣信息 */ - List getMatchDiscountProductList(Collection skuIds); + List getMatchDiscountProductListBySkuIds(Collection skuIds); } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java index 52dfdbe27..7557580f2 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.promotion.api.discount.dto; import lombok.Data; +import java.time.LocalDateTime; + /** * 限时折扣活动商品 Response DTO * @@ -44,5 +46,14 @@ public class DiscountProductRespDTO { * 活动标题 */ private String activityName; + /** + * 活动开始时间点 + */ + private LocalDateTime activityStartTime; + /** + * 活动结束时间点 + */ + private LocalDateTime activityEndTime; + } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java index 68f76a1fa..c33afadd2 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.reward; import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; -import java.time.LocalDateTime; +import java.util.Collection; import java.util.List; /** @@ -13,12 +13,11 @@ import java.util.List; public interface RewardActivityApi { /** - * 获得当前时间内开启的满减送活动 + * 获得 spuId 商品匹配的的满减送活动列表 * - * @param status 状态 - * @param dateTime 当前时间,即筛选 <= dateTime 的满减送活动 + * @param spuIds SPU 编号 * @return 满减送活动列表 */ - List getRewardActivityListByStatusAndNow(Integer status, LocalDateTime dateTime); + List getMatchRewardActivityListBySpuIds(Collection spuIds); } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java index 958668461..2eeb07266 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java @@ -18,6 +18,11 @@ import java.util.Map; @Data public class RewardActivityMatchRespDTO { + /** + * 匹配的 SPU 数组 + */ + private List spuIds; + /** * 活动编号,主键自增 */ @@ -100,6 +105,13 @@ public class RewardActivityMatchRespDTO { */ private Map giveCouponTemplateCounts; + /** + * 规则描述 + * + * 通过 {@link #limit}、{@link #discountPrice} 等字段进行拼接 + */ + private String description; + } } 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 319625387..31b1c1c4d 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 @@ -20,8 +20,6 @@ public interface ErrorCodeConstants { ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1_013_002_000, "Banner 不存在"); // ========== Coupon 相关 1-013-003-000 ============ - ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1_013_003_000, "优惠劵没有可使用的商品!"); - ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1_013_003_001, "所结算的商品中未满足使用的金额"); // ========== 优惠劵模板 1-013-004-000 ========== ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_004_000, "优惠劵模板不存在"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java index 354f5b359..32f9ea426 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java @@ -1,19 +1,17 @@ package cn.iocoder.yudao.module.promotion.api.combination; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateRespDTO; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; -import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_RECORD_NOT_EXISTS; - /** * 拼团活动 API 实现类 * @@ -37,12 +35,9 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { } @Override - public boolean isCombinationRecordSuccess(Long userId, Long orderId) { + public CombinationRecordRespDTO getCombinationRecordByOrderId(Long userId, Long orderId) { CombinationRecordDO record = combinationRecordService.getCombinationRecord(userId, orderId); - if (record == null) { - throw exception(COMBINATION_RECORD_NOT_EXISTS); - } - return CombinationRecordStatusEnum.isSuccess(record.getStatus()); + return BeanUtils.toBean(record, CombinationRecordRespDTO.class); } @Override diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java index edc8f1b7f..167883e0b 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java @@ -1,11 +1,9 @@ package cn.iocoder.yudao.module.promotion.api.coupon; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; -import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; -import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -26,6 +24,11 @@ public class CouponApiImpl implements CouponApi { @Resource private CouponService couponService; + @Override + public List getCouponListByUserId(Long userId, Integer status) { + return BeanUtils.toBean(couponService.getCouponList(userId, status), CouponRespDTO.class); + } + @Override public void useCoupon(CouponUseReqDTO useReqDTO) { couponService.useCoupon(useReqDTO.getId(), useReqDTO.getUserId(), @@ -37,12 +40,6 @@ public class CouponApiImpl implements CouponApi { couponService.returnUsedCoupon(id); } - @Override - public CouponRespDTO validateCoupon(CouponValidReqDTO validReqDTO) { - CouponDO coupon = couponService.validCoupon(validReqDTO.getId(), validReqDTO.getUserId()); - return CouponConvert.INSTANCE.convert(coupon); - } - @Override public List takeCouponsByAdmin(Map giveCoupons, Long userId) { return couponService.takeCouponsByAdmin(giveCoupons, userId); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java index 82b8516f9..d9af82a00 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java @@ -1,12 +1,13 @@ package cn.iocoder.yudao.module.promotion.api.discount; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; -import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.util.Collection; import java.util.List; @@ -23,8 +24,9 @@ public class DiscountActivityApiImpl implements DiscountActivityApi { private DiscountActivityService discountActivityService; @Override - public List getMatchDiscountProductList(Collection skuIds) { - return DiscountActivityConvert.INSTANCE.convertList02(discountActivityService.getMatchDiscountProductList(skuIds)); + public List getMatchDiscountProductListBySkuIds(Collection skuIds) { + List list = discountActivityService.getMatchDiscountProductListBySkuIds(skuIds); + return BeanUtils.toBean(list, DiscountProductRespDTO.class); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java index ce3d1c802..24d8844ee 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java @@ -1,14 +1,12 @@ package cn.iocoder.yudao.module.promotion.api.reward; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; -import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import java.time.LocalDateTime; +import java.util.Collection; import java.util.List; /** @@ -24,9 +22,8 @@ public class RewardActivityApiImpl implements RewardActivityApi { private RewardActivityService rewardActivityService; @Override - public List getRewardActivityListByStatusAndNow(Integer status, LocalDateTime dateTime) { - List list = rewardActivityService.getRewardActivityListByStatusAndDateTimeLt(status, dateTime); - return BeanUtils.toBean(list, RewardActivityMatchRespDTO.class); + public List getMatchRewardActivityListBySpuIds(Collection spuIds) { + return rewardActivityService.getMatchRewardActivityListBySpuIds(spuIds); } } 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 index 9ba319463..2f9e7863f 100644 --- 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 @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; @@ -16,18 +17,20 @@ import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordSe import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; +import java.util.Collections; import java.util.List; import java.util.Map; 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.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - 拼团活动") @@ -87,6 +90,23 @@ public class CombinationActivityController { return success(CombinationActivityConvert.INSTANCE.convert(activity, products)); } + @GetMapping("/list-by-ids") + @Operation(summary = "获得拼团活动列表,基于活动编号数组") + @Parameter(name = "ids", description = "活动编号数组", required = true, example = "[1024, 1025]") + public CommonResult> getCombinationActivityListByIds(@RequestParam("ids") List ids) { + // 1. 获得开启的活动列表 + List activityList = combinationActivityService.getCombinationActivityListByIds(ids); + activityList.removeIf(activity -> CommonStatusEnum.isDisable(activity.getStatus())); + if (CollUtil.isEmpty(activityList)) { + return success(Collections.emptyList()); + } + // 2. 拼接返回 + List productList = combinationActivityService.getCombinationProductListByActivityIds( + convertList(activityList, CombinationActivityDO::getId)); + List spuList = productSpuApi.getSpuList(convertList(activityList, CombinationActivityDO::getSpuId)); + return success(CombinationActivityConvert.INSTANCE.convertList(activityList, productList, spuList)); + } + @GetMapping("/page") @Operation(summary = "获得拼团活动分页") @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") 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 index 0ac77c559..d65ecfe10 100644 --- 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 @@ -27,4 +27,14 @@ public class CombinationActivityRespVO extends CombinationActivityBaseVO { @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED) private List products; + @Schema(description = "商品 SPU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "一个白菜") + private String spuName; // 从 SPU 的 name 读取 + @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") + private String picUrl; // 从 SPU 的 picUrl 读取 + @Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") + private Integer marketPrice; // 从 SPU 的 marketPrice 读取 + + @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer combinationPrice; // 从 products 获取最小 price 读取 + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplateBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplateBaseVO.java index 6885246b4..98842bcf9 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplateBaseVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplateBaseVO.java @@ -9,12 +9,12 @@ import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityType import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - import jakarta.validation.constraints.AssertTrue; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + import java.time.LocalDateTime; import java.util.List; import java.util.Objects; 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 dd64870e4..de90c0977 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 @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; @@ -13,15 +14,17 @@ import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; +import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - 秒杀活动") @@ -89,11 +92,28 @@ public class SeckillActivityController { } // 拼接数据 - List products = seckillActivityService.getSeckillProductListByActivityId( + List products = seckillActivityService.getSeckillProductListByActivityIds( convertSet(pageResult.getList(), SeckillActivityDO::getId)); List spuList = productSpuApi.getSpuList( convertSet(pageResult.getList(), SeckillActivityDO::getSpuId)); return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, products, spuList)); } + @GetMapping("/list-by-ids") + @Operation(summary = "获得秒杀活动列表,基于活动编号数组") + @Parameter(name = "ids", description = "活动编号数组", required = true, example = "[1024, 1025]") + public CommonResult> getCombinationActivityListByIds(@RequestParam("ids") List ids) { + // 1. 获得开启的活动列表 + List activityList = seckillActivityService.getSeckillActivityListByIds(ids); + activityList.removeIf(activity -> CommonStatusEnum.isDisable(activity.getStatus())); + if (CollUtil.isEmpty(activityList)) { + return success(Collections.emptyList()); + } + // 2. 拼接返回 + List productList = seckillActivityService.getSeckillProductListByActivityIds( + convertList(activityList, SeckillActivityDO::getId)); + List spuList = productSpuApi.getSpuList(convertList(activityList, SeckillActivityDO::getSpuId)); + return success(SeckillActivityConvert.INSTANCE.convertList(activityList, productList, spuList)); + } + } 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 742c73ba6..18b2170e3 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 @@ -54,4 +54,7 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO { example = "50") private Integer marketPrice; + @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer seckillPrice; // 从 products 获取最小 price 读取 + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java index fae7fa54d..59a9e781e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java @@ -1,25 +1,13 @@ package cn.iocoder.yudao.module.promotion.controller.app.activity; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -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.app.activity.vo.AppActivityRespVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; -import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; -import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; -import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; -import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; -import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; -import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -31,11 +19,10 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.time.LocalDateTime; -import java.util.*; +import java.util.ArrayList; +import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; @Tag(name = "用户 APP - 营销活动") // 用于提供跨多个活动的 HTTP 接口 @RestController @@ -49,152 +36,31 @@ public class AppActivityController { private SeckillActivityService seckillActivityService; @Resource private BargainActivityService bargainActivityService; - @Resource - private DiscountActivityService discountActivityService; - @Resource - private RewardActivityService rewardActivityService; - - @Resource - private ProductSpuApi productSpuApi; @GetMapping("/list-by-spu-id") - @Operation(summary = "获得单个商品,近期参与的每个活动") + @Operation(summary = "获得单个商品,进行中的拼团、秒杀、砍价活动信息", description = "每种活动,只返回一个") @Parameter(name = "spuId", description = "商品编号", required = true) public CommonResult> getActivityListBySpuId(@RequestParam("spuId") Long spuId) { - // 每种活动,只返回一个 - return success(getAppActivityList(Collections.singletonList(spuId))); - } - - @GetMapping("/list-by-spu-ids") - @Operation(summary = "获得多个商品,近期参与的每个活动") - @Parameter(name = "spuIds", description = "商品编号数组", required = true) - public CommonResult>> getActivityListBySpuIds(@RequestParam("spuIds") List spuIds) { - if (CollUtil.isEmpty(spuIds)) { - return success(MapUtil.empty()); - } - // 每种活动,只返回一个;key 为 SPU 编号 - return success(convertMultiMap(getAppActivityList(spuIds), AppActivityRespVO::getSpuId)); - } - - private List getAppActivityList(Collection spuIds) { - if (CollUtil.isEmpty(spuIds)) { - return new ArrayList<>(); - } - // 获取开启的且开始的且没有结束的活动 - List activityList = new ArrayList<>(); - LocalDateTime now = LocalDateTime.now(); + List activityVOList = new ArrayList<>(); // 1. 拼团活动 - getCombinationActivities(spuIds, now, activityList); + CombinationActivityDO combinationActivity = combinationActivityService.getMatchCombinationActivityBySpuId(spuId); + if (combinationActivity != null) { + activityVOList.add(new AppActivityRespVO(combinationActivity.getId(), PromotionTypeEnum.COMBINATION_ACTIVITY.getType(), + combinationActivity.getName(), combinationActivity.getSpuId(), combinationActivity.getStartTime(), combinationActivity.getEndTime())); + } // 2. 秒杀活动 - getSeckillActivities(spuIds, now, activityList); + SeckillActivityDO seckillActivity = seckillActivityService.getMatchSeckillActivityBySpuId(spuId); + if (seckillActivity != null) { + activityVOList.add(new AppActivityRespVO(seckillActivity.getId(), PromotionTypeEnum.SECKILL_ACTIVITY.getType(), + seckillActivity.getName(), seckillActivity.getSpuId(), seckillActivity.getStartTime(), seckillActivity.getEndTime())); + } // 3. 砍价活动 - getBargainActivities(spuIds, now, activityList); - // 4. 限时折扣活动 - getDiscountActivities(spuIds, now, activityList); - // 5. 满减送活动 - getRewardActivityList(spuIds, now, activityList); - return activityList; - } - - private void getCombinationActivities(Collection spuIds, LocalDateTime now, List activityList) { - List combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatusAndDateTimeLt( - spuIds, CommonStatusEnum.ENABLE.getStatus(), now); - if (CollUtil.isEmpty(combinationActivities)) { - return; - } - - combinationActivities.forEach(item -> { - activityList.add(new AppActivityRespVO(item.getId(), PromotionTypeEnum.COMBINATION_ACTIVITY.getType(), - item.getName(), item.getSpuId(), item.getStartTime(), item.getEndTime())); - }); - } - - private void getSeckillActivities(Collection spuIds, LocalDateTime now, List activityList) { - List seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatusAndDateTimeLt( - spuIds, CommonStatusEnum.ENABLE.getStatus(), now); - if (CollUtil.isEmpty(seckillActivities)) { - return; - } - - seckillActivities.forEach(item -> { - activityList.add(new AppActivityRespVO(item.getId(), PromotionTypeEnum.SECKILL_ACTIVITY.getType(), - item.getName(), item.getSpuId(), item.getStartTime(), item.getEndTime())); - }); - } - - private void getBargainActivities(Collection spuIds, LocalDateTime now, List activityList) { - List bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatusAndDateTimeLt( - spuIds, CommonStatusEnum.ENABLE.getStatus(), now); - if (CollUtil.isNotEmpty(bargainActivities)) { - return; - } - - bargainActivities.forEach(item -> { - activityList.add(new AppActivityRespVO(item.getId(), PromotionTypeEnum.BARGAIN_ACTIVITY.getType(), - item.getName(), item.getSpuId(), item.getStartTime(), item.getEndTime())); - }); - } - - private void getDiscountActivities(Collection spuIds, LocalDateTime now, List activityList) { - List discountActivities = discountActivityService.getDiscountActivityBySpuIdsAndStatusAndDateTimeLt( - spuIds, CommonStatusEnum.ENABLE.getStatus(), now); - if (CollUtil.isEmpty(discountActivities)) { - return; - } - - List products = discountActivityService.getDiscountProductsByActivityId( - convertSet(discountActivities, DiscountActivityDO::getId)); - Map productMap = convertMap(products, DiscountProductDO::getActivityId, DiscountProductDO::getSpuId); - discountActivities.forEach(item -> activityList.add(new AppActivityRespVO(item.getId(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(), - item.getName(), productMap.get(item.getId()), item.getStartTime(), item.getEndTime()))); - } - - private void getRewardActivityList(Collection spuIds, LocalDateTime now, List activityList) { - // 1.1 获得所有的活动 - List rewardActivityList = rewardActivityService.getRewardActivityListByStatusAndDateTimeLt( - CommonStatusEnum.ENABLE.getStatus(), now); - if (CollUtil.isEmpty(rewardActivityList)) { - return; - } - // 1.2 获得所有的商品信息 - List spuList = productSpuApi.getSpuList(spuIds); - if (CollUtil.isEmpty(spuList)) { - return; - } - - // 2. 构建活动 - for (RewardActivityDO rewardActivity : rewardActivityList) { - // 情况一:所有商品都能参加 - if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope())) { - buildAppActivityRespVO(rewardActivity, spuIds, activityList); - } - // 情况二:指定商品参加 - if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope())) { - List fSpuIds = spuList.stream().map(ProductSpuRespDTO::getId).filter(id -> - rewardActivity.getProductScopeValues().contains(id)).toList(); - buildAppActivityRespVO(rewardActivity, fSpuIds, activityList); - } - // 情况三:指定商品类型参加 - if (PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) { - List fSpuIds = spuList.stream().filter(spuItem -> rewardActivity.getProductScopeValues() - .contains(spuItem.getCategoryId())).map(ProductSpuRespDTO::getId).toList(); - buildAppActivityRespVO(rewardActivity, fSpuIds, activityList); - } - } - } - - private static void buildAppActivityRespVO(RewardActivityDO rewardActivity, Collection spuIds, - List activityList) { - for (Long spuId : spuIds) { - // 校验商品是否已经加入过活动 - if (anyMatch(activityList, appActivity -> ObjUtil.equal(appActivity.getId(), rewardActivity.getId()) && - ObjUtil.equal(appActivity.getSpuId(), spuId))) { - continue; - } - activityList.add(new AppActivityRespVO(rewardActivity.getId(), - PromotionTypeEnum.REWARD_ACTIVITY.getType(), rewardActivity.getName(), spuId, - rewardActivity.getStartTime(), rewardActivity.getEndTime())); + BargainActivityDO bargainActivity = bargainActivityService.getMatchBargainActivityBySpuId(spuId); + if (bargainActivity != null) { + activityVOList.add(new AppActivityRespVO(bargainActivity.getId(), PromotionTypeEnum.BARGAIN_ACTIVITY.getType(), + bargainActivity.getName(), bargainActivity.getSpuId(), bargainActivity.getStartTime(), bargainActivity.getEndTime())); } + return success(activityVOList); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java index 867c2d4b8..90a9fd8d7 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java @@ -14,24 +14,20 @@ import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivity import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import jakarta.annotation.Resource; -import java.time.Duration; import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "用户 APP - 拼团活动") @@ -40,45 +36,12 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. @Validated public class AppCombinationActivityController { - /** - * {@link AppCombinationActivityRespVO} 缓存,通过它异步刷新 {@link #getCombinationActivityList0(Integer)} 所要的首页数据 - */ - private final LoadingCache> combinationActivityListCache = buildAsyncReloadingCache(Duration.ofSeconds(10L), - new CacheLoader>() { - - @Override - public List load(Integer count) { - return getCombinationActivityList0(count); - } - - }); - @Resource private CombinationActivityService activityService; @Resource private ProductSpuApi spuApi; - @GetMapping("/list") - @Operation(summary = "获得拼团活动列表", description = "用于小程序首页") - @Parameter(name = "count", description = "需要展示的数量", example = "6") - public CommonResult> getCombinationActivityList( - @RequestParam(name = "count", defaultValue = "6") Integer count) { - return success(combinationActivityListCache.getUnchecked(count)); - } - - private List getCombinationActivityList0(Integer count) { - List activityList = activityService.getCombinationActivityListByCount(count); - if (CollUtil.isEmpty(activityList)) { - return Collections.emptyList(); - } - // 拼接返回 - List productList = activityService.getCombinationProductListByActivityIds( - convertList(activityList, CombinationActivityDO::getId)); - List spuList = spuApi.getSpuList(convertList(activityList, CombinationActivityDO::getSpuId)); - return CombinationActivityConvert.INSTANCE.convertAppList(activityList, productList, spuList); - } - @GetMapping("/page") @Operation(summary = "获得拼团活动分页") public CommonResult> getCombinationActivityPage(PageParam pageParam) { @@ -93,6 +56,23 @@ public class AppCombinationActivityController { return success(CombinationActivityConvert.INSTANCE.convertAppPage(pageResult, productList, spuList)); } + @GetMapping("/list-by-ids") + @Operation(summary = "获得拼团活动列表,基于活动编号数组") + @Parameter(name = "ids", description = "活动编号数组", required = true, example = "[1024, 1025]") + public CommonResult> getCombinationActivityListByIds(@RequestParam("ids") List ids) { + // 1. 获得开启的活动列表 + List activityList = activityService.getCombinationActivityListByIds(ids); + activityList.removeIf(activity -> CommonStatusEnum.isDisable(activity.getStatus())); + if (CollUtil.isEmpty(activityList)) { + return success(Collections.emptyList()); + } + // 2. 拼接返回 + List productList = activityService.getCombinationProductListByActivityIds( + convertList(activityList, CombinationActivityDO::getId)); + List spuList = spuApi.getSpuList(convertList(activityList, CombinationActivityDO::getSpuId)); + return success(CombinationActivityConvert.INSTANCE.convertAppList(activityList, productList, spuList)); + } + @GetMapping("/get-detail") @Operation(summary = "获得拼团活动明细") @Parameter(name = "id", description = "活动编号", required = true, example = "1024") diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java index 64462a377..8f933fa3e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java @@ -19,15 +19,14 @@ public class AppCombinationActivityRespVO { @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") private Long spuId; + @Schema(description = "商品 SPU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "一个白菜") + private String spuName; // 从 SPU 的 name 读取 @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") - // 从 SPU 的 picUrl 读取 - private String picUrl; - + private String picUrl; // 从 SPU 的 picUrl 读取 @Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") - // 从 SPU 的 marketPrice 读取 - private Integer marketPrice; + private Integer marketPrice; // 从 SPU 的 marketPrice 读取 @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") - private Integer combinationPrice; + private Integer combinationPrice; // 从 products 获取最小 price 读取 } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java index ed19d9141..bde2d8f91 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java @@ -5,7 +5,9 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.*; +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO; +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO; +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponTakeReqVO; import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; @@ -15,13 +17,12 @@ import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import java.util.Collections; -import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -56,14 +57,6 @@ public class AppCouponController { return success(canTakeAgain); } - @GetMapping("/match-list") - @Operation(summary = "获得匹配指定商品的优惠劵列表", description = "用于下单页,展示优惠劵列表") - public CommonResult> getMatchCouponList(AppCouponMatchReqVO matchReqVO) { - // todo: 优化:优惠金额倒序 - List list = couponService.getMatchCouponList(getLoginUserId(), matchReqVO); - return success(BeanUtils.toBean(list, AppCouponMatchRespVO.class)); - } - @GetMapping("/page") @Operation(summary = "我的优惠劵列表") @PreAuthenticated diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchReqVO.java deleted file mode 100755 index 6dc287d98..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchReqVO.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import java.util.List; - -@Schema(description = "用户 App - 优惠劵的匹配 Request VO") -@Data -public class AppCouponMatchReqVO { - - @Schema(description = "商品金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "商品金额不能为空") - private Integer price; - - @Schema(description = "商品 SPU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]") - @NotEmpty(message = "商品 SPU 编号不能为空") - private List spuIds; - - @Schema(description = "商品 SKU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]") - @NotEmpty(message = "商品 SKU 编号不能为空") - private List skuIds; - - @Schema(description = "分类编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[10, 20]") - @NotEmpty(message = "分类编号不能为空") - private List categoryIds; - -} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchRespVO.java deleted file mode 100755 index da60390fe..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchRespVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "用户 App - 优惠劵 Response VO") -@Data -public class AppCouponMatchRespVO extends AppCouponRespVO { - - @Schema(description = "是否匹配", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean match; - - @Schema(description = "匹配条件的提示", example = "所结算商品没有符合条件的商品") - private String description; - -} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java index c0949f671..f6084a2c4 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import jakarta.validation.constraints.Min; import java.time.LocalDateTime; import java.util.List; @@ -42,7 +41,6 @@ public class AppCouponRespVO { private Integer discountPercent; @Schema(description = "优惠金额", example = "10") - @Min(value = 0, message = "优惠金额需要大于等于 0") private Integer discountPrice; @Schema(description = "折扣上限", example = "100") // 单位:分,仅在 discountType 为 PERCENT 使用 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/reward/vo/AppRewardActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/reward/vo/AppRewardActivityRespVO.java index acaa5225d..37f77ba86 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/reward/vo/AppRewardActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/reward/vo/AppRewardActivityRespVO.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivi import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.time.LocalDateTime; import java.util.List; @Schema(description = "用户 App - 满减送活动 Response VO") @@ -19,6 +20,12 @@ public class AppRewardActivityRespVO { @Schema(description = "活动标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "满啦满啦") private String name; + @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime startTime; + + @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime endTime; + @Schema(description = "条件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer conditionType; @@ -26,7 +33,7 @@ public class AppRewardActivityRespVO { private Integer productScope; @Schema(description = "商品 SPU 编号的数组", example = "1,2,3") - private List productSpuIds; + private List productScopeValues; @Schema(description = "优惠规则的数组") private List rules; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java index c91de0ee7..6105f9516 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java @@ -23,6 +23,7 @@ import com.google.common.cache.LoadingCache; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -30,11 +31,11 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import jakarta.annotation.Resource; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -86,7 +87,7 @@ public class AppSeckillActivityController { // 2.1 查询满足当前阶段的活动 List activityList = activityService.getSeckillActivityListByConfigIdAndStatus(config.getId(), CommonStatusEnum.ENABLE.getStatus()); - List productList = activityService.getSeckillProductListByActivityId( + List productList = activityService.getSeckillProductListByActivityIds( convertList(activityList, SeckillActivityDO::getId)); // 2.2 获取 spu 信息 List spuList = spuApi.getSpuList(convertList(activityList, SeckillActivityDO::getSpuId)); @@ -101,7 +102,7 @@ public class AppSeckillActivityController { if (CollUtil.isEmpty(pageResult.getList())) { return success(PageResult.empty(pageResult.getTotal())); } - List productList = activityService.getSeckillProductListByActivityId( + List productList = activityService.getSeckillProductListByActivityIds( convertList(pageResult.getList(), SeckillActivityDO::getId)); // 2. 拼接数据 @@ -149,4 +150,21 @@ public class AppSeckillActivityController { return success(SeckillActivityConvert.INSTANCE.convert3(activity, productList, startTime, endTime)); } + @GetMapping("/list-by-ids") + @Operation(summary = "获得拼团活动列表,基于活动编号数组") + @Parameter(name = "ids", description = "活动编号数组", required = true, example = "[1024, 1025]") + public CommonResult> getCombinationActivityListByIds(@RequestParam("ids") List ids) { + // 1. 获得开启的活动列表 + List activityList = activityService.getSeckillActivityListByIds(ids); + activityList.removeIf(activity -> CommonStatusEnum.isDisable(activity.getStatus())); + if (CollUtil.isEmpty(activityList)) { + return success(Collections.emptyList()); + } + // 2. 拼接返回 + List productList = activityService.getSeckillProductListByActivityIds( + convertList(activityList, SeckillActivityDO::getId)); + List spuList = spuApi.getSpuList(convertList(activityList, SeckillActivityDO::getSpuId)); + return success(SeckillActivityConvert.INSTANCE.convertAppList(activityList, productList, spuList)); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java index 68e7ff829..907a3ce08 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java @@ -16,6 +16,9 @@ public class AppSeckillActivityRespVO { @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") private Long spuId; + @Schema(description = "商品 SPU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "一个白菜") + private String spuName; // 从 SPU 的 name 读取 + @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 picUrl 读取 example = "https://www.iocoder.cn/xx.png") private String picUrl; 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 index 8acdac6ee..3ee4a8190 100644 --- 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 @@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; @@ -127,40 +128,42 @@ public interface CombinationActivityConvert { .setSpuName(spu.getName()).setPicUrl(sku.getPicUrl()); } - List convertAppList(List list); - - default List convertAppList(List list, - List productList, - List spuList) { - List activityList = convertAppList(list); + default List convertList(List list, + List productList, + List spuList) { + List activityList = BeanUtils.toBean(list, CombinationActivityRespVO.class); Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); Map> productMap = convertMultiMap(productList, CombinationProductDO::getActivityId); return CollectionUtils.convertList(activityList, item -> { // 设置 product 信息 item.setCombinationPrice(getMinValue(productMap.get(item.getId()), CombinationProductDO::getCombinationPrice)); // 设置 SPU 信息 - findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); + findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()) + .setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); return item; }); } - PageResult convertAppPage(PageResult result); + default List convertAppList(List list, + List productList, + List spuList) { + List activityList = BeanUtils.toBean(list, AppCombinationActivityRespVO.class); + Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); + Map> productMap = convertMultiMap(productList, CombinationProductDO::getActivityId); + return CollectionUtils.convertList(activityList, item -> { + // 设置 product 信息 + item.setCombinationPrice(getMinValue(productMap.get(item.getId()), CombinationProductDO::getCombinationPrice)); + // 设置 SPU 信息 + findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()) + .setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); + return item; + }); + } default PageResult convertAppPage(PageResult result, List productList, List spuList) { - PageResult appPage = convertAppPage(result); - Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); - Map> productMap = convertMultiMap(productList, CombinationProductDO::getActivityId); - List list = CollectionUtils.convertList(appPage.getList(), item -> { - // 设置 product 信息 - item.setCombinationPrice(getMinValue(productMap.get(item.getId()), CombinationProductDO::getCombinationPrice)); - // 设置 SPU 信息 - findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); - return item; - }); - appPage.setList(list); - return appPage; + return new PageResult<>(convertAppList(result.getList(), productList, spuList), result.getTotal()); } AppCombinationActivityDetailRespVO convert2(CombinationActivityDO combinationActivity); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java index 542a77e84..0ac9c58da 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java @@ -4,9 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchRespVO; import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO; -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; @@ -16,7 +14,6 @@ import org.mapstruct.factory.Mappers; import java.time.LocalDateTime; import java.util.Collection; -import java.util.List; /** * 优惠劵 Convert diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java index 0ecbd92ef..8f0da6649 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; -import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.*; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; @@ -34,9 +33,6 @@ public interface DiscountActivityConvert { List convertList(List list); List convertList2(List list); - - List convertList02(List list); - PageResult convertPage(PageResult page); default PageResult convertPage(PageResult page, @@ -121,7 +117,10 @@ public interface DiscountActivityConvert { default boolean isEquals(DiscountProductDO productDO, DiscountProductDO productVO) { if (ObjectUtil.notEqual(productDO.getSpuId(), productVO.getSpuId()) || ObjectUtil.notEqual(productDO.getSkuId(), productVO.getSkuId()) - || ObjectUtil.notEqual(productDO.getDiscountType(), productVO.getDiscountType())) { + || ObjectUtil.notEqual(productDO.getDiscountType(), productVO.getDiscountType()) + || ObjectUtil.notEqual(productDO.getActivityEndTime(), productVO.getActivityEndTime()) + || ObjectUtil.notEqual(productDO.getActivityStartTime(), productVO.getActivityStartTime()) + || ObjectUtil.notEqual(productDO.getActivityStatus(), productVO.getActivityStatus())) { return false; } if (productDO.getDiscountType().equals(PromotionDiscountTypeEnum.PRICE.getType())) { diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java index 10259cb69..5c3277d0e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.convert.seckill; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; @@ -87,6 +88,38 @@ public interface SeckillActivityConvert { return CollectionUtils.convertList(products, item -> convert(activity, item).setActivityStatus(activity.getStatus())); } + default List convertList(List list, + List productList, + List spuList) { + List activityList = BeanUtils.toBean(list, SeckillActivityRespVO.class); + Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); + Map> productMap = convertMultiMap(productList, SeckillProductDO::getActivityId); + return CollectionUtils.convertList(activityList, item -> { + // 设置 product 信息 + item.setSeckillPrice(getMinValue(productMap.get(item.getId()), SeckillProductDO::getSeckillPrice)); + // 设置 SPU 信息 + findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()) + .setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); + return item; + }); + } + + default List convertAppList(List list, + List productList, + List spuList) { + List activityList = BeanUtils.toBean(list, AppSeckillActivityRespVO.class); + Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); + Map> productMap = convertMultiMap(productList, SeckillProductDO::getActivityId); + return CollectionUtils.convertList(activityList, item -> { + // 设置 product 信息 + item.setSeckillPrice(getMinValue(productMap.get(item.getId()), SeckillProductDO::getSeckillPrice)); + // 设置 SPU 信息 + findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()) + .setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); + return item; + }); + } + List convertList2(List list); List convertList3(List activityList); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java index 12b6822d6..b4baab40a 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java @@ -66,10 +66,16 @@ public class DiscountProductDO extends BaseDO { */ private Integer discountPrice; + /** + * 活动标题 + * + * 冗余 {@link DiscountActivityDO#getName()} + */ + private String activityName; /** * 活动状态 * - * 关联 {@link DiscountActivityDO#getStatus()} + * 冗余 {@link DiscountActivityDO#getStatus()} */ private Integer activityStatus; /** diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java index 72d604e77..08783bd34 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java @@ -6,14 +6,11 @@ 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.bargain.vo.activity.BargainActivityPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.time.LocalDateTime; -import java.util.Collection; import java.util.List; -import java.util.Map; /** * 砍价活动 Mapper @@ -86,35 +83,13 @@ public interface BargainActivityMapper extends BaseMapperX { .last("LIMIT " + count)); } - /** - * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 - * - * @param spuIds spu 编号 - * @param status 状态 - * @return 包含 spuId 和 activityId 的 map 对象列表 - */ - default List> selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(Collection spuIds, Integer status) { - return selectMaps(new QueryWrapper() - .select("spu_id AS spuId, MAX(DISTINCT(id)) AS activityId") // 时间越大 id 也越大 直接用 id - .in("spu_id", spuIds) - .eq("status", status) - .groupBy("spu_id")); - } - - /** - * 获取指定活动编号的活动列表且 - * 开始时间和结束时间小于给定时间 dateTime 的活动列表 - * - * @param ids 活动编号 - * @param dateTime 指定日期 - * @return 活动列表 - */ - default List selectListByIdsAndDateTimeLt(Collection ids, LocalDateTime dateTime) { - return selectList(new LambdaQueryWrapperX() - .in(BargainActivityDO::getId, ids) - .lt(BargainActivityDO::getStartTime, dateTime) - .gt(BargainActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动 - .orderByDesc(BargainActivityDO::getCreateTime)); + default BargainActivityDO selectBySpuIdAndStatusAndNow(Long spuId, Integer status) { + LocalDateTime now = LocalDateTime.now(); + return selectOne(new LambdaQueryWrapperX() + .eq(BargainActivityDO::getSpuId, spuId) + .eq(BargainActivityDO::getStatus, status) + .lt(BargainActivityDO::getStartTime, now) + .gt(BargainActivityDO::getEndTime, now)); // 开始时间 < now < 结束时间,也就是说获取指定时间段的活动 } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java index 55e975c45..df909a67c 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java @@ -6,14 +6,10 @@ 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.CombinationActivityPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; import java.time.LocalDateTime; -import java.util.Collection; import java.util.List; -import java.util.Map; /** * 拼团活动 Mapper @@ -39,40 +35,13 @@ public interface CombinationActivityMapper extends BaseMapperX selectListByStatus(Integer status, Integer count) { - return selectList(new LambdaQueryWrapperX() + default CombinationActivityDO selectBySpuIdAndStatusAndNow(Long spuId, Integer status) { + LocalDateTime now = LocalDateTime.now(); + return selectOne(new LambdaQueryWrapperX() + .eq(CombinationActivityDO::getSpuId, spuId) .eq(CombinationActivityDO::getStatus, status) - .last("LIMIT " + count)); + .lt(CombinationActivityDO::getStartTime, now) + .gt(CombinationActivityDO::getEndTime, now)); // 开始时间 < now < 结束时间,也就是说获取指定时间段的活动 } - /** - * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 - * @param spuIds spu 编号 - * @param status 状态 - * @return 包含 spuId 和 activityId 的 map 对象列表 - */ - default List> selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(@Param("spuIds") Collection spuIds, @Param("status") Integer status) { - return selectMaps(new QueryWrapper() - .select("spu_id AS spuId, MAX(DISTINCT(id)) AS activityId") // 时间越大 id 也越大 直接用 id - .in("spu_id", spuIds) - .eq("status", status) - .groupBy("spu_id")); - } - - /** - * 获取指定活动编号的活动列表且 - * 开始时间和结束时间小于给定时间 dateTime 的活动列表 - * - * @param ids 活动编号 - * @param dateTime 指定日期 - * @return 活动列表 - */ - default List selectListByIdsAndDateTimeLt(Collection ids, LocalDateTime dateTime) { - return selectList(new LambdaQueryWrapperX() - .in(CombinationActivityDO::getId, ids) - .lt(CombinationActivityDO::getStartTime, dateTime) - .gt(CombinationActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动 - .orderByDesc(CombinationActivityDO::getCreateTime)); - } - -} +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java index e5f1daf6c..ce89b0593 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java @@ -1,13 +1,11 @@ package cn.iocoder.yudao.module.promotion.dal.mysql.coupon; import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.StrUtil; 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.coupon.vo.coupon.CouponPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; -import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.github.yulichang.toolkit.MPJWrappers; import org.apache.ibatis.annotations.Mapper; @@ -16,8 +14,6 @@ import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; @@ -84,22 +80,6 @@ public interface CouponMapper extends BaseMapperX { return convertMap(list, map -> MapUtil.getLong(map, templateIdAlias), map -> MapUtil.getInt(map, countAlias)); } - default List selectListByUserIdAndStatusAndUsePriceLeAndProductScope( - Long userId, Integer status, Integer usePrice, List spuIds, List categoryIds) { - Function, String> productScopeValuesFindInSetFunc = ids -> ids.stream() - .map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id)) - .collect(Collectors.joining(" OR ")); - return selectList(new LambdaQueryWrapperX() - .eq(CouponDO::getUserId, userId) - .eq(CouponDO::getStatus, status) - .le(CouponDO::getUsePrice, usePrice) // 价格小于等于,满足价格使用条件 - .and(w -> w.eq(CouponDO::getProductScope, PromotionProductScopeEnum.ALL.getScope()) // 商品范围一:全部 - .or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.SPU.getScope()) // 商品范围二:满足指定商品 - .apply(productScopeValuesFindInSetFunc.apply(spuIds))) - .or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.CATEGORY.getScope()) // 商品范围三:满足指定分类 - .apply(productScopeValuesFindInSetFunc.apply(categoryIds))))); - } - default List selectListByStatusAndValidEndTimeLe(Integer status, LocalDateTime validEndTime) { return selectList(new LambdaQueryWrapperX() .eq(CouponDO::getStatus, status) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java index 50e3c0315..29b771126 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java @@ -70,7 +70,7 @@ public interface CouponTemplateMapper extends BaseMapperX { .in(CouponTemplateDO::getTakeType, canTakeTypes) // 2. 领取方式一致 .and(ww -> ww.gt(CouponTemplateDO::getValidEndTime, LocalDateTime.now()) // 3.1 未过期 .or().eq(CouponTemplateDO::getValidityType, CouponTemplateValidityTypeEnum.TERM.getType())) // 3.2 领取之后 - .apply(" (take_count < total_count OR total_count = -1 )"); // 4. 剩余数量大于 0,或者无限领取 + .apply(" (take_count < total_count OR total_count = -1)"); // 4. 剩余数量大于 0,或者无限领取 } return canTakeConsumer; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java index 5257b836d..f8fb0d0d6 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java @@ -1,11 +1,12 @@ package cn.iocoder.yudao.module.promotion.dal.mysql.discount; 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.discount.DiscountProductDO; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import java.util.Map; @@ -18,20 +19,22 @@ import java.util.Map; @Mapper public interface DiscountProductMapper extends BaseMapperX { - default List selectListBySkuId(Collection skuIds) { - return selectList(DiscountProductDO::getSkuId, skuIds); - } - default List selectListByActivityId(Long activityId) { return selectList(DiscountProductDO::getActivityId, activityId); } - default List selectListByActivityId(Collection activityIds) { - return selectList(DiscountProductDO::getActivityId, activityIds); + default List selectListBySkuIds(Collection skuIds) { + return selectList(DiscountProductDO::getSkuId, skuIds); } - // TODO @zhangshuai:逻辑里,尽量避免写 join 语句哈,你可以看看这个查询,有什么办法优化?目前的一个思路,是分 2 次查询,性能也是 ok 的 - List getMatchDiscountProductList(@Param("skuIds") Collection skuIds); + default List selectListBySkuIdsAndStatusAndNow(Collection skuIds, Integer status) { + LocalDateTime now = LocalDateTime.now(); + return selectList(new LambdaQueryWrapperX() + .in(DiscountProductDO::getSkuId, skuIds) + .eq(DiscountProductDO::getActivityStatus,status) + .lt(DiscountProductDO::getActivityStartTime, now) + .gt(DiscountProductDO::getActivityEndTime, now)); + } /** * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java index 6f377fb60..6d8e9c684 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java @@ -1,14 +1,19 @@ package cn.iocoder.yudao.module.promotion.dal.mysql.reward; +import cn.hutool.core.util.StrUtil; 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.reward.vo.RewardActivityPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import org.apache.ibatis.annotations.Mapper; import java.time.LocalDateTime; +import java.util.Collection; import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; /** * 满减送活动 Mapper @@ -25,12 +30,23 @@ public interface RewardActivityMapper extends BaseMapperX { .orderByDesc(RewardActivityDO::getId)); } - default List selectListByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime) { + default List selectListBySpuIdAndStatusAndNow(Collection spuIds, + Collection categoryIds, + Integer status) { + LocalDateTime now = LocalDateTime.now(); + Function, String> productScopeValuesFindInSetFunc = ids -> ids.stream() + .map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id)) + .collect(Collectors.joining(" OR ")); return selectList(new LambdaQueryWrapperX() .eq(RewardActivityDO::getStatus, status) - // 开始时间 < 指定时间(dateTime) < 结束时间,也就是说获取指定时间段的活动 - .lt(RewardActivityDO::getStartTime, dateTime).gt(RewardActivityDO::getEndTime, dateTime) - .orderByAsc(RewardActivityDO::getStartTime) + .lt(RewardActivityDO::getStartTime, now) + .gt(RewardActivityDO::getEndTime, now) + .and(i -> i.eq(RewardActivityDO::getProductScope, PromotionProductScopeEnum.SPU.getScope()) + .and(i1 -> i1.apply(productScopeValuesFindInSetFunc.apply(spuIds))) + .or(i1 -> i1.eq(RewardActivityDO::getProductScope, PromotionProductScopeEnum.ALL.getScope())) + .or(i1 -> i1.eq(RewardActivityDO::getProductScope, PromotionProductScopeEnum.CATEGORY.getScope()) + .and(i2 -> i2.apply(productScopeValuesFindInSetFunc.apply(categoryIds))))) + .orderByDesc(RewardActivityDO::getId) ); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java index 0b68609c9..51d3309b3 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java @@ -8,15 +8,11 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; import java.time.LocalDateTime; -import java.util.Collection; import java.util.List; -import java.util.Map; /** * 秒杀活动 Mapper @@ -51,7 +47,7 @@ public interface SeckillActivityMapper extends BaseMapperX { Assert.isTrue(count > 0); return update(null, new LambdaUpdateWrapper() .eq(SeckillActivityDO::getId, id) - .gt(SeckillActivityDO::getStock, count) + .ge(SeckillActivityDO::getStock, count) .setSql("stock = stock - " + count)); } @@ -69,41 +65,21 @@ public interface SeckillActivityMapper extends BaseMapperX { .setSql("stock = stock + " + count)); } - default PageResult selectPage(AppSeckillActivityPageReqVO pageReqVO, Integer status) { + default PageResult selectPage(AppSeckillActivityPageReqVO pageReqVO, Integer status, LocalDateTime dateTime) { return selectPage(pageReqVO, new LambdaQueryWrapperX() .eqIfPresent(SeckillActivityDO::getStatus, status) + .lt(SeckillActivityDO::getStartTime, dateTime) + .gt(SeckillActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动 .apply(ObjectUtil.isNotNull(pageReqVO.getConfigId()), "FIND_IN_SET(" + pageReqVO.getConfigId() + ",config_ids) > 0")); } - /** - * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 - * - * @param spuIds spu 编号 - * @param status 状态 - * @return 包含 spuId 和 activityId 的 map 对象列表 - */ - default List> selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(@Param("spuIds") Collection spuIds, @Param("status") Integer status) { - return selectMaps(new QueryWrapper() - .select("spu_id AS spuId, MAX(DISTINCT(id)) AS activityId") // 时间越大 id 也越大 直接用 id - .in("spu_id", spuIds) - .eq("status", status) - .groupBy("spu_id")); - } - - /** - * 获取指定活动编号的活动列表且 - * 开始时间和结束时间小于给定时间 dateTime 的活动列表 - * - * @param ids 活动编号 - * @param dateTime 指定日期 - * @return 活动列表 - */ - default List selectListByIdsAndDateTimeLt(Collection ids, LocalDateTime dateTime) { - return selectList(new LambdaQueryWrapperX() - .in(SeckillActivityDO::getId, ids) - .lt(SeckillActivityDO::getStartTime, dateTime) - .gt(SeckillActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动 - .orderByDesc(SeckillActivityDO::getCreateTime)); + default SeckillActivityDO selectBySpuIdAndStatusAndNow(Long spuId, Integer status) { + LocalDateTime now = LocalDateTime.now(); + return selectOne(new LambdaQueryWrapperX() + .eq(SeckillActivityDO::getSpuId, spuId) + .eq(SeckillActivityDO::getStatus, status) + .lt(SeckillActivityDO::getStartTime, now) + .gt(SeckillActivityDO::getEndTime, now)); // 开始时间 < now < 结束时间,也就是说获取指定时间段的活动 } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java index 789a3c520..73d13d597 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java @@ -6,10 +6,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.Ba import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.BargainActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.BargainActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; - import jakarta.validation.Valid; -import java.time.LocalDateTime; -import java.util.Collection; + import java.util.List; import java.util.Set; @@ -108,13 +106,11 @@ public interface BargainActivityService { List getBargainActivityListByCount(Integer count); /** - * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 + * 获得 SPU 进行中的砍价活动 * - * @param spuIds spu 编号 - * @param status 状态 - * @param dateTime 日期时间 - * @return 砍价活动列表 + * @param spuId SPU 编号数组 + * @return 砍价活动 */ - List getBargainActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime); + BargainActivityDO getMatchBargainActivityBySpuId(Long spuId); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java index f145fc665..165b0167e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java @@ -1,7 +1,5 @@ package cn.iocoder.yudao.module.promotion.service.bargain; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageParam; @@ -15,17 +13,17 @@ import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.Ba import cn.iocoder.yudao.module.promotion.convert.bargain.BargainActivityConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; import cn.iocoder.yudao.module.promotion.dal.mysql.bargain.BargainActivityMapper; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.time.LocalDateTime; -import java.util.*; +import java.util.List; +import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; @@ -194,15 +192,8 @@ public class BargainActivityServiceImpl implements BargainActivityService { } @Override - public List getBargainActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime) { - // 1. 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 - List> spuIdAndActivityIdMaps = bargainActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status); - if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) { - return Collections.emptyList(); - } - // 2. 查询活动详情 - return bargainActivityMapper.selectListByIdsAndDateTimeLt( - convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime); + public BargainActivityDO getMatchBargainActivityBySpuId(Long spuId) { + return bargainActivityMapper.selectBySpuIdAndStatusAndNow(spuId, CommonStatusEnum.ENABLE.getStatus()); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java index 8637a9607..759d6a589 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java @@ -7,9 +7,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activit import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; - import jakarta.validation.Valid; -import java.time.LocalDateTime; + import java.util.Collection; import java.util.Collections; import java.util.List; @@ -100,14 +99,6 @@ public interface CombinationActivityService { */ List getCombinationActivityListByIds(Collection ids); - /** - * 获取正在进行的活动分页数据 - * - * @param count 需要的数量 - * @return 拼团活动分页 - */ - List getCombinationActivityListByCount(Integer count); - /** * 获取正在进行的活动分页数据 * @@ -117,22 +108,20 @@ public interface CombinationActivityService { PageResult getCombinationActivityPage(PageParam pageParam); /** - * 获取指定活动、指定 sku 编号的商品 + * 获取指定活动、指定 SKU 编号的商品 * * @param activityId 活动编号 - * @param skuId sku 编号 + * @param skuId SKU 编号 * @return 活动商品信息 */ CombinationProductDO selectByActivityIdAndSkuId(Long activityId, Long skuId); /** - * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 + * 获得 SPU 进行中的拼团活动 * - * @param spuIds spu 编号 - * @param status 状态 - * @param dateTime 日期时间 - * @return 拼团活动列表 + * @param spuId SPU 编号数组 + * @return 拼团活动 */ - List getCombinationActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime); + CombinationActivityDO getMatchCombinationActivityBySpuId(Long spuId); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java index 6d51bde6c..8e168f4f9 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.promotion.service.combination; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageParam; @@ -20,19 +19,18 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationA import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; -import java.time.LocalDateTime; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; @@ -178,7 +176,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic combinationProductMapper.updateBatch(diffList.get(1)); } if (CollUtil.isNotEmpty(diffList.get(2))) { - combinationProductMapper.deleteBatchIds(CollectionUtils.convertList(diffList.get(2), CombinationProductDO::getId)); + combinationProductMapper.deleteByIds(CollectionUtils.convertList(diffList.get(2), CombinationProductDO::getId)); } } @@ -225,11 +223,6 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic return combinationActivityMapper.selectList(CombinationActivityDO::getId, ids); } - @Override - public List getCombinationActivityListByCount(Integer count) { - return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count); - } - @Override public PageResult getCombinationActivityPage(PageParam pageParam) { return combinationActivityMapper.selectPage(pageParam, CommonStatusEnum.ENABLE.getStatus()); @@ -243,15 +236,8 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic } @Override - public List getCombinationActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime) { - // 1.查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 - List> spuIdAndActivityIdMaps = combinationActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status); - if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) { - return Collections.emptyList(); - } - // 2.查询活动详情 - return combinationActivityMapper.selectListByIdsAndDateTimeLt( - convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime); + public CombinationActivityDO getMatchCombinationActivityBySpuId(Long spuId) { + return combinationActivityMapper.selectBySpuIdAndStatusAndNow(spuId, CommonStatusEnum.ENABLE.getStatus()); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java index 5fdcd0669..c24cf3ac9 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; @@ -18,26 +17,6 @@ import java.util.*; */ public interface CouponService { - /** - * 校验优惠劵,包括状态、有限期 - * - * 1. 如果校验通过,则返回优惠劵信息 - * 2. 如果校验不通过,则直接抛出业务异常 - * - * @param id 优惠劵编号 - * @param userId 用户编号 - * @return 优惠劵信息 - */ - CouponDO validCoupon(Long id, Long userId); - - /** - * 校验优惠劵,包括状态、有限期 - * - * @param coupon 优惠劵 - * @see #validCoupon(Long, Long) 逻辑相同,只是入参不同 - */ - void validCoupon(CouponDO coupon); - /** * 使用优惠劵 * @@ -171,15 +150,6 @@ public interface CouponService { return MapUtil.getInt(map, templateId, 0); } - /** - * 获取用户匹配的优惠券列表 - * - * @param userId 用户编号 - * @param matchReqVO 匹配参数 - * @return 优惠券列表 - */ - List getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO); - /** * 获取用户是否可以领取优惠券 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java index 3945aa06b..9ceb9507d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java @@ -12,7 +12,6 @@ import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; @@ -56,18 +55,9 @@ public class CouponServiceImpl implements CouponService { private MemberUserApi memberUserApi; @Override - public CouponDO validCoupon(Long id, Long userId) { - CouponDO coupon = couponMapper.selectByIdAndUserId(id, userId); - if (coupon == null) { - throw exception(COUPON_NOT_EXISTS); - } - validCoupon(coupon); - return coupon; - } - - @Override - public void validCoupon(CouponDO coupon) { + public void useCoupon(Long id, Long userId, Long orderId) { // 校验状态 + CouponDO coupon = couponMapper.selectByIdAndUserId(id, userId); if (ObjectUtil.notEqual(coupon.getStatus(), CouponStatusEnum.UNUSED.getStatus())) { throw exception(COUPON_STATUS_NOT_UNUSED); } @@ -75,12 +65,6 @@ public class CouponServiceImpl implements CouponService { if (!LocalDateTimeUtils.isBetween(coupon.getValidStartTime(), coupon.getValidEndTime())) { throw exception(COUPON_VALID_TIME_NOT_NOW); } - } - - @Override - public void useCoupon(Long id, Long userId, Long orderId) { - // 校验优惠劵 - validCoupon(id, userId); // 更新状态 int updateCount = couponMapper.updateByIdAndStatus(id, CouponStatusEnum.UNUSED.getStatus(), @@ -284,9 +268,8 @@ public class CouponServiceImpl implements CouponService { if (couponTemplate == null) { throw exception(COUPON_TEMPLATE_NOT_EXISTS); } - // 校验剩余数量(仅在 CouponTakeTypeEnum.USER 用户领取时) - if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeCount()) - && couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) { + // 校验剩余数量 + if (couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) { throw exception(COUPON_TEMPLATE_NOT_ENOUGH); } // 校验"固定日期"的有效期类型是否过期 @@ -355,16 +338,6 @@ public class CouponServiceImpl implements CouponService { return couponMapper.selectCountByUserIdAndTemplateIdIn(userId, templateIds); } - @Override - public List getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO) { - List list = couponMapper.selectListByUserIdAndStatusAndUsePriceLeAndProductScope(userId, - CouponStatusEnum.UNUSED.getStatus(), - matchReqVO.getPrice(), matchReqVO.getSpuIds(), matchReqVO.getCategoryIds()); - // 兜底逻辑:如果 CouponExpireJob 未执行,status 未变成 EXPIRE ,但是 validEndTime 已经过期了,需要进行过滤 - list.removeIf(coupon -> !LocalDateTimeUtils.isBetween(coupon.getValidStartTime(), coupon.getValidEndTime())); - return list; - } - @Override public Map getUserCanCanTakeMap(Long userId, List templates) { // 1. 未登录时,都显示可以领取 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java index 019c45dae..100f5541b 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java @@ -12,10 +12,10 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper; import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.util.Collection; import java.util.List; import java.util.Objects; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java index e08c7e2b5..a41b9b6ac 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java @@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivit import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; import jakarta.validation.Valid; -import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -27,7 +26,7 @@ public interface DiscountActivityService { * @param skuIds SKU 编号数组 * @return 匹配的限时折扣商品 */ - List getMatchDiscountProductList(Collection
- * 1. 如果校验通过,则返回优惠劵信息 - * 2. 如果校验不通过,则直接抛出业务异常 - * - * @param id 优惠劵编号 - * @param userId 用户编号 - * @return 优惠劵信息 - */ - CouponDO validCoupon(Long id, Long userId); - - /** - * 校验优惠劵,包括状态、有限期 - * - * @param coupon 优惠劵 - * @see #validCoupon(Long, Long) 逻辑相同,只是入参不同 - */ - void validCoupon(CouponDO coupon); - /** * 使用优惠劵 * @@ -171,15 +150,6 @@ public interface CouponService { return MapUtil.getInt(map, templateId, 0); } - /** - * 获取用户匹配的优惠券列表 - * - * @param userId 用户编号 - * @param matchReqVO 匹配参数 - * @return 优惠券列表 - */ - List getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO); - /** * 获取用户是否可以领取优惠券 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java index 3945aa06b..9ceb9507d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java @@ -12,7 +12,6 @@ import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; @@ -56,18 +55,9 @@ public class CouponServiceImpl implements CouponService { private MemberUserApi memberUserApi; @Override - public CouponDO validCoupon(Long id, Long userId) { - CouponDO coupon = couponMapper.selectByIdAndUserId(id, userId); - if (coupon == null) { - throw exception(COUPON_NOT_EXISTS); - } - validCoupon(coupon); - return coupon; - } - - @Override - public void validCoupon(CouponDO coupon) { + public void useCoupon(Long id, Long userId, Long orderId) { // 校验状态 + CouponDO coupon = couponMapper.selectByIdAndUserId(id, userId); if (ObjectUtil.notEqual(coupon.getStatus(), CouponStatusEnum.UNUSED.getStatus())) { throw exception(COUPON_STATUS_NOT_UNUSED); } @@ -75,12 +65,6 @@ public class CouponServiceImpl implements CouponService { if (!LocalDateTimeUtils.isBetween(coupon.getValidStartTime(), coupon.getValidEndTime())) { throw exception(COUPON_VALID_TIME_NOT_NOW); } - } - - @Override - public void useCoupon(Long id, Long userId, Long orderId) { - // 校验优惠劵 - validCoupon(id, userId); // 更新状态 int updateCount = couponMapper.updateByIdAndStatus(id, CouponStatusEnum.UNUSED.getStatus(), @@ -284,9 +268,8 @@ public class CouponServiceImpl implements CouponService { if (couponTemplate == null) { throw exception(COUPON_TEMPLATE_NOT_EXISTS); } - // 校验剩余数量(仅在 CouponTakeTypeEnum.USER 用户领取时) - if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeCount()) - && couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) { + // 校验剩余数量 + if (couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) { throw exception(COUPON_TEMPLATE_NOT_ENOUGH); } // 校验"固定日期"的有效期类型是否过期 @@ -355,16 +338,6 @@ public class CouponServiceImpl implements CouponService { return couponMapper.selectCountByUserIdAndTemplateIdIn(userId, templateIds); } - @Override - public List getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO) { - List list = couponMapper.selectListByUserIdAndStatusAndUsePriceLeAndProductScope(userId, - CouponStatusEnum.UNUSED.getStatus(), - matchReqVO.getPrice(), matchReqVO.getSpuIds(), matchReqVO.getCategoryIds()); - // 兜底逻辑:如果 CouponExpireJob 未执行,status 未变成 EXPIRE ,但是 validEndTime 已经过期了,需要进行过滤 - list.removeIf(coupon -> !LocalDateTimeUtils.isBetween(coupon.getValidStartTime(), coupon.getValidEndTime())); - return list; - } - @Override public Map getUserCanCanTakeMap(Long userId, List templates) { // 1. 未登录时,都显示可以领取 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java index 019c45dae..100f5541b 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java @@ -12,10 +12,10 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper; import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.util.Collection; import java.util.List; import java.util.Objects; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java index e08c7e2b5..a41b9b6ac 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java @@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivit import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; import jakarta.validation.Valid; -import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -27,7 +26,7 @@ public interface DiscountActivityService { * @param skuIds SKU 编号数组 * @return 匹配的限时折扣商品 */ - List getMatchDiscountProductList(Collection