From b9e7481bdf6161e90093a4534c9466192c46f3ab Mon Sep 17 00:00:00 2001 From: lym <1994302445@qq.com> Date: Tue, 13 May 2025 11:36:20 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B5=84=E9=87=91=E7=AE=A1=E7=90=86=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChenfengRabbitMQAutoConfiguration.java | 43 ++- .../rabbitmq/constant/RabbitMqConstants.java | 16 ++ .../api/advertisement/AdvertisementApi.java | 26 ++ .../system/enums/DictTypeConstants.java | 4 + .../system/enums/ErrorCodeConstants.java | 19 ++ .../AdvertisementStatusEnum.java | 64 +++++ .../advertisement/MessageStatusEnum.java | 52 ++++ .../enums/products/DurationUnitEnum.java | 51 ++++ .../enums/products/ProductStatusEnum.java | 51 ++++ .../products/ProductsPurchaseTypeEnum.java | 46 ++++ .../enums/recharge/PurchaseTypeEnum.java | 46 ++++ .../enums/recharge/RechargeTypeEnum.java | 50 ++++ .../AdvertisementController.java | 106 ++++++++ .../vo/AdvertisementPageReqVO.java | 65 +++++ .../advertisement/vo/AdvertisementRespVO.java | 41 +++ .../vo/AdvertisementSaveReqVO.java | 57 ++++ .../admin/products/ProductsController.java | 94 +++++++ .../products/ProductsDetailController.java | 74 +++++ .../products/vo/product/ProductPageReqVO.java | 41 +++ .../products/vo/product/ProductRespVO.java | 37 +++ .../products/vo/product/ProductSaveReqVO.java | 26 ++ .../ProductDetailsPageReqVO.java | 63 +++++ .../productDetails/ProductDetailsRespVO.java | 57 ++++ .../ProductDetailsSaveReqVO.java | 52 ++++ .../recharge/RechargeActiveController.java | 74 +++++ .../admin/recharge/vo/RechargePageReqVO.java | 67 +++++ .../admin/recharge/vo/RechargeRespVO.java | 53 ++++ .../admin/recharge/vo/RechargeSaveReqVO.java | 67 +++++ .../advertisement/AdvertisementDO.java | 73 +++++ .../advertisement/AdvertisementTaskDO.java | 50 ++++ .../dal/dataobject/products/ProductsDO.java | 45 ++++ .../dataobject/products/ProductsDetailDO.java | 83 ++++++ .../recharge/GiftMoneyDetailsDO.java | 66 +++++ .../advertisement/AdvertisementMapper.java | 73 +++++ .../AdvertisementTaskMapper.java | 45 ++++ .../mysql/products/ProductsDetailMapper.java | 57 ++++ .../dal/mysql/products/ProductsMapper.java | 26 ++ .../recharge/GiftMoneyDetailsMapper.java | 59 ++++ .../AdvertisementSendConsumer.java | 71 +++++ .../AdvertisementSendMessage.java | 35 +++ .../advertisement/AdvertisementProducer.java | 82 ++++++ .../AdvertisementCompensateTask.java | 116 ++++++++ .../advertisement/AdvertisementService.java | 56 ++++ .../AdvertisementServiceImpl.java | 251 +++++++++++++++++ .../products/ProductsDetailService.java | 54 ++++ .../products/ProductsDetailServiceImpl.java | 253 ++++++++++++++++++ .../service/products/ProductsService.java | 52 ++++ .../service/products/ProductsServiceImpl.java | 86 ++++++ .../recharge/RechargeActiveService.java | 53 ++++ .../recharge/RechargeActiveServiceImpl.java | 75 ++++++ .../system/util/SnowflakeIdWorker3rd.java | 63 +++++ .../advertisement/AdvertisementStatus.java | 28 ++ .../AdvertisementStatusValidator.java | 31 +++ .../validation/products/ProductStatus.java | 27 ++ .../products/ProductStatusValidator.java | 27 ++ .../validation/products/ProductType.java | 25 ++ .../products/ProductTypeValidator.java | 28 ++ .../validation/recharge/MoneyValid.java | 58 ++++ .../validation/recharge/MoneyValidator.java | 87 ++++++ .../validation/recharge/PurchaseType.java | 26 ++ .../recharge/PurchaseTypeValidator.java | 27 ++ .../validation/recharge/RechargeType.java | 26 ++ .../recharge/RechargeTypeValidator.java | 26 ++ .../src/main/resources/application.yaml | 5 + 64 files changed, 3678 insertions(+), 9 deletions(-) create mode 100644 cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/advertisement/AdvertisementApi.java create mode 100644 cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/advertisement/AdvertisementStatusEnum.java create mode 100644 cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/advertisement/MessageStatusEnum.java create mode 100644 cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/DurationUnitEnum.java create mode 100644 cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/ProductStatusEnum.java create mode 100644 cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/ProductsPurchaseTypeEnum.java create mode 100644 cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/recharge/PurchaseTypeEnum.java create mode 100644 cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/recharge/RechargeTypeEnum.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/AdvertisementController.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementPageReqVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementRespVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementSaveReqVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/ProductsController.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/ProductsDetailController.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductPageReqVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductRespVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductSaveReqVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsPageReqVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsRespVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsSaveReqVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/RechargeActiveController.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargePageReqVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargeRespVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargeSaveReqVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/advertisement/AdvertisementDO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/advertisement/AdvertisementTaskDO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/products/ProductsDO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/products/ProductsDetailDO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/recharge/GiftMoneyDetailsDO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/advertisement/AdvertisementMapper.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/advertisement/AdvertisementTaskMapper.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/products/ProductsDetailMapper.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/products/ProductsMapper.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/recharge/GiftMoneyDetailsMapper.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/consumer/advertisement/AdvertisementSendConsumer.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/advertisement/AdvertisementSendMessage.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/advertisement/AdvertisementProducer.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementCompensateTask.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementService.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementServiceImpl.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsDetailService.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsDetailServiceImpl.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsService.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsServiceImpl.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/recharge/RechargeActiveService.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/recharge/RechargeActiveServiceImpl.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/util/SnowflakeIdWorker3rd.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/advertisement/AdvertisementStatus.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/advertisement/AdvertisementStatusValidator.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductStatus.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductStatusValidator.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductType.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductTypeValidator.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/MoneyValid.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/MoneyValidator.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/PurchaseType.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/PurchaseTypeValidator.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/RechargeType.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/RechargeTypeValidator.java diff --git a/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/config/ChenfengRabbitMQAutoConfiguration.java b/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/config/ChenfengRabbitMQAutoConfiguration.java index 4ba13acca..1d1f2b360 100644 --- a/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/config/ChenfengRabbitMQAutoConfiguration.java +++ b/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/config/ChenfengRabbitMQAutoConfiguration.java @@ -2,14 +2,10 @@ package com.cf.imes.framework.mq.rabbitmq.config; import com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants; import lombok.extern.slf4j.Slf4j; -import org.springframework.amqp.core.Binding; -import org.springframework.amqp.core.BindingBuilder; -import org.springframework.amqp.core.DirectExchange; -import org.springframework.amqp.core.FanoutExchange; -import org.springframework.amqp.core.Queue; -import org.springframework.amqp.core.QueueBuilder; +import org.springframework.amqp.core.*; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; @@ -17,9 +13,7 @@ import org.springframework.context.annotation.Bean; import java.util.HashMap; import java.util.Map; -import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.ORDER_IMPORT_DEAD_LETTER_EXCHANGE; -import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.ORDER_IMPORT_DEAD_LETTER_QUEUE; -import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.ORDER_IMPORT_DEAD_LETTER_ROUTING_KEY; +import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.*; /** * RabbitMQ 消息队列配置类 @@ -139,4 +133,35 @@ public class ChenfengRabbitMQAutoConfiguration { return BindingBuilder.bind(orderImportDeadLetterQueue()).to(orderImportDeadLetterExchange()).with(ORDER_IMPORT_DEAD_LETTER_ROUTING_KEY); } + + /** + * 广告状态修改 延迟队列 + */ + @Bean + public Queue advertisementUpdateDelayedQueue(){ + return QueueBuilder.durable(SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_QUEUE).build(); + } + + /** + * 广告状态修改 定义延迟交换机 + */ + @Bean + public CustomExchange advertisementUpdateDelayExchange() { + Map args = new HashMap<>(); + args.put("x-delayed-type", "direct"); + return new CustomExchange(SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_EXCHANGE, "x-delayed-message", true, false, args); + } + + /** + * 广告状态修改 队列与交换机绑定 + */ + @Bean + public Binding advertisementUpdateQueueABindingX(@Qualifier("advertisementUpdateDelayedQueue") Queue queue, + @Qualifier("advertisementUpdateDelayExchange") CustomExchange delayedExchange){ + return BindingBuilder.bind(queue) + .to(delayedExchange) + .with(SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_ROUTING_KEY) + .noargs(); + } + } diff --git a/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/constant/RabbitMqConstants.java b/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/constant/RabbitMqConstants.java index 553315086..91c711a61 100644 --- a/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/constant/RabbitMqConstants.java +++ b/cf-framework/cf-spring-boot-starter-mq/src/main/java/com/cf/imes/framework/mq/rabbitmq/constant/RabbitMqConstants.java @@ -41,4 +41,20 @@ public class RabbitMqConstants { * 生产单导入死信路由键 */ public static final String ORDER_IMPORT_DEAD_LETTER_ROUTING_KEY = "order_import_dead_letter_routing_key"; + + /** + * 广告状态修改 延迟队列 + */ + public static final String SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_QUEUE = "system_advertisement_update_delayed_queue"; + + /** + * 广告状态修改 延迟交换机 + */ + public static final String SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_EXCHANGE = "system_advertisement_update_delayed_exchange"; + + /** + * 广告状态修改 延迟路由键 + */ + public static final String SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_ROUTING_KEY = "system_advertisement_update_delayed_routing_key"; + } diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/advertisement/AdvertisementApi.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/advertisement/AdvertisementApi.java new file mode 100644 index 000000000..d30c99b9b --- /dev/null +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/advertisement/AdvertisementApi.java @@ -0,0 +1,26 @@ +package com.cf.imes.module.system.api.advertisement; + +import com.cf.imes.module.system.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient(name = ApiConstants.NAME) // TODO 晨丰:fallbackFactory = +@Tag(name = "RPC 服务 - 广告管理") +public interface AdvertisementApi { + + String PREFIX = ApiConstants.PREFIX + "/ad"; + + @GetMapping(PREFIX + "/published") + @Operation(summary = "结束发布广告") + @Parameter(name = "id", description = "广告id", required = true) + Boolean published(@RequestParam("id") Long id) ; + + @GetMapping(PREFIX + "/publishing") + @Operation(summary = "立即发布广告") + @Parameter(name = "id", description = "广告id", required = true) + Boolean publishing(@RequestParam("id") Long id) ; +} diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/DictTypeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/DictTypeConstants.java index 47c79a9f2..10cde325c 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/DictTypeConstants.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/DictTypeConstants.java @@ -29,4 +29,8 @@ public class DictTypeConstants { public static final String PLATE_TEXTURE_TYPE = "plate_texture_type";// 板材纹路:0有 1无 + + + public static final String ADVERTISEMENT_POSITION = "advertisement_position"; + } diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java index 4da378b3c..be6c6405c 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java @@ -422,5 +422,24 @@ public class ErrorCodeConstants { public static final ErrorCode INVOICE_FILE_DATA_ERROR = new ErrorCode(1_002_043_007, "发票附件下载失败,请重新下载或稍等重试"); + public static final ErrorCode PRODUCTS_NO_EXIST = new ErrorCode(1_002_044_001, "当前产品不存在"); + public static final ErrorCode PRODUCTS_DETAIL_NO_EXIST = new ErrorCode(1_002_044_002, "当前产品的规则不存在"); + public static final ErrorCode PRODUCTS_DURATION_NOT_NULL = new ErrorCode(1_002_044_003, "购买方式为时长时,需确定产品时长"); + public static final ErrorCode PRODUCTS_OUTPUT_NOT_NULL = new ErrorCode(1_002_044_004, "购买方式为产量时,需确定产量数量"); + public static final ErrorCode PRODUCTS_DETAIL_DURATION_EXIST = new ErrorCode(1_002_044_005, "存在当前时长的产品定价规则"); + public static final ErrorCode PRODUCTS_DETAIL_OUTPUT_EXIST = new ErrorCode(1_002_044_006, "存在当前产量的产品定价规则"); + public static final ErrorCode PRODUCTS_DURATION_NUM_ERR = new ErrorCode(1_002_044_007, "产品定价规则,时长数据设置有误"); + public static final ErrorCode PRODUCTS_DURATION_INT_ERR = new ErrorCode(1_002_044_008, "产品定价规则,时长数据为正整数"); + public static final ErrorCode PRODUCTS_DURATION_UNIT_ERR = new ErrorCode(1_002_044_009, "产品定价规则,时长单位设置有误"); + + public static final ErrorCode ADVERTISEMENT_POSITION_NO_EXIST = new ErrorCode(1_003_001_001, "广告所选放置位置不存在"); + public static final ErrorCode ADVERTISEMENT_NO_EXIST = new ErrorCode(1_003_001_002, "广告不存在"); + public static final ErrorCode ADVERTISEMENT_STATUS_ERROR = new ErrorCode(1_003_001_003, "当前广告已经发布,无需立即发布"); + public static final ErrorCode ADVERTISEMENT_STATUS_ERROR2 = new ErrorCode(1_003_001_004, "当前广告已过结束时间,请点击重新发布"); + public static final ErrorCode ADVERTISEMENT_END_ERROR = new ErrorCode(1_003_001_005, "当前广告未发布,无需结束发布"); + public static final ErrorCode ADVERTISEMENT_END_ERROR2 = new ErrorCode(1_003_001_006, "当前广告已结束,无需立即结束"); + public static final ErrorCode ADVERTISEMENT_FAIL = new ErrorCode(1_003_001_007, "自动发布失败"); + + public static final ErrorCode RECHARGE_ACTIVE_NO_EXIST = new ErrorCode(1_004_001_001, "当前赠送金活动不存在"); } diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/advertisement/AdvertisementStatusEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/advertisement/AdvertisementStatusEnum.java new file mode 100644 index 000000000..3a8727b65 --- /dev/null +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/advertisement/AdvertisementStatusEnum.java @@ -0,0 +1,64 @@ +package com.cf.imes.module.system.enums.advertisement; + +import com.cf.imes.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Objects; + +/** + * 广告状态单位态枚举 + * + * @author 晨丰科技 + */ +@Getter +@AllArgsConstructor +public enum AdvertisementStatusEnum implements IntArrayValuable { + + ALL(0, "全部"), + UNPUBLISHED(1, "未发布"), + PUBLISHED(2, "已发布"), + ENDED(3, "已结束"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AdvertisementStatusEnum::getStatus).toArray(); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + + public static boolean isAll(String name) { + return Objects.equals(ALL.name, name); + } + + public static boolean isUnpublished(String name) { + return Objects.equals(UNPUBLISHED.name, name); + } + + public static boolean isPublished(String name) { + return Objects.equals(PUBLISHED.name, name); + } + + public static boolean isEnded(String name) { + return Objects.equals(ENDED.name, name); + } + + public static Integer getNameByStatus(String name) { + for (AdvertisementStatusEnum e : values()) { + if (e.getName().equals(name)) { + return e.getStatus(); + } + } + return null; + } +} diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/advertisement/MessageStatusEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/advertisement/MessageStatusEnum.java new file mode 100644 index 000000000..1efa568f2 --- /dev/null +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/advertisement/MessageStatusEnum.java @@ -0,0 +1,52 @@ +package com.cf.imes.module.system.enums.advertisement; + +import com.cf.imes.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Objects; + +/** + * 延迟消息状态单位态枚举 + * + * @author 晨丰科技 + */ +@Getter +@AllArgsConstructor +public enum MessageStatusEnum implements IntArrayValuable { + + PENDING(0, "待处理"), + PROCESSED(1, "已处理"), + CANCELLED(2, "已取消"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MessageStatusEnum::getStatus).toArray(); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + + public static boolean isPending(String name) { + return Objects.equals(PENDING.name, name); + } + + public static boolean isProcessed(String name) { + return Objects.equals(PROCESSED.name, name); + } + + public static boolean isCancelled(String name) { + return Objects.equals(CANCELLED.name, name); + } + + +} diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/DurationUnitEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/DurationUnitEnum.java new file mode 100644 index 000000000..b1e735437 --- /dev/null +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/DurationUnitEnum.java @@ -0,0 +1,51 @@ +package com.cf.imes.module.system.enums.products; + +import com.cf.imes.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Objects; + +/** + * 时长单位态枚举 + * + * @author 晨丰科技 + */ +@Getter +@AllArgsConstructor +public enum DurationUnitEnum implements IntArrayValuable { + + YEAR(0, "year"), + MONTH(1, "month"), + DAY(2, "day"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DurationUnitEnum::getStatus).toArray(); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + + public static boolean isYear(String name) { + return Objects.equals(YEAR.name, name); + } + + public static boolean isMonth(String name) { + return Objects.equals(MONTH.name, name); + } + + public static boolean isDay(String name) { + return Objects.equals(DAY.name, name); + } + +} diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/ProductStatusEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/ProductStatusEnum.java new file mode 100644 index 000000000..015314964 --- /dev/null +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/ProductStatusEnum.java @@ -0,0 +1,51 @@ +package com.cf.imes.module.system.enums.products; + +import com.cf.imes.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Objects; + +/** + * 产品状态枚举 + * + * @author 晨丰科技 + */ +@Getter +@AllArgsConstructor +public enum ProductStatusEnum implements IntArrayValuable { + + PRODUCT_ALL(0, "全部"), + PRODUCT_WAITING_UPDATES(1, "待上架"), + PRODUCT_UPDATES(2, "已上架"), + PRODUCT_DELIS(3, "已下架"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductStatusEnum::getStatus).toArray(); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + + public static boolean isProductWaitingUpdates(Integer status) { + return Objects.equals(PRODUCT_WAITING_UPDATES.status, status); + } + + public static boolean isProductUpdates(Integer status) { + return Objects.equals(PRODUCT_UPDATES.status, status); + } + + public static boolean isProductDelis(Integer status) { + return Objects.equals(PRODUCT_DELIS.status, status); + } +} diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/ProductsPurchaseTypeEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/ProductsPurchaseTypeEnum.java new file mode 100644 index 000000000..0b5805e44 --- /dev/null +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/products/ProductsPurchaseTypeEnum.java @@ -0,0 +1,46 @@ +package com.cf.imes.module.system.enums.products; + +import com.cf.imes.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Objects; + +/** + * 产品详情购买方式状态枚举 + * + * @author 晨丰科技 + */ +@Getter +@AllArgsConstructor +public enum ProductsPurchaseTypeEnum implements IntArrayValuable { + + DURATION(0, "时长"), + OUTPUT(1, "产量"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductsPurchaseTypeEnum::getStatus).toArray(); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + + public static boolean isDURATION(Integer status) { + return Objects.equals(DURATION.status, status); + } + + public static boolean isOUTPUT(Integer status) { + return Objects.equals(OUTPUT.status, status); + } +} + diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/recharge/PurchaseTypeEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/recharge/PurchaseTypeEnum.java new file mode 100644 index 000000000..5cb61cd6e --- /dev/null +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/recharge/PurchaseTypeEnum.java @@ -0,0 +1,46 @@ +package com.cf.imes.module.system.enums.recharge; + +import com.cf.imes.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Objects; + +/** + * 充值赠送类型枚举 + * + * @author 晨丰科技 + */ +@Getter +@AllArgsConstructor +public enum PurchaseTypeEnum implements IntArrayValuable { + + ONE(0, "满X送X"), + TWO(1, "每满X送X"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PurchaseTypeEnum::getStatus).toArray(); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + + public static boolean isOne(String name) { + return Objects.equals(ONE.name, name); + } + + public static boolean isTwo(String name) { + return Objects.equals(TWO.name, name); + } + +} diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/recharge/RechargeTypeEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/recharge/RechargeTypeEnum.java new file mode 100644 index 000000000..e05728a4c --- /dev/null +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/recharge/RechargeTypeEnum.java @@ -0,0 +1,50 @@ +package com.cf.imes.module.system.enums.recharge; + +import com.cf.imes.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Objects; + +/** + * 充值类型枚举 + * + * @author 晨丰科技 + */ +@Getter +@AllArgsConstructor +public enum RechargeTypeEnum implements IntArrayValuable { + + ONE(0, "微信、支付宝"), + TWO(1, "微信"), + THREE(2, "支付宝"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(RechargeTypeEnum::getStatus).toArray(); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + + public static boolean isOne(String name) { + return Objects.equals(ONE.name, name); + } + + public static boolean isTwo(String name) { + return Objects.equals(TWO.name, name); + } + + public static boolean isThree(String name) { + return Objects.equals(THREE.name, name); + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/AdvertisementController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/AdvertisementController.java new file mode 100644 index 000000000..cc12b33c0 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/AdvertisementController.java @@ -0,0 +1,106 @@ +package com.cf.imes.module.system.controller.admin.advertisement; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.module.system.controller.admin.advertisement.vo.AdvertisementPageReqVO; +import com.cf.imes.module.system.controller.admin.advertisement.vo.AdvertisementRespVO; +import com.cf.imes.module.system.controller.admin.advertisement.vo.AdvertisementSaveReqVO; +import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementDO; +import com.cf.imes.module.system.enums.advertisement.AdvertisementStatusEnum; +import com.cf.imes.module.system.service.advertisement.AdvertisementService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static com.cf.imes.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 广告管理") +@RestController +@RequestMapping("/system/ad") +@Validated +@Slf4j +public class AdvertisementController { + + @Resource + private AdvertisementService advertisementService; + + @PostMapping("/create") + @Operation(summary = "新建广告") + @PreAuthorize("@ss.hasPermission('base:advertisement:create')") + public CommonResult createAdvertisement(@Valid @RequestBody AdvertisementSaveReqVO createReqVO) { + return success(advertisementService.create(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新广告") + @PreAuthorize("@ss.hasPermission('base:advertisement:update')") + public CommonResult updateAdvertisement(@Valid @RequestBody AdvertisementSaveReqVO updateReqVO) { + AdvertisementDO productsDO = BeanUtils.toBean(updateReqVO, AdvertisementDO.class); + advertisementService.update(productsDO, 0); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除广告") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('base:advertisement:delete')") + public CommonResult deleteAdvertisement(@RequestParam("id") Long id) { + advertisementService.delete(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得广告") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('base:advertisement:query')") + public CommonResult getAdvertisement(@RequestParam("id") Long id) { + AdvertisementDO productRespVO = advertisementService.get(id); + return success(BeanUtils.toBean(productRespVO, AdvertisementRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得广告分页") + @PreAuthorize("@ss.hasPermission('base:advertisement:query')") + public CommonResult> getAdvertisementPage(@Valid AdvertisementPageReqVO pageReqVO) { + PageResult pageResult = advertisementService.getPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, AdvertisementSaveReqVO.class)); + } + + @PutMapping("/published") + @Operation(summary = "结束发布广告") + @Parameter(name = "id", description = "广告id", required = true) + @PreAuthorize("@ss.hasPermission('base:advertisement:update')") + public CommonResult published(@RequestParam("id") Long id) { + advertisementService.update(id, AdvertisementStatusEnum.ENDED.getStatus()); + return success(true); + } + + @PutMapping("/publishing") + @Operation(summary = "立即发布广告") + @PreAuthorize("@ss.hasPermission('base:advertisement:update')") + @Parameter(name = "id", description = "广告id", required = true) + public CommonResult publishing(@RequestParam("id") Long id) { + advertisementService.update(id,AdvertisementStatusEnum.PUBLISHED.getStatus()); + return success(true); + } + + @PutMapping("/republish") + @Operation(summary = "重新发布广告") + @Parameter(name = "id", description = "广告id", required = true) + @PreAuthorize("@ss.hasPermission('base:advertisement:update')") + public CommonResult republish(@Valid @RequestBody AdvertisementSaveReqVO updateReqVO) { + AdvertisementDO productsDO = BeanUtils.toBean(updateReqVO, AdvertisementDO.class); + advertisementService.update(productsDO, 1); + return success(true); + } + + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementPageReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementPageReqVO.java new file mode 100644 index 000000000..57dbe1e29 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementPageReqVO.java @@ -0,0 +1,65 @@ +package com.cf.imes.module.system.controller.admin.advertisement.vo; + +import com.cf.imes.framework.common.pojo.PageParam; +import com.cf.imes.module.system.validation.advertisement.AdvertisementStatus; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 广告分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AdvertisementPageReqVO extends PageParam { + + @Schema(description = "广告id", example = "163681486581530624") + private Long id; + + @Schema(description = "广告名称", example = "西亚哈") + private String adName; + + @Schema(description = "软件标识", example = "163681481946824704") + private String softwareId; + + @Schema(description = "广告位置") + private String adPosition; + + @Schema(description = "广告图片") + private String adImagePath; + + @Schema(description = "投放开始时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] startTime; + + @Schema(description = "投放结束时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] endTime; + + @Schema(description = "跳转路径") + private String adRedirectUrl; + + @Schema(description = "广告顺序") + private Short sort; + + @Schema(description = "广告状态", example = "0全部 1未发布 2已发布 3已结束") + @AdvertisementStatus + private Integer status; + + @Schema(description = "操作人") + private String updater; + + @Schema(description = "操作时间") + private LocalDateTime updateTime; + + @Schema(description = "排序", example = "ascend") + private String order; + + @Schema(description = "排序字段", example = "id") + private String field; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementRespVO.java new file mode 100644 index 000000000..b1fd54001 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementRespVO.java @@ -0,0 +1,41 @@ +package com.cf.imes.module.system.controller.admin.advertisement.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 广告管理 Response VO") +@Data +@ExcelIgnoreUnannotated +public class AdvertisementRespVO { + + @Schema(description = "广告id", requiredMode = Schema.RequiredMode.REQUIRED, example = "163681486581530624") + private int id; + + @Schema(description = "广告名称", example = "西亚哈") + private String adName; + + @Schema(description = "广告位置") + private String adPosition; + + @Schema(description = "图片路径") + private String adImagePath; + + @Schema(description = "投放开始时间") + private LocalDateTime startTime; + + @Schema(description = "投放结束时间") + private LocalDateTime endTime; + + @Schema(description = "跳转路径") + private String adRedirectUrl; + + @Schema(description = "广告顺序") + private Short sort; + + @Schema(description = "广告状态", example = "0全部 1未发布 2已发布 3已结束") + private Integer status; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementSaveReqVO.java new file mode 100644 index 000000000..4397d595c --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/advertisement/vo/AdvertisementSaveReqVO.java @@ -0,0 +1,57 @@ +package com.cf.imes.module.system.controller.admin.advertisement.vo; + +import com.cf.imes.framework.common.validation.NumberValid; +import com.cf.imes.module.system.validation.advertisement.AdvertisementStatus; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 广告新增/修改 Request VO") +@Data +public class AdvertisementSaveReqVO { + + @Schema(description = "广告id", example = "1") + private Long id; + + @Schema(description = "广告名称", example = "西亚哈") + @NotBlank(message = "广告名称不能为空") + @Size(max = 32, message = "广告名称长度不能超过 32 个字符") + private String adName; + + @Schema(description = "软件标识", example = "163681481946824704") + private String softwareId; + + @Schema(description = "广告位置,字典键值", example = "[1,2]") + @NotNull(message = "广告位置不能为空") + private Integer[] adPosition; + + @Schema(description = "广告图片") + @NotBlank(message = "广告图片不能为空") + @Size(max = 255, message = "广告图片长度不能超过 255 个字符") + private String adImagePath; + + @Schema(description = "投放开始时间") + @NotNull(message = "投放开始时间不能为空") + private LocalDateTime startTime; + + @Schema(description = "投放结束时间") + @NotNull(message = "投放结束时间不能为空") + private LocalDateTime endTime; + + @Schema(description = "跳转路径") + @Size(max = 255, message = "链接长度不能超过 255 个字符") + private String adRedirectUrl; + + @Schema(description = "广告顺序") + @NumberValid(name = "广告顺序") + private Integer sort; + + @Schema(description = "广告状态", example = "0全部 1未发布 2已发布 3已结束") + @AdvertisementStatus + private Integer status; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/ProductsController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/ProductsController.java new file mode 100644 index 000000000..ce20ec4c0 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/ProductsController.java @@ -0,0 +1,94 @@ +package com.cf.imes.module.system.controller.admin.products; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.module.system.controller.admin.products.vo.product.ProductPageReqVO; +import com.cf.imes.module.system.controller.admin.products.vo.product.ProductRespVO; +import com.cf.imes.module.system.controller.admin.products.vo.product.ProductSaveReqVO; +import com.cf.imes.module.system.dal.dataobject.products.ProductsDO; +import com.cf.imes.module.system.service.products.ProductsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static com.cf.imes.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 产品管理") +@RestController +@RequestMapping("/system/products") +@Validated +public class ProductsController { + + + @Resource + private ProductsService productsService; + + @PostMapping("/create") + @Operation(summary = "新建产品") +// @PreAuthorize("@ss.hasPermission('base:products:create')") + public CommonResult createProducts(@RequestParam("productName") String productName) { + return success(productsService.create(productName)); + } + + @PutMapping("/update") + @Operation(summary = "更新产品") +// @PreAuthorize("@ss.hasPermission('base:products:update')") + public CommonResult updateProducts(@Valid @RequestBody ProductSaveReqVO updateReqVO) { + ProductsDO productsDO = BeanUtils.toBean(updateReqVO, ProductsDO.class); + productsService.update(productsDO); + return success(true); + } + + @PutMapping("/freeze") + @Operation(summary = "下架产品") +// @PreAuthorize("@ss.hasPermission('base:products:freeze')") + public CommonResult freezeProducts(@Valid Long id) { + ProductsDO productsDO = new ProductsDO().setId(id).setStatus(3); + productsService.update(productsDO); + return success(true); + } + + @PutMapping("/melt") + @Operation(summary = "上架产品") + @PreAuthorize("@ss.hasPermission('base:products:melt')") + public CommonResult meltProducts(@Valid Long id) { + ProductsDO productsDO = new ProductsDO().setId(id).setStatus(2); + productsService.update(productsDO); + return success(true); + } + + + @DeleteMapping("/delete") + @Operation(summary = "删除产品") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('base:products:delete')") + public CommonResult deleteProducts(@RequestParam("id") Long id) { + productsService.delete(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('base:products:query')") + public CommonResult getProducts(@RequestParam("id") Long id) { + ProductsDO productRespVO = productsService.get(id); + return success(BeanUtils.toBean(productRespVO, ProductRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品分页") + @PreAuthorize("@ss.hasPermission('base:products:query')") + public CommonResult> getProductsPage(@Valid ProductPageReqVO pageReqVO) { + PageResult pageResult = productsService.getPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ProductRespVO.class)); + } + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/ProductsDetailController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/ProductsDetailController.java new file mode 100644 index 000000000..1817a7c82 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/ProductsDetailController.java @@ -0,0 +1,74 @@ +package com.cf.imes.module.system.controller.admin.products; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.module.system.controller.admin.products.vo.productDetails.ProductDetailsPageReqVO; +import com.cf.imes.module.system.controller.admin.products.vo.productDetails.ProductDetailsRespVO; +import com.cf.imes.module.system.controller.admin.products.vo.productDetails.ProductDetailsSaveReqVO; +import com.cf.imes.module.system.dal.dataobject.products.ProductsDetailDO; +import com.cf.imes.module.system.service.products.ProductsDetailService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static com.cf.imes.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 产品明细管理") +@RestController +@RequestMapping("/system/product-details") +@Validated +public class ProductsDetailController { + + @Resource + private ProductsDetailService productDetailsService; + + @PostMapping("/create") + @Operation(summary = "新建产品明细") + @PreAuthorize("@ss.hasPermission('base:productDetails:create')") + public CommonResult createProducts(@Valid @RequestBody ProductDetailsSaveReqVO createReqVO) { + return success(productDetailsService.create(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新产品明细") + @PreAuthorize("@ss.hasPermission('base:productDetails:update')") + public CommonResult updateProducts(@Valid @RequestBody ProductDetailsSaveReqVO updateReqVO) { + productDetailsService.update(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('base:productDetails:delete')") + public CommonResult deleteProducts(@RequestParam("id") Long id) { + productDetailsService.delete(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('base:productDetails:query')") + public CommonResult> getProducts(@RequestParam("id") Long id) { + List productDetailsDO = productDetailsService.get(id); + return success(productDetailsDO); + } + + @GetMapping("/page") + @Operation(summary = "获得产品明细分页") + @PreAuthorize("@ss.hasPermission('base:productDetails:query')") + public CommonResult> getProductsPage(@Valid ProductDetailsPageReqVO pageReqVO) { + PageResult pageResult = productDetailsService.getPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ProductDetailsRespVO.class)); + } + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductPageReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductPageReqVO.java new file mode 100644 index 000000000..1cbe9395a --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductPageReqVO.java @@ -0,0 +1,41 @@ +package com.cf.imes.module.system.controller.admin.products.vo.product; + +import com.cf.imes.framework.common.pojo.PageParam; +import com.cf.imes.module.system.validation.products.ProductStatus; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 产品表 products Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductPageReqVO extends PageParam { + + @Schema(description = "产品id", example = "1") + private Long id; + + @Schema(description = "产品名称", example = "赵六") + private String productName; + + @Schema(description = "产品状态", example = "0待上架 1已上架 2已下架") + @ProductStatus + private Integer status; + + @Schema(description = "软件id", example = "1") + private Long softwareId; + + @Schema(description = "操作时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] updateTime; + + @Schema(description = "是否删除") + private Integer deleted; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductRespVO.java new file mode 100644 index 000000000..94781ca09 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductRespVO.java @@ -0,0 +1,37 @@ +package com.cf.imes.module.system.controller.admin.products.vo.product; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.cf.imes.module.system.validation.products.ProductStatus; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 产品表 products Response VO") +@Data +@ExcelIgnoreUnannotated +public class ProductRespVO { + + @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10725") + @ExcelProperty("产品ID") + private Long id; + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") + @ExcelProperty("产品名称") + private String productName; + + @Schema(description = "产品状态", example = "0待上架 1已上架 2已下架") + @ExcelProperty("产品状态") + @ProductStatus + private Integer status; + + @Schema(description = "软件id", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("软件id") + private Long softwareId; + + @Schema(description = "编辑时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("编辑时间") + private LocalDateTime updateTime; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductSaveReqVO.java new file mode 100644 index 000000000..2c17c4efc --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/product/ProductSaveReqVO.java @@ -0,0 +1,26 @@ +package com.cf.imes.module.system.controller.admin.products.vo.product; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; + +@Schema(description = "管理后台 - 产品表 product新增/修改 Request VO") +@Data +public class ProductSaveReqVO { + + @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10725") + private Long id; + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") + @NotEmpty(message = "产品名称不能为空") + private String productName; + + @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer status; + + @Schema(description = "软件id", requiredMode = Schema.RequiredMode.REQUIRED) + private Long softwareId; + + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsPageReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsPageReqVO.java new file mode 100644 index 000000000..36aaf8174 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsPageReqVO.java @@ -0,0 +1,63 @@ +package com.cf.imes.module.system.controller.admin.products.vo.productDetails; + +import com.cf.imes.framework.common.pojo.PageParam; +import com.cf.imes.module.system.validation.products.ProductType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 产品详情表 productDetails Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductDetailsPageReqVO extends PageParam { + + @Schema(description = "产品详情id", example = "1") + private Long id; + + @Schema(description = "产品ID", example = "1") + private String productId; + + @Schema(description = "购买方式", example = "购买方式:0时长;1产量") + @ProductType + private Integer purchaseType; + + @Schema(description = "正常时间", example = "半个月") + private String duration; + + @Schema(description = "正常产量", example = "") + private BigDecimal output; + + @Schema(description = "赠送时间", example = "半个月") + private String giftDuration; + + @Schema(description = "赠送产量", example = "") + private BigDecimal giftOutput; + + @Schema(description = "产品原价", example = "100") + private BigDecimal originalPrice; + + @Schema(description = "折扣", example = "0.8") + private BigDecimal discount; + + @Schema(description = "产品现价", example = "80") + private BigDecimal currentPrice; + + @Schema(description = "是否特惠", example = "是") + private Boolean isDiscounted; + + @Schema(description = "操作时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] updateTime; + + @Schema(description = "是否删除") + private Integer deleted; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsRespVO.java new file mode 100644 index 000000000..1e4c96a22 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsRespVO.java @@ -0,0 +1,57 @@ +package com.cf.imes.module.system.controller.admin.products.vo.productDetails; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.cf.imes.module.system.validation.products.ProductType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + + +@Schema(description = "管理后台 - 产品明细表 productsDetails Response VO") +@Data +@ExcelIgnoreUnannotated +public class ProductDetailsRespVO { + + @Schema(description = "产品详情id", requiredMode = Schema.RequiredMode.REQUIRED, example = "10725") + @ExcelProperty("产品详情id") + private Long id; + + @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("产品ID") + private String productId; + + @Schema(description = "购买方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "购买方式:0时长;1产量") + @ProductType + private Integer purchaseType; + + @Schema(description = "正常时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "半个月") + private String duration; + + @Schema(description = "正常产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "") + private BigDecimal output; + + @Schema(description = "赠送时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "半个月") + private String giftDuration; + + @Schema(description = "赠送产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "") + private BigDecimal giftOutput; + + @Schema(description = "产品原价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private BigDecimal originalPrice; + + @Schema(description = "折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8") + private BigDecimal discount; + + @Schema(description = "产品现价", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") + private BigDecimal currentPrice; + + @Schema(description = "是否特惠", requiredMode = Schema.RequiredMode.REQUIRED, example = "是") + private Boolean isDiscounted; + + @Schema(description = "操作时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime updateTime; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsSaveReqVO.java new file mode 100644 index 000000000..4946236b2 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/products/vo/productDetails/ProductDetailsSaveReqVO.java @@ -0,0 +1,52 @@ +package com.cf.imes.module.system.controller.admin.products.vo.productDetails; + +import com.cf.imes.module.system.validation.products.ProductType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +@Schema(description = "管理后台 - 产品明细表 productDetails新增/修改 Request VO") +@Data +public class ProductDetailsSaveReqVO { + + @Schema(description = "产品详情id", requiredMode = Schema.RequiredMode.REQUIRED, example = "10725") + private Long id; + + @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "产品名称不能为空") + private Long productId; + + @Schema(description = "购买方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "购买方式:0时长;1产量") + @NotNull(message = "购买方式不能为空") + @ProductType + private Integer purchaseType; + + @Schema(description = "产品时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1month") + private String duration; + + @Schema(description = "产品产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "") + private BigDecimal output; + + @Schema(description = "赠送时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "半个月") + private String giftDuration; + + @Schema(description = "赠送产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "") + private BigDecimal giftOutput; + + @Schema(description = "产品原价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "产品时间不能为空") + private BigDecimal originalPrice; + + @Schema(description = "折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8") + private BigDecimal discount; + + @Schema(description = "产品现价", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") + @NotNull(message = "产品时间不能为空") + private BigDecimal currentPrice; + + @Schema(description = "是否特惠", requiredMode = Schema.RequiredMode.REQUIRED, example = "是") + private Boolean isDiscounted; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/RechargeActiveController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/RechargeActiveController.java new file mode 100644 index 000000000..e891170a6 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/RechargeActiveController.java @@ -0,0 +1,74 @@ +package com.cf.imes.module.system.controller.admin.recharge; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.module.system.controller.admin.recharge.vo.RechargePageReqVO; +import com.cf.imes.module.system.controller.admin.recharge.vo.RechargeRespVO; +import com.cf.imes.module.system.controller.admin.recharge.vo.RechargeSaveReqVO; +import com.cf.imes.module.system.dal.dataobject.recharge.GiftMoneyDetailsDO; +import com.cf.imes.module.system.service.recharge.RechargeActiveService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; + +import static com.cf.imes.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 充值活动管理") +@RestController +@RequestMapping("/system/recharge-active") +@Validated +public class RechargeActiveController { + + @Resource + private RechargeActiveService productsService; + + @PostMapping("/create") + @Operation(summary = "新建充值活动") + @PreAuthorize("@ss.hasPermission('base:recharge-active:create')") + public CommonResult createRechargeActive(@Valid @RequestBody RechargeSaveReqVO createReqVO) { + return success(productsService.create(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新充值活动") + @PreAuthorize("@ss.hasPermission('base:recharge-active:update')") + public CommonResult updateRechargeActive(@Valid @RequestBody RechargeSaveReqVO updateReqVO) { + productsService.update(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除充值活动") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('base:recharge-active:delete')") + public CommonResult deleteRechargeActive(@RequestParam("id") Long id) { + productsService.delete(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得充值活动") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('base:recharge-active:query')") + public CommonResult getRechargeActive(@RequestParam("id") Long id) { + GiftMoneyDetailsDO giftMoneyDetailsDO = productsService.get(id); + return success(BeanUtils.toBean(giftMoneyDetailsDO, RechargeRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得充值活动分页") + @PreAuthorize("@ss.hasPermission('base:recharge-active:query')") + public CommonResult> getRechargeActivePage(@Valid RechargePageReqVO pageReqVO) { + PageResult pageResult = productsService.getPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, RechargeRespVO.class)); + } + + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargePageReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargePageReqVO.java new file mode 100644 index 000000000..012218611 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargePageReqVO.java @@ -0,0 +1,67 @@ +package com.cf.imes.module.system.controller.admin.recharge.vo; + +import com.cf.imes.framework.common.pojo.PageParam; +import com.cf.imes.module.system.validation.recharge.PurchaseType; +import com.cf.imes.module.system.validation.recharge.RechargeType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 赠送金活动表 gift_money Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class RechargePageReqVO extends PageParam { + + @Schema(description = "活动id", example = "1") + private Long id; + + @Schema(description = "活动名称", example = "赵六") + private String activityName; + + @Schema(description = "赠送类型", example = "0满X送X; 1每满X送X") + @PurchaseType + private Integer purchaseType; + + @Schema(description = "充值类型", example = "0微信、支付宝 1微信 2支付宝") + @RechargeType + private Integer rechargeType; + + @Schema(description = "充值金额") + private BigDecimal rechargeAmount; + + @Schema(description = "赠送金额") + private BigDecimal giftAmount; + + @Schema(description = "投放开始时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] startTime; + + @Schema(description = "投放结束时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] endTime; + + @Schema(description = "操作时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] updateTime; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "是否删除") + private Integer deleted; + + @Schema(description = "排序", example = "ascend") + private String order; + + @Schema(description = "排序字段", example = "id") + private String field; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargeRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargeRespVO.java new file mode 100644 index 000000000..99f756d70 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargeRespVO.java @@ -0,0 +1,53 @@ +package com.cf.imes.module.system.controller.admin.recharge.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 赠送金活动表 gift_money Request VO") +@Data +@ExcelIgnoreUnannotated +public class RechargeRespVO { + + @Schema(description = "活动id", example = "1") + private Long id; + + @Schema(description = "活动名称", example = "赵六") + private String activityName; + + @Schema(description = "赠送类型", example = "0满X送X; 1每满X送X") + private Integer purchaseType; + + @Schema(description = "充值类型", example = "0微信、支付宝 1微信 2支付宝") + private Integer rechargeType; + + @Schema(description = "充值金额") + private BigDecimal rechargeAmount; + + @Schema(description = "赠送金额") + private BigDecimal giftAmount; + + @Schema(description = "投放开始时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime startTime; + + @Schema(description = "投放结束时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime endTime; + + @Schema(description = "操作时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime updateTime; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "是否删除") + private Integer deleted; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargeSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargeSaveReqVO.java new file mode 100644 index 000000000..7ba5de4b8 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/recharge/vo/RechargeSaveReqVO.java @@ -0,0 +1,67 @@ +package com.cf.imes.module.system.controller.admin.recharge.vo; + +import com.cf.imes.module.system.validation.recharge.MoneyValid; +import com.cf.imes.module.system.validation.recharge.PurchaseType; +import com.cf.imes.module.system.validation.recharge.RechargeType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 赠送金活动表 gift_money 新增/修改 Request VO") +@Data +public class RechargeSaveReqVO { + + @Schema(description = "活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") + @NotNull(message = "活动名称不能为空") + private String activityName; + + @Schema(description = "赠送类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0满X送X; 1每满X送X") + @NotNull(message = "赠送类型不能为空") + @PurchaseType + private Integer purchaseType; + + @Schema(description = "充值类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0微信、支付宝 1微信 2支付宝") + @NotNull(message = "充值类型不能为空") + @RechargeType + private Integer rechargeType; + + @Schema(description = "充值金额",requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "充值金额不能为空") + @MoneyValid(name = "充值金额") + private BigDecimal rechargeAmount; + + @Schema(description = "赠送金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "赠送金额不能为空") + @MoneyValid(name = "赠送金额") + private BigDecimal giftAmount; + + @Schema(description = "开始时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @NotNull(message = "开始时间不能为空") + private LocalDateTime startTime; + + @Schema(description = "结束时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @NotNull(message = "结束时间不能为空") + private LocalDateTime endTime; + + @Schema(description = "操作时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime updateTime; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") + private String remark; + + @Schema(description = "是否删除") + private Integer deleted; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/advertisement/AdvertisementDO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/advertisement/AdvertisementDO.java new file mode 100644 index 000000000..9eb4c3c45 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/advertisement/AdvertisementDO.java @@ -0,0 +1,73 @@ +package com.cf.imes.module.system.dal.dataobject.advertisement; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 广告表 product_details DO + * + * @author 晨丰科技 + */ +@TableName("advertisement") +@KeySequence("advertisement_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AdvertisementDO extends BaseDO { + + /** + * 广告 ID + */ + @TableId + private Long id; + /** + * 广告名称 + */ + private String adName; + /** + * 软件id,不同软件的标识(用于分辩不同系统中的产品)---目前就只有一个产品 + */ + private String softwareId; + /** + * 广告位置 + */ + private String adPosition; + /** + * 图片路径 + */ + private String adImagePath; + + /** + * 投放开始时间 + */ + private LocalDateTime startTime; + + /** + * 投放结束时间 + */ + private LocalDateTime endTime; + /** + * 跳转路径 + */ + private String adRedirectUrl; + /** + * 广告顺序 + */ + private Integer sort; + + /** + * 广告状态 0全部 1未发布 2已发布 3已结束 + */ + private Integer status; + + + private Boolean deleted; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/advertisement/AdvertisementTaskDO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/advertisement/AdvertisementTaskDO.java new file mode 100644 index 000000000..a2a09e916 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/advertisement/AdvertisementTaskDO.java @@ -0,0 +1,50 @@ +package com.cf.imes.module.system.dal.dataobject.advertisement; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; +import lombok.*; + +/** + * 广告状态修改任务 + * + */ +@TableName("system_advertisement_task") +@KeySequence("system_advertisement_task_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AdvertisementTaskDO extends BaseDO { + + /** + * 主键 + */ + @TableId + private Long id; + + /** + * 广告id + */ + private Long advertisementId; + + /** + * 消息id + */ + private String messageId; + + /** + * 广告状态,AdvertisementStatusEnum + */ + private Integer advertisementStatus; + + /** + * 消费状态 MessageStatusEnum + */ + private Integer messageStatus; + + private Boolean deleted; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/products/ProductsDO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/products/ProductsDO.java new file mode 100644 index 000000000..359bb3cfa --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/products/ProductsDO.java @@ -0,0 +1,45 @@ +package com.cf.imes.module.system.dal.dataobject.products; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; +import lombok.*; + + +/** + * 产品表 products DO + * + * @author 晨丰科技 + */ +@TableName("products") +@KeySequence("products_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductsDO extends BaseDO { + + /** + * 产品 ID + */ + @TableId + private Long id; + /** + * 产品名称 + */ + private String productName; + /** + * 产品状态 + */ + private Integer status; + /** + * 软件id,不同软件的标识(用于分辩不同系统中的产品)---目前就只有一个产品 + */ + private Integer softwareId; + + private Boolean deleted; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/products/ProductsDetailDO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/products/ProductsDetailDO.java new file mode 100644 index 000000000..8a1ca2cfd --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/products/ProductsDetailDO.java @@ -0,0 +1,83 @@ +package com.cf.imes.module.system.dal.dataobject.products; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; +import lombok.*; + +import java.math.BigDecimal; + +/** + * 产品明细表 product_details DO + * + * @author 晨丰科技 + */ +@TableName("products_detail") +@KeySequence("products_detail_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductsDetailDO extends BaseDO { + + /** + * 产品明细 ID + */ + @TableId + private Long id; + + /** + * 产品id + */ + private Long productId; + + /** + * 产品明细购买方式 0时长 1产量 + */ + private Integer purchaseType; + + /** + * 正常时间,不加赠送时间 + */ + private String duration; + + /** + * 正常产量,不加赠送产量 + */ + @TableField("`output`") + private BigDecimal output; + + /** + * 赠送时间 + */ + private String giftDuration; + + /** + * 赠送产量 + */ + private BigDecimal giftOutput; + + /** + * 产品原价 + */ + private BigDecimal originalPrice; + + /** + * 折扣 + */ + private BigDecimal discount; + + /** + * 产品现价 + */ + private BigDecimal currentPrice; + + /** + * 是否特惠: 0否1是 + */ + private Boolean isDiscounted; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/recharge/GiftMoneyDetailsDO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/recharge/GiftMoneyDetailsDO.java new file mode 100644 index 000000000..0c20b5336 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/recharge/GiftMoneyDetailsDO.java @@ -0,0 +1,66 @@ +package com.cf.imes.module.system.dal.dataobject.recharge; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 赠送金规则表 gift_money_details DO + * + * @author 晨丰科技 + */ +@TableName("gift_money_details") +@KeySequence("gift_money_details_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class GiftMoneyDetailsDO extends BaseDO { + + /** + * 产品 ID + */ + @TableId + private Long id; + /** + * 活动名称 + */ + private String activityName; + /** + * 赠送类型 0满X送X; 1每满X送X + */ + private Integer purchaseType; + /** + * 充值类型 0微信、支付宝 1微信 2支付宝 + */ + private Integer rechargeType; + /** + * 充值金额 + */ + private BigDecimal rechargeAmount; + /** + * 赠送金额 + */ + private BigDecimal giftAmount; + /** + * 活动开始时间 + */ + private LocalDateTime startTime; + /** + * 活动结束时间 + */ + private LocalDateTime endTime; + /** + * 备注 + */ + private String remark; + + private Boolean deleted; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/advertisement/AdvertisementMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/advertisement/AdvertisementMapper.java new file mode 100644 index 000000000..a6aa9be0e --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/advertisement/AdvertisementMapper.java @@ -0,0 +1,73 @@ +package com.cf.imes.module.system.dal.mysql.advertisement; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.system.controller.admin.advertisement.vo.AdvertisementPageReqVO; +import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementDO; +import org.apache.ibatis.annotations.Mapper; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 广告信息表 Mapper + * + * @author 晨丰科技 + */ +@Mapper +public interface AdvertisementMapper extends BaseMapperX { + + default PageResult selectPage(AdvertisementPageReqVO reqVO, boolean deleted) { + + LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX() + .likeIfPresent(AdvertisementDO::getAdName, reqVO.getAdName()) + .likeIfPresent(AdvertisementDO::getAdPosition, reqVO.getAdPosition()) + .eqIfPresent(AdvertisementDO::getStatus, reqVO.getStatus()) + .eqIfPresent(AdvertisementDO::getDeleted, deleted); + + if (reqVO.getOrder() == null) { + queryWrapper.orderByDesc(AdvertisementDO::getSort); + }else { + if (reqVO.getOrder().equals("ascend")) { + switch (reqVO.getField()) { + case "id" -> queryWrapper.orderByAsc(AdvertisementDO::getId); + case "adName" -> queryWrapper.orderByAsc(AdvertisementDO::getAdName); + case "updater" -> queryWrapper.orderByAsc(AdvertisementDO::getUpdater); + case "updateTime" -> queryWrapper.orderByAsc(AdvertisementDO::getUpdateTime); + default -> { + // default不排序 + } + } + }else if (reqVO.getOrder().equals("descend")) { + switch (reqVO.getField()) { + case "id" -> queryWrapper.orderByDesc(AdvertisementDO::getId); + case "adName" -> queryWrapper.orderByDesc(AdvertisementDO::getAdName); + case "updater" -> queryWrapper.orderByDesc(AdvertisementDO::getUpdater); + case "updateTime" -> queryWrapper.orderByDesc(AdvertisementDO::getUpdateTime); + default -> { + // default不排序 + } + } + } + } + + return selectPage(reqVO, queryWrapper); + + } + + default int updateAdStatus(Long id, Integer newStatus) { + return update(new LambdaUpdateWrapper() + .set(AdvertisementDO::getStatus, newStatus) + .eq(AdvertisementDO::getId, id) + .eq(AdvertisementDO::getDeleted, false)); + } + + default List selectList(LocalDateTime now, Integer status) { + return selectList(new LambdaQueryWrapperX() + .le(AdvertisementDO::getStartTime, now) + .eq(AdvertisementDO::getStatus, status)); + + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/advertisement/AdvertisementTaskMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/advertisement/AdvertisementTaskMapper.java new file mode 100644 index 000000000..236cbbe67 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/advertisement/AdvertisementTaskMapper.java @@ -0,0 +1,45 @@ +package com.cf.imes.module.system.dal.mysql.advertisement; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; +import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementTaskDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 广告消费信息表 Mapper + * + * @author 晨丰科技 + */ +@Mapper +public interface AdvertisementTaskMapper extends BaseMapperX { + + default int updateToDeletedById(Long adId, Boolean deleted, Integer messageStatus) { + return update(new LambdaUpdateWrapper() + .set(AdvertisementTaskDO::getDeleted, deleted) + .set(AdvertisementTaskDO::getMessageStatus, messageStatus) + .eq(AdvertisementTaskDO::getAdvertisementId, adId)); + } + + default List selectIdByAdvertisementId(Long adId) { + return selectList(new LambdaUpdateWrapper() + .eq(AdvertisementTaskDO::getAdvertisementId, adId)) + .stream() + .map(AdvertisementTaskDO::getMessageId) + .toList(); + } + + default AdvertisementTaskDO selectByMessageId(String messageId) { + return selectOne(new LambdaUpdateWrapper() + .eq(AdvertisementTaskDO::getMessageId, messageId) + .eq(AdvertisementTaskDO::getDeleted, Boolean.FALSE)); + } + + default int updateMessageStateByMessageId(String messageId, Boolean deleted, Integer messageStatus) { + return update(new LambdaUpdateWrapper() + .set(AdvertisementTaskDO::getMessageStatus, messageStatus) + .eq(AdvertisementTaskDO::getMessageId, messageId) + .eq(AdvertisementTaskDO::getDeleted, deleted)); + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/products/ProductsDetailMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/products/ProductsDetailMapper.java new file mode 100644 index 000000000..94c46662f --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/products/ProductsDetailMapper.java @@ -0,0 +1,57 @@ +package com.cf.imes.module.system.dal.mysql.products; + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.system.controller.admin.products.vo.productDetails.ProductDetailsPageReqVO; +import com.cf.imes.module.system.dal.dataobject.products.ProductsDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; + +/** + * 产品明细表 product_details Mapper + * + * @author 晨丰科技 + */ +@Mapper +public interface ProductsDetailMapper extends BaseMapperX { + + default PageResult selectPage(ProductDetailsPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ProductsDetailDO::getPurchaseType, reqVO.getPurchaseType()) + .eqIfPresent(ProductsDetailDO::getProductId, reqVO.getProductId()) + .eqIfPresent(ProductsDetailDO::getDuration, reqVO.getDuration()) + .eqIfPresent(ProductsDetailDO::getGiftDuration, reqVO.getGiftDuration()) + .eqIfPresent(ProductsDetailDO::getOutput, reqVO.getOutput()) + .eqIfPresent(ProductsDetailDO::getGiftOutput, reqVO.getGiftOutput()) + .eqIfPresent(ProductsDetailDO::getOriginalPrice, reqVO.getOriginalPrice()) + .eqIfPresent(ProductsDetailDO::getDiscount, reqVO.getDiscount()) + .eqIfPresent(ProductsDetailDO::getCurrentPrice, reqVO.getCurrentPrice()) + .eqIfPresent(ProductsDetailDO::getIsDiscounted, reqVO.getIsDiscounted()) + ); + } + + + // 时长查重,添加productId为查询条件 + default int selectCountByDuration(String duration, Long productId, Boolean flag) { + LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX<>(); + queryWrapper.eq(ProductsDetailDO::getDuration, duration) + .eq(ProductsDetailDO::getDeleted, false); + if (flag) { // flag为true时,查询条件中添加productId + queryWrapper.eq(ProductsDetailDO::getProductId, productId); + } + return Math.toIntExact(selectCount(queryWrapper)); + } + +// 产量查重 + default int selectCountByOutput(BigDecimal output, Long productId, Boolean flag) { + LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX<>(); + queryWrapper.eq(ProductsDetailDO::getDuration, output) + .eq(ProductsDetailDO::getDeleted, false); + if (flag) { // flag为true时,查询条件中添加productId + queryWrapper.eq(ProductsDetailDO::getProductId, productId); + } + return Math.toIntExact(selectCount(queryWrapper)); + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/products/ProductsMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/products/ProductsMapper.java new file mode 100644 index 000000000..d7f218e45 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/products/ProductsMapper.java @@ -0,0 +1,26 @@ +package com.cf.imes.module.system.dal.mysql.products; + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.system.controller.admin.products.vo.product.ProductPageReqVO; +import com.cf.imes.module.system.dal.dataobject.products.ProductsDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 产品表 product Mapper + * + * @author 晨丰科技 + */ +@Mapper +public interface ProductsMapper extends BaseMapperX { + + default PageResult selectPage(ProductPageReqVO reqVO, boolean deleted) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ProductsDO::getId, reqVO.getId()) + .likeIfPresent(ProductsDO::getProductName, reqVO.getProductName()) + .eqIfPresent(ProductsDO::getStatus, reqVO.getStatus()) + .eq(ProductsDO::getDeleted, deleted)); + } + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/recharge/GiftMoneyDetailsMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/recharge/GiftMoneyDetailsMapper.java new file mode 100644 index 000000000..32fee4bd6 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/recharge/GiftMoneyDetailsMapper.java @@ -0,0 +1,59 @@ +package com.cf.imes.module.system.dal.mysql.recharge; + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.system.controller.admin.recharge.vo.RechargePageReqVO; +import com.cf.imes.module.system.dal.dataobject.recharge.GiftMoneyDetailsDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 赠送金活动详情表 gift_money_details Mapper + * + * @author 晨丰科技 + */ +@Mapper +public interface GiftMoneyDetailsMapper extends BaseMapperX { + default PageResult selectPage(RechargePageReqVO reqVO) { + LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX() + .likeIfPresent(GiftMoneyDetailsDO::getActivityName, reqVO.getActivityName()) + .eqIfPresent(GiftMoneyDetailsDO::getPurchaseType, reqVO.getPurchaseType()) + .eqIfPresent(GiftMoneyDetailsDO::getRechargeType, reqVO.getRechargeType()) + .eqIfPresent(GiftMoneyDetailsDO::getGiftAmount, reqVO.getGiftAmount()) + .eqIfPresent(GiftMoneyDetailsDO::getRechargeAmount, reqVO.getRechargeAmount()) + .betweenIfPresent(GiftMoneyDetailsDO::getStartTime, reqVO.getStartTime()) + .betweenIfPresent(GiftMoneyDetailsDO::getEndTime, reqVO.getEndTime()); + + if (reqVO.getOrder() == null) { + queryWrapper.orderByDesc(GiftMoneyDetailsDO::getId); + }else { + if (reqVO.getOrder().equals("ascend")) { + switch (reqVO.getField()) { + case "id" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getId); + case "rechargeAmount" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getRechargeAmount); + case "giftAmount" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getGiftAmount); + case "startTime" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getStartTime); + case "endTime" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getEndTime); + case "updateTime" -> queryWrapper.orderByAsc(GiftMoneyDetailsDO::getUpdateTime); + default -> { + // default不排序 + } + } + }else if (reqVO.getOrder().equals("descend")) { + switch (reqVO.getField()) { + case "id" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getId); + case "rechargeAmount" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getRechargeAmount); + case "giftAmount" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getGiftAmount); + case "startTime" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getStartTime); + case "endTime" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getEndTime); + case "updateTime" -> queryWrapper.orderByDesc(GiftMoneyDetailsDO::getUpdateTime); + default -> { + // default不排序 + } + } + } + } + + return selectPage(reqVO, queryWrapper); + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/consumer/advertisement/AdvertisementSendConsumer.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/consumer/advertisement/AdvertisementSendConsumer.java new file mode 100644 index 000000000..94e8dd567 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/consumer/advertisement/AdvertisementSendConsumer.java @@ -0,0 +1,71 @@ +package com.cf.imes.module.system.mq.consumer.advertisement; + +import com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants; +import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementDO; +import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementTaskDO; +import com.cf.imes.module.system.dal.mysql.advertisement.AdvertisementMapper; +import com.cf.imes.module.system.dal.mysql.advertisement.AdvertisementTaskMapper; +import com.cf.imes.module.system.enums.advertisement.AdvertisementStatusEnum; +import com.cf.imes.module.system.enums.advertisement.MessageStatusEnum; +import com.cf.imes.module.system.mq.message.advertisement.AdvertisementSendMessage; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.Objects; + + +/** + * 针对 {@link AdvertisementSendMessage} 的消费者 + * + * @author 晨丰科技 + */ +@Component +@Slf4j +public class AdvertisementSendConsumer { + + @Resource + private AdvertisementMapper advertisementMapper; + + @Resource + private AdvertisementTaskMapper advertisementTaskMapper; + + @RabbitListener(queues = RabbitMqConstants.SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_QUEUE) + public void onMessage(AdvertisementSendMessage message){ + // 1. 获取广告数据 + AdvertisementDO ad = advertisementMapper.selectById(message.getAdId()); + if (ad == null || ad.getDeleted()) + return; + + // 2. 检查消息有效性 + AdvertisementTaskDO messageRecord = advertisementTaskMapper.selectByMessageId(message.getMessageId()); + if (messageRecord == null || + Objects.equals(messageRecord.getMessageStatus(), MessageStatusEnum.CANCELLED.getStatus())) { + return; + } + + // 3. 处理状态变更 + if (AdvertisementStatusEnum.PUBLISHED.getName().equals(message.getAction())) { // 待发布 + if (ad.getStatus() == AdvertisementStatusEnum.UNPUBLISHED.getStatus() && + LocalDateTime.now().isAfter(ad.getStartTime())) { + updateAdStatus(ad, messageRecord.getAdvertisementStatus()); + } + } else if (AdvertisementStatusEnum.ENDED.getName().equals(message.getAction())) { // 待结束 + if (ad.getStatus() == AdvertisementStatusEnum.PUBLISHED.getStatus() && + LocalDateTime.now().isAfter(ad.getEndTime())) { + updateAdStatus(ad, messageRecord.getAdvertisementStatus()); + } + } + + // 4. 标记消息为已处理 + messageRecord.setMessageStatus(MessageStatusEnum.PROCESSED.getStatus()); + advertisementTaskMapper.updateMessageStateByMessageId(message.getMessageId(),false, MessageStatusEnum.PROCESSED.getStatus()); + } + + private void updateAdStatus(AdvertisementDO ad, Integer newStatus) { + advertisementMapper.updateAdStatus(ad.getId(), newStatus); + } + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/advertisement/AdvertisementSendMessage.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/advertisement/AdvertisementSendMessage.java new file mode 100644 index 000000000..bd87b542f --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/advertisement/AdvertisementSendMessage.java @@ -0,0 +1,35 @@ +package com.cf.imes.module.system.mq.message.advertisement; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +/** + * 广告状态更改消息 + * + * @author 晨丰科技 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class AdvertisementSendMessage { + + /** + * 广告id + */ + @NotNull(message = "广告id不能为空") + private Long adId; + + /** + * 消息id + */ + @NotNull(message = "消息id") + private String messageId; + + /** + * 消息类别 + */ + private String action; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/advertisement/AdvertisementProducer.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/advertisement/AdvertisementProducer.java new file mode 100644 index 000000000..c53993f86 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/advertisement/AdvertisementProducer.java @@ -0,0 +1,82 @@ +package com.cf.imes.module.system.mq.producer.advertisement; + +import com.cf.imes.module.system.mq.message.advertisement.AdvertisementSendMessage; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.stereotype.Component; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; +import org.springframework.web.context.request.RequestContextHolder; + +import javax.annotation.Resource; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.UUID; + +import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_EXCHANGE; +import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_ROUTING_KEY; + +/** + * Advertisement 广告相关消息的 Producer + * + */ +@Slf4j +@Component +public class AdvertisementProducer { + + @Resource + private RabbitTemplate rabbitTemplate; + + + /** + * 发送 {@link AdvertisementSendMessage} 消息 + * + * @param adId 广告id + * @param action 类型 + * @param triggerTime 到期时间 + */ + + public String sendAdvertisementSendMessage(Long adId, String action, LocalDateTime triggerTime) { + + String messageId = UUID.randomUUID().toString(); + + + long delay = Duration.between(LocalDateTime.now(), triggerTime).toMillis(); + + if (delay > 0) { + RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(), true); + AdvertisementSendMessage message = new AdvertisementSendMessage(adId, messageId, action); + + if (TransactionSynchronizationManager.isActualTransactionActive()) { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + // 数据库操作全部完成发送消息 + rabbitTemplate.convertAndSend( + SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_EXCHANGE, + SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_ROUTING_KEY, + message, + correlationData -> { + correlationData.getMessageProperties().setMessageId(messageId); + correlationData.getMessageProperties().setDelay(Long.valueOf(delay).intValue()); + return correlationData; + }); + } + }); + } else { + // 数据库操作全部完成发送消息 + rabbitTemplate.convertAndSend( + SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_EXCHANGE, + SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_ROUTING_KEY, + message, + correlationData -> { + correlationData.getMessageProperties().setMessageId(messageId); + correlationData.getMessageProperties().setDelay(Long.valueOf(delay).intValue()); + return correlationData; + }); + } + } + + return messageId; + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementCompensateTask.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementCompensateTask.java new file mode 100644 index 000000000..2df521899 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementCompensateTask.java @@ -0,0 +1,116 @@ +package com.cf.imes.module.system.service.advertisement; + +import com.alibaba.nacos.common.utils.StringUtils; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementDO; +import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementTaskDO; +import com.cf.imes.module.system.dal.mysql.advertisement.AdvertisementMapper; +import com.cf.imes.module.system.dal.mysql.advertisement.AdvertisementTaskMapper; +import com.cf.imes.module.system.enums.advertisement.AdvertisementStatusEnum; +import com.cf.imes.module.system.enums.advertisement.MessageStatusEnum; +import com.cf.imes.module.system.mq.message.advertisement.AdvertisementSendMessage; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.context.request.RequestContextHolder; + +import javax.annotation.Resource; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_EXCHANGE; +import static com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants.SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_ROUTING_KEY; + +/** + * 广告状态修改 Service 实现类 + * + */ +@Service +@Validated +@Slf4j +public class AdvertisementCompensateTask { + + @Resource + private AdvertisementMapper advertisementMapper; + + @Resource + private AdvertisementTaskMapper advertisementTaskMapper; + + @Resource + private RabbitTemplate rabbitTemplate; + + + //=== 补偿任务 ===// +// @Scheduled(cron = "0 0/30 * * * ?") + public void checkAdStatusConsistency() { + // 1. 检查应发布但未发布的广告 + List unpublishedAds = advertisementMapper.selectList(LocalDateTime.now(), AdvertisementStatusEnum.UNPUBLISHED.getStatus()); + unpublishedAds.forEach(ad -> { + updateAdStatus(ad, AdvertisementStatusEnum.PUBLISHED.getStatus()); + rescheduleExpireMessage(ad); + }); + + // 2. 检查应结束但未结束的广告 + List publishedAds = advertisementMapper.selectList( + new QueryWrapper() + .le("end_time", LocalDateTime.now()) + .eq("status", AdvertisementStatusEnum.PUBLISHED.getStatus()) + ); + publishedAds.forEach(ad -> updateAdStatus(ad, AdvertisementStatusEnum.ENDED.getStatus())); + } + + private void rescheduleExpireMessage(AdvertisementDO ad) { + if (ad.getEndTime().isAfter(LocalDateTime.now())) { + String newMsgId = sendSingleMessage(ad.getId(), "expire", ad.getEndTime()); + trackMessage(ad.getId(), newMsgId, AdvertisementStatusEnum.PUBLISHED.getStatus(), MessageStatusEnum.CANCELLED.getStatus()); + } + } + + private void updateAdStatus(AdvertisementDO ad, Integer newStatus) { + advertisementMapper.updateAdStatus(ad.getId(), newStatus); + + } + + /** + * 发送单个延迟消息 + */ + private String sendSingleMessage(Long adId, String action, LocalDateTime triggerTime) { + String messageId = UUID.randomUUID().toString(); + long delay = Duration.between(LocalDateTime.now(), triggerTime).toMillis(); + + + if (delay > 0) { + RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(), true); + + rabbitTemplate.convertAndSend( + SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_EXCHANGE, + SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_ROUTING_KEY, + new AdvertisementSendMessage(adId, messageId, action), + correlationData -> { + correlationData.getMessageProperties().setMessageId(messageId); + correlationData.getMessageProperties().setDelay(Long.valueOf(delay).intValue()); + return correlationData; + } + ); + } + return messageId; + } + + /** + * 记录消息追踪 + */ + private void trackMessage(Long adId, String messageId, Integer advertisementStatus, Integer messageStatus) { + if (StringUtils.isNotBlank(messageId)) { + advertisementTaskMapper.insert(new AdvertisementTaskDO() + .setAdvertisementId(adId) + .setMessageId(messageId) + .setMessageStatus(messageStatus) + .setAdvertisementStatus(advertisementStatus) + ); + log.info("[trackMessage][adId({}) messageId({}) 记录消息追踪成功]", adId, messageId); + } + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementService.java new file mode 100644 index 000000000..4c473d2d5 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementService.java @@ -0,0 +1,56 @@ +package com.cf.imes.module.system.service.advertisement; + + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.module.system.controller.admin.advertisement.vo.AdvertisementPageReqVO; +import com.cf.imes.module.system.controller.admin.advertisement.vo.AdvertisementSaveReqVO; +import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementDO; + +import javax.validation.Valid; + +public interface AdvertisementService { + + /** + * 创建广告 + * + * @param createReqVO 产品名称 + * @return 编号 + */ + Long create(@Valid AdvertisementSaveReqVO createReqVO); + + /** + * 更新广告 + * + * @param updateReqVO 更新信息 + */ + void update(@Valid AdvertisementDO updateReqVO, Integer index); + + /** + * 更新广告状态 + * + * @param id 更新信息 + */ + void update(Long id, Integer status); + + /** + * 删除广告 + * + * @param id 编号 + */ + void delete(Long id); + + /** + * 获得广告 + * + * @param id 编号 + */ + AdvertisementDO get(Long id); + + /** + * 获得广告 分页 + * + * @param pageReqVO 分页查询 + */ + PageResult getPage(AdvertisementPageReqVO pageReqVO); + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementServiceImpl.java new file mode 100644 index 000000000..be9be6f60 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/advertisement/AdvertisementServiceImpl.java @@ -0,0 +1,251 @@ +package com.cf.imes.module.system.service.advertisement; + +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.nacos.common.utils.StringUtils; +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaUpdateWrapperX; +import com.cf.imes.module.system.controller.admin.advertisement.vo.AdvertisementPageReqVO; +import com.cf.imes.module.system.controller.admin.advertisement.vo.AdvertisementSaveReqVO; +import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementDO; +import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementTaskDO; +import com.cf.imes.module.system.dal.mysql.advertisement.AdvertisementMapper; +import com.cf.imes.module.system.dal.mysql.advertisement.AdvertisementTaskMapper; +import com.cf.imes.module.system.enums.advertisement.AdvertisementStatusEnum; +import com.cf.imes.module.system.enums.advertisement.MessageStatusEnum; +import com.cf.imes.module.system.mq.producer.advertisement.AdvertisementProducer; +import com.cf.imes.module.system.service.dict.DictDataService; +import com.cf.imes.module.system.util.SnowflakeIdWorker3rd; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.Arrays; + +import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.*; + +/** + * 广告表 advertisement Service 实现类 + * + * @author 晨丰科技 + */ +@Service +@Validated +@Slf4j +public class AdvertisementServiceImpl implements AdvertisementService{ + + private static final String ADVERTISEMENT_POSITION = "advertisement_position"; + + private static final String EMPTY_STRING = new String(); + + @Value("${chenfeng.info.name}") + private String SOFT_WARE_ID; // 获取软件标识-可修改 + + @Resource + private DictDataService dictDataService; + + @Resource + private AdvertisementMapper advertisementMapper; + + @Resource + private AdvertisementTaskMapper advertisementTaskMapper; + + @Resource + private SnowflakeIdWorker3rd idWorker; + + @Resource + private AdvertisementProducer advertisementProducer; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long create(AdvertisementSaveReqVO createReqVO) { + // 遍历adPosition验证广告位置是否存在 + for (Integer adPosition : createReqVO.getAdPosition()) { + if (dictDataService.getDictData(ADVERTISEMENT_POSITION, adPosition.toString()) == null) { + throw exception(ADVERTISEMENT_POSITION_NO_EXIST); + } + } + // 插入广告 + Long id = idWorker.nextId(); + createReqVO.setId(id); + AdvertisementDO advertisementDO = BeanUtils.toBean(createReqVO, AdvertisementDO.class) + .setAdPosition(Arrays.toString(createReqVO.getAdPosition())) +// .setStartTime(createReqVO.getStartTime().toLocalDate().atStartOfDay()) // 开始结束时间设置为每天00:00:00 +// .setEndTime(createReqVO.getEndTime().toLocalDate().atStartOfDay()) + .setStatus(validateAdvertisementStatus(createReqVO.getStartTime(), createReqVO.getEndTime())) + .setSoftwareId(SOFT_WARE_ID); + advertisementMapper.insert(advertisementDO); + + // 使用子线程,添加生产者队列,待到达发布时间进行广告状态修改为已发布 + sendDelayMessages(advertisementDO); + return advertisementDO.getId(); + } + + /** + * 发送初始延迟消息 + * + * 根据状态发送延迟信息 + */ + private void sendDelayMessages(AdvertisementDO ad) { + + // 删除可能存在的旧消息 + cancelExistingMessages(ad.getId()); + + // 发送发布消息 + if (ad.getStartTime().isAfter(LocalDateTime.now())) { + String publishMsgId = advertisementProducer.sendAdvertisementSendMessage(ad.getId(), AdvertisementStatusEnum.PUBLISHED.getName(), ad.getStartTime()); // 发布 + trackMessage(ad.getId(), publishMsgId, AdvertisementStatusEnum.PUBLISHED.getStatus(), MessageStatusEnum.PENDING.getStatus()); + } + + // 发送结束消息 + if (ad.getEndTime().isAfter(LocalDateTime.now())) { + String expireMsgId = advertisementProducer.sendAdvertisementSendMessage(ad.getId(), AdvertisementStatusEnum.ENDED.getName(), ad.getEndTime()); // 结束 + trackMessage(ad.getId(), expireMsgId, AdvertisementStatusEnum.ENDED.getStatus(), MessageStatusEnum.PENDING.getStatus()); + } + } + + /** + * 记录消息追踪 + */ + private void trackMessage(Long adId, String messageId, Integer advertisementStatus, Integer messageStatus) { + if (StringUtils.isNotBlank(messageId)) { + advertisementTaskMapper.insert(new AdvertisementTaskDO() + .setAdvertisementId(adId) + .setMessageId(messageId) + .setMessageStatus(messageStatus) + .setAdvertisementStatus(advertisementStatus) + ); + log.info("[trackMessage][adId({}) messageId({}) 记录消息追踪成功]", adId, messageId); + } + } + + /** + * 取消关联的消息 + */ + private void cancelExistingMessages(Long adId) { + // 标记消息为已取消(实际消费时检查) + advertisementTaskMapper.updateToDeletedById(adId,true, MessageStatusEnum.CANCELLED.getStatus()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(AdvertisementDO updateReqVO, Integer index) { + // 确认广告是否存在 + validateAdvertisementExists(updateReqVO.getId(), false); + // 更新内容 + AdvertisementDO advertisementDO = BeanUtils.toBean(updateReqVO, AdvertisementDO.class); + // 删除现有广告的延迟队列 + if (index == 0) { // 全部更新 + advertisementDO.setAdRedirectUrl(getEmpty(advertisementDO.getAdRedirectUrl())) + .setSort(getZeroInt(advertisementDO.getSort())) + .setStatus(validateAdvertisementStatus(advertisementDO.getStartTime(), advertisementDO.getEndTime())); + + } else { + advertisementDO = getAdvertisementDO(updateReqVO.getId(), false) + .setStartTime(updateReqVO.getStartTime()) + .setEndTime(updateReqVO.getEndTime()) + .setStatus(validateAdvertisementStatus(advertisementDO.getStartTime(), advertisementDO.getEndTime())); + + } + // 根据修改时间,新增广告状态修改延迟队列 + advertisementMapper.updateById(advertisementDO); + + // 使用子线程,添加生产者队列,待到达发布时间进行广告状态修改为已发布 + sendDelayMessages(advertisementDO); + } + // 判断广告状态 + public int validateAdvertisementStatus(LocalDateTime startTime, LocalDateTime endTime) { + // 当前时间 + LocalDateTime now = LocalDateTime.now(); + if (now.isBefore(startTime)) { // 未开始 + return AdvertisementStatusEnum.UNPUBLISHED.getStatus(); + } else if (now.isAfter(endTime)) { // 已结束 + return AdvertisementStatusEnum.ENDED.getStatus(); + } else { // 进行中 + return AdvertisementStatusEnum.PUBLISHED.getStatus(); + } + } + + /** + * value为空返回EMPTY_STRING + * + * @param value + * @return + */ + private String getEmpty(String value) { + return StringUtils.defaultIfEmpty(value, EMPTY_STRING); + } + + /** + * value为空返回0.0 + * + * @param value + * @return + */ + private int getZeroInt(Integer value) { + return ObjectUtil.defaultIfNull(value, 0); + } + + private void validateAdvertisementExists(Long id, Boolean deleted) { + AdvertisementDO advertisementDO = advertisementMapper.selectOne(new LambdaQueryWrapperX() + .eq(AdvertisementDO::getId, id) + .eq(AdvertisementDO::getDeleted, deleted)); + if (advertisementDO == null) { + throw exception(ADVERTISEMENT_NO_EXIST); + } + } + + private AdvertisementDO getAdvertisementDO(Long id, Boolean deleted) { + return advertisementMapper.selectOne(new LambdaQueryWrapperX() + .eq(AdvertisementDO::getId, id) + .eq(AdvertisementDO::getDeleted, deleted)); + } + + @Override + public void update(Long id, Integer status) { // 发布,结束 + if (status.equals(AdvertisementStatusEnum.PUBLISHED.getStatus())) { // 立即发布 + if (LocalDateTime.now().isAfter(getAdvertisementDO(id, false).getStartTime())) { + throw exception(ADVERTISEMENT_STATUS_ERROR); + } + if (LocalDateTime.now().isAfter(getAdvertisementDO(id, false).getEndTime())) { + throw exception(ADVERTISEMENT_STATUS_ERROR2); + } + + } else if (status.equals(AdvertisementStatusEnum.ENDED.getStatus())) { // 结束发布 + if (LocalDateTime.now().isBefore(getAdvertisementDO(id, false).getStartTime())) { + throw exception(ADVERTISEMENT_END_ERROR); + } + if (LocalDateTime.now().isAfter(getAdvertisementDO(id, false).getEndTime())) { + throw exception(ADVERTISEMENT_END_ERROR2); + } + } + advertisementMapper.update(new AdvertisementDO().setStatus(status), + new LambdaUpdateWrapperX() + .eq(AdvertisementDO::getId, id) + .eq(AdvertisementDO::getDeleted, false)); + } + + @Override + public void delete(Long id) { + // 确认广告是否存在 + validateAdvertisementExists(id, false); + advertisementMapper.deleteById(id); + } + + @Override + public AdvertisementDO get(Long id) { + validateAdvertisementExists(id, false); + return getAdvertisementDO(id, false); + } + + @Override + public PageResult getPage(AdvertisementPageReqVO pageReqVO) { + return advertisementMapper.selectPage(pageReqVO, false); + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsDetailService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsDetailService.java new file mode 100644 index 000000000..95b578893 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsDetailService.java @@ -0,0 +1,54 @@ +package com.cf.imes.module.system.service.products; + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.module.system.controller.admin.products.vo.productDetails.ProductDetailsPageReqVO; +import com.cf.imes.module.system.controller.admin.products.vo.productDetails.ProductDetailsSaveReqVO; +import com.cf.imes.module.system.dal.dataobject.products.ProductsDetailDO; + +import javax.validation.Valid; +import java.util.List; + +/** + * 产品明细表 product_details Service 接口 + * + * @author 晨丰科技 + */ +public interface ProductsDetailService { + + /** + * 创建产品明细(定价规则) + * + * @param createReqVO 产品明细内容 + * @return 编号 + */ + Long create(@Valid ProductDetailsSaveReqVO createReqVO); + + /** + * 更新产品 + * + * @param updateReqVO 更新信息 + */ + void update(@Valid ProductDetailsSaveReqVO updateReqVO); + + /** + * 删除产品 + * + * @param id 编号 + */ + void delete(Long id); + + /** + * 获得产品 + * + * @param id 编号 + */ + List get(Long id); + + /** + * 获得产品 分页 + * + * @param pageReqVO 分页查询 + */ + PageResult getPage(ProductDetailsPageReqVO pageReqVO); + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsDetailServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsDetailServiceImpl.java new file mode 100644 index 000000000..7eea99c78 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsDetailServiceImpl.java @@ -0,0 +1,253 @@ +package com.cf.imes.module.system.service.products; + +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.nacos.common.utils.StringUtils; +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.system.controller.admin.products.vo.productDetails.ProductDetailsPageReqVO; +import com.cf.imes.module.system.controller.admin.products.vo.productDetails.ProductDetailsSaveReqVO; +import com.cf.imes.module.system.dal.dataobject.products.ProductsDO; +import com.cf.imes.module.system.dal.dataobject.products.ProductsDetailDO; +import com.cf.imes.module.system.dal.mysql.products.ProductsDetailMapper; +import com.cf.imes.module.system.dal.mysql.products.ProductsMapper; +import com.cf.imes.module.system.enums.products.DurationUnitEnum; +import com.cf.imes.module.system.enums.products.ProductsPurchaseTypeEnum; +import com.cf.imes.module.system.util.SnowflakeIdWorker3rd; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.*; + +/** + * 产品明细 productsDetails Service 实现类 + * + * @author 晨丰科技 + */ +@Service +@Validated +public class ProductsDetailServiceImpl implements ProductsDetailService { + + @Resource + private ProductsDetailMapper productDetailsMapper; + + @Resource + private ProductsMapper productsMapper; + + @Resource + private SnowflakeIdWorker3rd idWorker; + + private static final String EMPTY_STRING = new String(); + private static final String DURATION_NUM = "\\d+"; + private static final String DURATION_UNIT = "[a-zA-Z]+"; + + @Override + public Long create(ProductDetailsSaveReqVO createReqVO) { +// 校验是否有这个产品 + validateProductExist(createReqVO.getProductId(), false); + + if (createReqVO.getPurchaseType() == ProductsPurchaseTypeEnum.DURATION.getStatus()) { + if (StringUtils.isBlank(createReqVO.getDuration())) { + throw exception(PRODUCTS_DURATION_NOT_NULL); + } +// 校验时长 + String duration = checkDuration(createReqVO.getDuration()); + String giftDuration = null; + if (createReqVO.getGiftDuration() != null) { + giftDuration = checkDuration(createReqVO.getGiftDuration()); + } + createReqVO.setDuration(duration).setGiftDuration(giftDuration); + +// 时长/产量 去重 + checkProductDetails(createReqVO, false); + } else if (createReqVO.getPurchaseType() == ProductsPurchaseTypeEnum.OUTPUT.getStatus()) { + if (StringUtils.isBlank(createReqVO.getDuration())) { + throw exception(PRODUCTS_OUTPUT_NOT_NULL); + } + } + + Long id = idWorker.nextId(); + createReqVO.setId(id); + ProductsDetailDO productDetailsDO = BeanUtils.toBean(createReqVO, ProductsDetailDO.class).setId(id); + productDetailsMapper.insert(productDetailsDO); + return id ; + } + +// 时长校验 + private String checkDuration(String duration){ + int number = extractDuration(duration); + String unit = extractDurationUnit(duration); + return number + "-" + unit; + } + +// 数字提取 + private int extractDuration(String duration) { + Pattern pattern = Pattern.compile(DURATION_NUM); + Matcher matcher = pattern.matcher(duration); + + List numbers = new ArrayList<>(); + while (matcher.find()) { + numbers.add(matcher.group()); + } + + if (numbers.size() != 1) { + throw exception(PRODUCTS_DURATION_NUM_ERR); + } + + String numberStr = numbers.get(0); + int number; + try { + number = Integer.parseInt(numberStr); + } catch (NumberFormatException e) { + throw exception(PRODUCTS_DURATION_NUM_ERR); + } + + // 校验数值是否为正整数(>0) + if (number < 0) { + throw exception(PRODUCTS_DURATION_INT_ERR); + } + + // 校验字符串格式(禁止前导零) + if (numberStr.startsWith("0") && numberStr.length() > 1) { + throw exception(PRODUCTS_DURATION_NUM_ERR); + } + + return number; + } + +// 时长单位提取 + private String extractDurationUnit(String duration){ + Pattern pattern = Pattern.compile(DURATION_UNIT); + Matcher matcher = pattern.matcher(duration); + + while (matcher.find()) { + String unit = matcher.group(); + if (DurationUnitEnum.isYear(unit)) { + return DurationUnitEnum.YEAR.getName(); + } else if (DurationUnitEnum.isMonth(unit)) { + return DurationUnitEnum.MONTH.getName(); + } else if (DurationUnitEnum.isDay(unit)) { + return DurationUnitEnum.DAY.getName(); + } + } + throw exception(PRODUCTS_DURATION_UNIT_ERR); + } +// 产品存在性校验 + private void validateProductExist(Long productId, boolean deleted){ + ProductsDO productsDO = productsMapper.selectOne(new LambdaQueryWrapperX() + .eq(ProductsDO::getId, productId) + .eq(ProductsDO::getDeleted, deleted)); + if (productsDO == null) { + throw exception(PRODUCTS_NO_EXIST); + } + } +// 时长/产量去重 + private void checkProductDetails(ProductDetailsSaveReqVO createReqVO, Boolean flag){ + int count; + if (createReqVO.getPurchaseType() == 0){ + //时长去重 + count = productDetailsMapper.selectCountByDuration(createReqVO.getDuration(), createReqVO.getProductId(), flag); + if (count > 0) { + throw exception(PRODUCTS_DETAIL_DURATION_EXIST); + } + }else if (createReqVO.getPurchaseType() == 1){ + //产量去重 + count = productDetailsMapper.selectCountByOutput(createReqVO.getOutput(), createReqVO.getProductId(), flag); + if (count > 0) { + throw exception(PRODUCTS_DETAIL_OUTPUT_EXIST); + } + } + } + + @Override + public void update(ProductDetailsSaveReqVO updateReqVO) { +// 校验是否有这个产品 + validateProductExist(updateReqVO.getProductId(), false); + + validateProductDetailsExists(updateReqVO.getId(), false); + + if (updateReqVO.getPurchaseType() == ProductsPurchaseTypeEnum.DURATION.getStatus()) { + if (StringUtils.isBlank(updateReqVO.getDuration())) { + throw exception(PRODUCTS_DURATION_NOT_NULL); + } +// 校验时长 + String duration = checkDuration(updateReqVO.getDuration()); + String giftDuration = null; + if (updateReqVO.getGiftDuration() != null) { + giftDuration = checkDuration(updateReqVO.getGiftDuration()); + } + updateReqVO.setDuration(duration).setGiftDuration(giftDuration); + +// 时长/产量 去重 + checkProductDetails(updateReqVO, true); + } else if (updateReqVO.getPurchaseType() == ProductsPurchaseTypeEnum.OUTPUT.getStatus()) { + if (StringUtils.isBlank(updateReqVO.getDuration())) { + throw exception(PRODUCTS_OUTPUT_NOT_NULL); + } + } + ProductsDetailDO productDetailsDO = BeanUtils.toBean(updateReqVO, ProductsDetailDO.class) + .setDiscount(getZeroBigDecimal(updateReqVO.getDiscount())) + .setOriginalPrice(getZeroBigDecimal(updateReqVO.getOriginalPrice())) + .setIsDiscounted(updateReqVO.getIsDiscounted() ? Boolean.TRUE : Boolean.FALSE); + productDetailsMapper.updateById(productDetailsDO); + } + + /** + * value为空返回EMPTY_STRING + * + * @param value + * @return + */ + private String getEmpty(String value) { + return StringUtils.defaultIfEmpty(value, EMPTY_STRING); + } + + /** + * value为空返回0.0 + * + * @param value + * @return + */ + private BigDecimal getZeroBigDecimal(BigDecimal value) { + return ObjectUtil.defaultIfNull(value, BigDecimal.ZERO); + } + + @Override + public void delete(Long id) { +// 判单是否存在 + validateProductDetailsExists(id, false); + productDetailsMapper.deleteById(id); + } + + @Override + public List get(Long id) { + validateProductDetailsExists(id, false); + return productDetailsMapper.selectList(); + } + + @Override + public PageResult getPage(ProductDetailsPageReqVO pageReqVO) { + return productDetailsMapper.selectPage(pageReqVO.setDeleted(0)); + } + +// 判断是否存在 + private void validateProductDetailsExists(Long id, boolean deleted) { + if (id == null) { + throw exception(PRODUCTS_DETAIL_NO_EXIST); + } + if (productDetailsMapper.selectOne(new LambdaQueryWrapperX() + .eq(ProductsDetailDO::getId, id) + .eq(ProductsDetailDO::getDeleted, false)) == null) { + throw exception(PRODUCTS_DETAIL_NO_EXIST); + } + } + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsService.java new file mode 100644 index 000000000..de4b43fe1 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsService.java @@ -0,0 +1,52 @@ +package com.cf.imes.module.system.service.products; + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.module.system.controller.admin.products.vo.product.ProductPageReqVO; +import com.cf.imes.module.system.dal.dataobject.products.ProductsDO; + +import javax.validation.Valid; + +/** + * 产品表 products Service 接口 + * + * @author 晨丰科技 + */ +public interface ProductsService { + + /** + * 创建产品 + * + * @param productName 产品名称 + * @return 编号 + */ + Long create(@Valid String productName); + + /** + * 更新产品 + * + * @param updateReqVO 更新信息 + */ + void update(@Valid ProductsDO updateReqVO); + + /** + * 删除产品 + * + * @param id 编号 + */ + void delete(Long id); + + /** + * 获得产品 + * + * @param id 编号 + */ + ProductsDO get(Long id); + + /** + * 获得产品 分页 + * + * @param pageReqVO 分页查询 + */ + PageResult getPage(ProductPageReqVO pageReqVO); + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsServiceImpl.java new file mode 100644 index 000000000..d239b225e --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/products/ProductsServiceImpl.java @@ -0,0 +1,86 @@ +package com.cf.imes.module.system.service.products; + + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.system.controller.admin.products.vo.product.ProductPageReqVO; +import com.cf.imes.module.system.dal.dataobject.products.ProductsDO; +import com.cf.imes.module.system.dal.mysql.products.ProductsMapper; +import com.cf.imes.module.system.util.SnowflakeIdWorker3rd; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_NO_EXIST; + +/** + * 产品 products Service 实现类 + * + * @author 晨丰科技 + */ +@Service +@Validated +public class ProductsServiceImpl implements ProductsService{ + + @Resource + private ProductsMapper productsMapper; + + @Resource + private SnowflakeIdWorker3rd idWorker; + + @Override + public Long create(String productName) { + Long id = idWorker.nextId(); + productsMapper.insert( + new ProductsDO() + .setId(id) + .setProductName(productName) + .setStatus(1) + .setSoftwareId(0) + ); + return id; + } + + @Override + public void update(ProductsDO updateReqVO) { + validateProductPlateExists(updateReqVO.getId()); + + productsMapper.updateById(updateReqVO); + } + + private void validateProductPlateExists(Long id) { + ProductsDO productsDO = getProductWithFalse(id); + if (productsDO == null) { + throw exception(PRODUCTS_NO_EXIST); + } + } + + public ProductsDO getProductWithFalse(Long id) { + return productsMapper.selectOne(new LambdaQueryWrapperX() + .eq(ProductsDO::getId, id) + .eq(ProductsDO::getDeleted, false)); + + } + + @Override + public void delete(Long id) { + validateProductPlateExists(id); + productsMapper.updateById( + new ProductsDO() + .setId(id) + .setDeleted(true) + ); + } + + @Override + public ProductsDO get(Long id) { + return getProductWithFalse(id); + } + + @Override + public PageResult getPage(ProductPageReqVO pageReqVO) { + return productsMapper.selectPage(pageReqVO, false); + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/recharge/RechargeActiveService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/recharge/RechargeActiveService.java new file mode 100644 index 000000000..491784d0d --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/recharge/RechargeActiveService.java @@ -0,0 +1,53 @@ +package com.cf.imes.module.system.service.recharge; + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.module.system.controller.admin.recharge.vo.RechargePageReqVO; +import com.cf.imes.module.system.controller.admin.recharge.vo.RechargeSaveReqVO; +import com.cf.imes.module.system.dal.dataobject.recharge.GiftMoneyDetailsDO; + +import javax.validation.Valid; + +/** + * 充值活动详情表 gift_money_details Service 接口 + * + * @author 晨丰科技 + */ +public interface RechargeActiveService { + + /** + * 创建充值活动 + * + * @param createReqVO + * @return 编号 + */ + Long create(@Valid RechargeSaveReqVO createReqVO); + + /** + * 更新充值活动 + * + * @param updateReqVO 更新信息 + */ + void update(@Valid RechargeSaveReqVO updateReqVO); + + /** + * 删除充值活动 + * + * @param id 编号 + */ + void delete(Long id); + + /** + * 获得充值活动 + * + * @param id 编号 + */ + GiftMoneyDetailsDO get(Long id); + + /** + * 获得充值活动 分页 + * + * @param pageReqVO 分页查询 + */ + PageResult getPage(RechargePageReqVO pageReqVO); + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/recharge/RechargeActiveServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/recharge/RechargeActiveServiceImpl.java new file mode 100644 index 000000000..50894949e --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/recharge/RechargeActiveServiceImpl.java @@ -0,0 +1,75 @@ +package com.cf.imes.module.system.service.recharge; + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.system.controller.admin.recharge.vo.RechargePageReqVO; +import com.cf.imes.module.system.controller.admin.recharge.vo.RechargeSaveReqVO; +import com.cf.imes.module.system.dal.dataobject.recharge.GiftMoneyDetailsDO; +import com.cf.imes.module.system.dal.mysql.recharge.GiftMoneyDetailsMapper; +import com.cf.imes.module.system.util.SnowflakeIdWorker3rd; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.RECHARGE_ACTIVE_NO_EXIST; + +/** + * 充值活动详情表 gift_money_details Service 实现类 + * + * @author 晨丰科技 + */ +@Service +@Validated +public class RechargeActiveServiceImpl implements RechargeActiveService{ + + @Resource + private SnowflakeIdWorker3rd idWorker; + + @Resource + private GiftMoneyDetailsMapper giftMoneyDetailsMapper; + + @Override + public Long create(RechargeSaveReqVO createReqVO) { + Long id = idWorker.nextId(); + GiftMoneyDetailsDO giftMoneyDetailsDOn = BeanUtils.toBean(createReqVO, GiftMoneyDetailsDO.class).setId(id); + giftMoneyDetailsMapper.insert(giftMoneyDetailsDOn); + return id; + } + + @Override + public void update(RechargeSaveReqVO updateReqVO) { + validateRechargeActiveExists(updateReqVO.getId(), false); + } + + // 校验是否存在 + private void validateRechargeActiveExists(Long id, boolean deleted) { + if (id == null) { + throw exception(RECHARGE_ACTIVE_NO_EXIST); + } + GiftMoneyDetailsDO dictType = giftMoneyDetailsMapper.selectOne(new LambdaQueryWrapperX() + .eq(GiftMoneyDetailsDO::getId, id) + .eq(GiftMoneyDetailsDO::getDeleted, deleted)); + if (dictType == null) { + throw exception(RECHARGE_ACTIVE_NO_EXIST); + } + } + @Override + public void delete(Long id) { + validateRechargeActiveExists(id, false); + giftMoneyDetailsMapper.deleteById(id); + } + + @Override + public GiftMoneyDetailsDO get(Long id) { + validateRechargeActiveExists(id, false); + return giftMoneyDetailsMapper.selectById(id); + } + + @Override + public PageResult getPage(RechargePageReqVO pageReqVO) { + return giftMoneyDetailsMapper.selectPage(pageReqVO); + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/util/SnowflakeIdWorker3rd.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/util/SnowflakeIdWorker3rd.java new file mode 100644 index 000000000..6ab065221 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/util/SnowflakeIdWorker3rd.java @@ -0,0 +1,63 @@ +package com.cf.imes.module.system.util; + +import org.springframework.stereotype.Component; + + +@Component +public class SnowflakeIdWorker3rd { + /** 初始时间 (2024-01-01 毫秒数: 1704038400000L) */ + private final long twepoch = 1704038400000L; + /** 序列号占位数 */ + private final long sequenceBits = 12L; + /** 时间戳左移位数 */ + private final long timestampLeftShift = 22L; // 12位序列号 + 10位预留 + /** 序列号掩码 */ + private final long sequenceMask = -1L ^ (-1L << sequenceBits); + /** 当前序列号 */ + private long sequence = 0L; + /** 上次生成ID的时间戳 */ + private long lastTimestamp = -1L; + + public synchronized long nextId() { + long timestamp = timeGen(); + if (timestamp < lastTimestamp) { + throw new RuntimeException("时钟回拨,无法生成ID。回拨时间:" + (lastTimestamp - timestamp) + "ms"); + } + + // 同一毫秒内生成序列号 + if (timestamp == lastTimestamp) { + sequence = (sequence + 1) & sequenceMask; + // 序列号溢出,等待下一毫秒 + if (sequence == 0) { + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0L; + } + + lastTimestamp = timestamp; + // 组合时间戳和序列号生成ID + return ((timestamp - twepoch) << timestampLeftShift) | sequence; + } + + /** 等待至下一毫秒 */ + private long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + /** 获取当前毫秒时间 */ + private long timeGen() { + return System.currentTimeMillis(); + } + + public static void main(String[] args) { + SnowflakeIdWorker3rd idWorker = new SnowflakeIdWorker3rd(); + for (int i = 0; i < 10; i++) { + System.out.println(idWorker.nextId()); + } + } +} \ No newline at end of file diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/advertisement/AdvertisementStatus.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/advertisement/AdvertisementStatus.java new file mode 100644 index 000000000..8eaef9e14 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/advertisement/AdvertisementStatus.java @@ -0,0 +1,28 @@ +package com.cf.imes.module.system.validation.advertisement; + + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +/** + * 广告状态校验注解 + * + * @author 晨丰科技 + */ +@Target({ + ElementType.FIELD, +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = {AdvertisementStatusValidator.class} +) +public @interface AdvertisementStatus { + String message() default "广告状态不合法,0:全部、1:未发布、2:已发布、3:已结束"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/advertisement/AdvertisementStatusValidator.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/advertisement/AdvertisementStatusValidator.java new file mode 100644 index 000000000..3a17345d4 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/advertisement/AdvertisementStatusValidator.java @@ -0,0 +1,31 @@ +package com.cf.imes.module.system.validation.advertisement; + + +import cn.hutool.core.util.ObjectUtil; +import com.cf.imes.module.system.enums.advertisement.AdvertisementStatusEnum; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.Objects; + +/** + * 广告状态校验器 + * + * @author 晨丰科技 + */ +public class AdvertisementStatusValidator implements ConstraintValidator { + + @Override + public boolean isValid(Integer value, ConstraintValidatorContext context) { + if (ObjectUtil.isNull(value)) { + return true; + } + for (AdvertisementStatusEnum statusEnum : AdvertisementStatusEnum.values()) { + if (Objects.equals(statusEnum.getStatus(), value)) { + return true; + } + } + return false; + } + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductStatus.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductStatus.java new file mode 100644 index 000000000..9169af9cc --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductStatus.java @@ -0,0 +1,27 @@ +package com.cf.imes.module.system.validation.products; + + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +/** + * 产品状态校验注解 + */ +@Target({ + ElementType.FIELD, +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = {ProductStatusValidator.class} +) +public @interface ProductStatus { + + String message() default "产品状态不合法,0:待上架 1:已上架 2:已下架"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductStatusValidator.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductStatusValidator.java new file mode 100644 index 000000000..a8858036e --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductStatusValidator.java @@ -0,0 +1,27 @@ +package com.cf.imes.module.system.validation.products; + +import cn.hutool.core.util.ObjectUtil; +import com.cf.imes.module.system.enums.products.ProductStatusEnum; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.Objects; + +/** + * 产品状态校验器 + */ +public class ProductStatusValidator implements ConstraintValidator { + + @Override + public boolean isValid(Integer value, ConstraintValidatorContext context) { + if (ObjectUtil.isNull(value)) { + return true; + } + for (ProductStatusEnum statusEnum : ProductStatusEnum.values()) { + if (Objects.equals(statusEnum.getStatus(), value)) { + return true; + } + } + return false; + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductType.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductType.java new file mode 100644 index 000000000..ae5e93383 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductType.java @@ -0,0 +1,25 @@ +package com.cf.imes.module.system.validation.products; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +/** + * 产品详情购买方式校验注解 + */ +@Target({ + ElementType.FIELD, +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = {ProductTypeValidator.class} +) +public @interface ProductType { + + String message() default "购买方式:0 时长;1 产量"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductTypeValidator.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductTypeValidator.java new file mode 100644 index 000000000..18bd001c1 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductTypeValidator.java @@ -0,0 +1,28 @@ +package com.cf.imes.module.system.validation.products; + +import cn.hutool.core.util.ObjectUtil; +import com.cf.imes.module.system.enums.products.ProductsPurchaseTypeEnum; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.Objects; + +/** + * 产品详情购买方式校验器 + */ +public class ProductTypeValidator implements ConstraintValidator { + + @Override + public boolean isValid(Integer value, ConstraintValidatorContext context) { + if (ObjectUtil.isNull(value)) { + return true; + } + for (ProductsPurchaseTypeEnum statusEnum : ProductsPurchaseTypeEnum.values()) { + if (Objects.equals(statusEnum.getStatus(), value)) { + return true; + } + } + return false; + } + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/MoneyValid.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/MoneyValid.java new file mode 100644 index 000000000..89d0bad42 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/MoneyValid.java @@ -0,0 +1,58 @@ +package com.cf.imes.module.system.validation.recharge; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +/** + * 自定义Double校验注解 + * + */ +@Target({ + ElementType.METHOD, + ElementType.FIELD, + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.PARAMETER, + ElementType.TYPE_USE +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = MoneyValidator.class +) +public @interface MoneyValid { + + /** + * 字段中文名 + * + * @return + */ + String name(); + + /** + * 校验提示信息 + * + * @return + */ + String message() default "数字不合法"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + /** + * 整数最大位数 + * + * @return + */ + int integer() default 7; + + /** + * 小数点后的最大位数 + * + * @return + */ + int fraction() default 3; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/MoneyValidator.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/MoneyValidator.java new file mode 100644 index 000000000..5aa93fed1 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/MoneyValidator.java @@ -0,0 +1,87 @@ +package com.cf.imes.module.system.validation.recharge; + +import cn.hutool.core.util.ObjectUtil; +import org.apache.commons.lang3.StringUtils; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.math.BigDecimal; + +/** + * Double类型校验器 + */ +public class MoneyValidator implements ConstraintValidator { + + private static final String ZERO = "0"; + private static final String GREATER_THAN_ZERO_NOTIFICATION = "%s必须大于0"; + private static final String LENGTH_ERROR_NOTIFICATION = "%s长度不合法,总长度不超过%d位,小数点后不超过%d位"; + + private String name; + private int maxIntegerDigits; + private int maxFractionDigits; + + @Override + public void initialize(MoneyValid constraintAnnotation) { + this.name = constraintAnnotation.name(); + this.maxIntegerDigits = constraintAnnotation.integer(); + this.maxFractionDigits = constraintAnnotation.fraction(); + } + + @Override + public boolean isValid(Number value, ConstraintValidatorContext context) { + if (ObjectUtil.isNull(value)) { + return true; + } + + String errorMessage = null; + if (value instanceof Integer) { + errorMessage = handleInteger((Integer) value); + } else if (value instanceof Long) { + errorMessage = handleLong((Long) value); + } else if (value instanceof Double) { + errorMessage = handleDouble((Double) value); + } else if (value instanceof BigDecimal) { + errorMessage = handleBigDecimal((BigDecimal) value); + } + + if (StringUtils.isNotEmpty(errorMessage)) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(errorMessage).addConstraintViolation(); + return false; + } + return true; + } + + private String handleInteger(Integer value) { + if (value <= 0) { + return String.format(GREATER_THAN_ZERO_NOTIFICATION, name); + } + return null; + } + + private String handleLong(Long value) { + if (value <= 0) { + return String.format(GREATER_THAN_ZERO_NOTIFICATION, name); + } + return null; + } + + private String handleDouble(Double value) { + return handleBigDecimal(new BigDecimal(value.toString())); + } + + private String handleBigDecimal(BigDecimal value) { + if (value.compareTo(BigDecimal.ZERO) <= 0) { + return String.format(GREATER_THAN_ZERO_NOTIFICATION, name); + } + + String[] parts = value.toPlainString().split("\\."); + int integerPartLength = parts[0].length(); + int fractionalPartLength = parts.length > 1 ? parts[1].length() : 0; + + if (integerPartLength > maxIntegerDigits || fractionalPartLength > maxFractionDigits) { + return String.format(LENGTH_ERROR_NOTIFICATION, name, maxIntegerDigits + maxFractionDigits, maxFractionDigits); + } + return null; + } +} \ No newline at end of file diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/PurchaseType.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/PurchaseType.java new file mode 100644 index 000000000..2cc9f0e2d --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/PurchaseType.java @@ -0,0 +1,26 @@ +package com.cf.imes.module.system.validation.recharge; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +/** + * 赠送类型校验注解 + */ +@Target({ + ElementType.FIELD, +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = {PurchaseTypeValidator.class} +) +public @interface PurchaseType { + + String message() default "赠送类型不合法,0:满X送X; 1:每满X送X"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/PurchaseTypeValidator.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/PurchaseTypeValidator.java new file mode 100644 index 000000000..3c0eda063 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/PurchaseTypeValidator.java @@ -0,0 +1,27 @@ +package com.cf.imes.module.system.validation.recharge; + +import cn.hutool.core.util.ObjectUtil; +import com.cf.imes.module.system.enums.recharge.PurchaseTypeEnum; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.Objects; + +/** + * 赠送类型校验器 + */ +public class PurchaseTypeValidator implements ConstraintValidator { + + @Override + public boolean isValid(Integer value, ConstraintValidatorContext context) { + if (ObjectUtil.isNull(value)) { + return true; + } + for (PurchaseTypeEnum statusEnum : PurchaseTypeEnum.values()) { + if (Objects.equals(statusEnum.getStatus(), value)) { + return true; + } + } + return false; + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/RechargeType.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/RechargeType.java new file mode 100644 index 000000000..b6a827359 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/RechargeType.java @@ -0,0 +1,26 @@ +package com.cf.imes.module.system.validation.recharge; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +/** + * 充值类型校验注解 + */ +@Target({ + ElementType.FIELD, +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = {RechargeTypeValidator.class} +) +public @interface RechargeType { + + String message() default "充值类型不合法, 0:微信、支付宝 1:微信 2:支付宝"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/RechargeTypeValidator.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/RechargeTypeValidator.java new file mode 100644 index 000000000..ced350199 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/recharge/RechargeTypeValidator.java @@ -0,0 +1,26 @@ +package com.cf.imes.module.system.validation.recharge; + +import cn.hutool.core.util.ObjectUtil; +import com.cf.imes.module.system.enums.recharge.RechargeTypeEnum; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.Objects; + +/** + * 充值类型校验器 + */ +public class RechargeTypeValidator implements ConstraintValidator { + @Override + public boolean isValid(Integer value, ConstraintValidatorContext context) { + if (ObjectUtil.isNull(value)) { + return true; + } + for (RechargeTypeEnum statusEnum : RechargeTypeEnum.values()) { + if (Objects.equals(statusEnum.getStatus(), value)) { + return true; + } + } + return false; + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml b/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml index 45b92e419..e43534b45 100644 --- a/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml +++ b/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml @@ -138,6 +138,7 @@ chenfeng: info: version: 1.0.0 base-package: com.cf.imes.module.system + name: 晨丰 web: admin-ui: url: http://dashboard.chenfeng.iocoder.cn # Admin 管理后台 UI 的地址 @@ -204,6 +205,10 @@ chenfeng: - system_machine_brand - system_machine_limit - system_config_token + - products_detail + - products + - advertisement + - system_advertisement_task use-data-code: imes_prod #动态数据源标识,后期添加的数据源需要修改此值 sms-code: # 短信验证码相关的配置项