Browse Source

【第一版开发】
1.优化代码
2.修复若干问题

ChenYL 10 months ago
parent
commit
1769f0b269
31 changed files with 441 additions and 208 deletions
  1. 8 1
      data-easy/src/main/java/com/dataeasy/server/atomic/entity/SubscriptionOrder.java
  2. 6 0
      data-easy/src/main/java/com/dataeasy/server/atomic/entity/SubscriptionSource.java
  3. 8 9
      data-easy/src/main/java/com/dataeasy/server/atomic/entity/SubscriptionUserConfig.java
  4. 11 32
      data-easy/src/main/java/com/dataeasy/server/atomic/entity/SubscriptionUserLog.java
  5. 7 0
      data-easy/src/main/java/com/dataeasy/server/atomic/service/ISubscriptionUserConfigService.java
  6. 6 0
      data-easy/src/main/java/com/dataeasy/server/atomic/service/ISubscriptionUserLogService.java
  7. 2 3
      data-easy/src/main/java/com/dataeasy/server/atomic/service/impl/SubscriptionSourceServiceImpl.java
  8. 16 5
      data-easy/src/main/java/com/dataeasy/server/atomic/service/impl/SubscriptionUserConfigServiceImpl.java
  9. 8 1
      data-easy/src/main/java/com/dataeasy/server/atomic/service/impl/SubscriptionUserLogServiceImpl.java
  10. 25 0
      data-easy/src/main/java/com/dataeasy/server/common/annotation/DataAuth.java
  11. 8 0
      data-easy/src/main/java/com/dataeasy/server/constant/CacheNameConstant.java
  12. 2 1
      data-easy/src/main/java/com/dataeasy/server/constant/ScheduleTaskEnum.java
  13. 71 0
      data-easy/src/main/java/com/dataeasy/server/core/aop/DataAuthAspect.java
  14. 5 2
      data-easy/src/main/java/com/dataeasy/server/core/handler/WxMpSubscribeHandler.java
  15. 2 2
      data-easy/src/main/java/com/dataeasy/server/pojo/subscription/SubscriptionSourceQuery.java
  16. 3 3
      data-easy/src/main/java/com/dataeasy/server/pojo/subscription/SubscriptionUserConfigQuery.java
  17. 2 2
      data-easy/src/main/java/com/dataeasy/server/service/controller/DataController.java
  18. 9 0
      data-easy/src/main/java/com/dataeasy/server/service/controller/TaskOpController.java
  19. 7 0
      data-easy/src/main/java/com/dataeasy/server/service/manager/IOrderManager.java
  20. 0 12
      data-easy/src/main/java/com/dataeasy/server/service/manager/IOrderService.java
  21. 6 0
      data-easy/src/main/java/com/dataeasy/server/service/manager/impl/DataManagerImpl.java
  22. 102 4
      data-easy/src/main/java/com/dataeasy/server/service/manager/impl/OrderManagerImpl.java
  23. 6 7
      data-easy/src/main/java/com/dataeasy/server/service/manager/impl/SubscriptionManagerImpl.java
  24. 2 1
      data-easy/src/main/java/com/dataeasy/server/service/manager/impl/UserManagerImpl.java
  25. 13 48
      data-easy/src/main/java/com/dataeasy/server/service/manager/impl/WxManagerImpl.java
  26. 5 5
      data-easy/src/main/java/com/dataeasy/server/task/AbstractDataTask.java
  27. 31 0
      data-easy/src/main/java/com/dataeasy/server/task/AutoDeleteSubscriptionUserConfigTask.java
  28. 0 24
      data-easy/src/main/java/com/dataeasy/server/utiis/DateUtils.java
  29. 3 3
      doc/sql/data.sql
  30. 25 0
      doc/sql/schema.sql
  31. 42 43
      doc/技术文档.md

+ 8 - 1
data-easy/src/main/java/com/dataeasy/server/atomic/entity/SubscriptionOrder.java

@@ -11,6 +11,7 @@ import java.io.Serial;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.sql.Timestamp;
+import java.time.LocalDateTime;
 
 /**
  * @author tyuio
@@ -50,6 +51,12 @@ public class SubscriptionOrder extends BaseEntity implements Serializable {
     @Column(name = "order_no")
     private String orderNo;
 
+    /**
+     * 微信支付订单号
+     */
+    @Column(name = "transaction_id")
+    private String transactionId;
+
     /**
      * 订阅价格(单位:元)
      */
@@ -66,7 +73,7 @@ public class SubscriptionOrder extends BaseEntity implements Serializable {
      * 订单关闭时间
      */
     @Column(name = "close_time")
-    private Timestamp closeTime;
+    private LocalDateTime closeTime;
 
     /**
      * 支付状态(NOTPAY-未支付,SUCCESS-支付成功、REFUND-转入退款、CLOSED-已关闭、REVOKED-已撤销)

+ 6 - 0
data-easy/src/main/java/com/dataeasy/server/atomic/entity/SubscriptionSource.java

@@ -24,6 +24,12 @@ public class SubscriptionSource extends BaseEntity implements Serializable {
     @Serial
     private static final long serialVersionUID = -5513593762548197292L;
 
+    /**
+     * 订阅源编码
+     */
+    @Column(name = "code")
+    private String code;
+
     /**
      * 主标题
      */

+ 8 - 9
data-easy/src/main/java/com/dataeasy/server/atomic/entity/SubscriptionUserConfig.java

@@ -9,8 +9,7 @@ import lombok.EqualsAndHashCode;
 
 import java.io.Serial;
 import java.io.Serializable;
-import java.sql.Timestamp;
-import java.util.Date;
+import java.time.LocalDate;
 
 /**
  * @author tyuio
@@ -33,22 +32,22 @@ public class SubscriptionUserConfig extends BaseEntity implements Serializable {
     private Long userId;
 
     /**
-     * 订阅源ID
+     * 订阅源编码
      */
-    @Column(name = "subscription_source_id")
-    private Long subscriptionSourceId;
+    @Column(name = "subscription_source_code")
+    private String subscriptionSourceCode;
 
     /**
      * 订阅开始时间
      */
-    @Column(name = "start_time")
-    private Timestamp startTime;
+    @Column(name = "start_date")
+    private LocalDate startDate;
 
     /**
      * 订阅结束时间
      */
-    @Column(name = "end_time")
-    private Timestamp endTime;
+    @Column(name = "end_date")
+    private LocalDate endDate;
 
     /**
      * 消息推送选项(ENABLE-开启、DISABLE-关闭)

+ 11 - 32
data-easy/src/main/java/com/dataeasy/server/atomic/entity/SubscriptionUserLog.java

@@ -1,6 +1,7 @@
 package com.dataeasy.server.atomic.entity;
 
 import com.dataeasy.server.common.pojo.BaseEntity;
+import com.dataeasy.server.constant.PaidOptionEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
 import lombok.Data;
@@ -9,6 +10,7 @@ import lombok.EqualsAndHashCode;
 import java.io.Serial;
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.time.LocalDate;
 import java.util.Date;
 
 /**
@@ -32,56 +34,33 @@ public class SubscriptionUserLog extends BaseEntity implements Serializable {
     private Long userId;
 
     /**
-     * 订阅源ID
-     */
-    @Column(name = "subscription_source_id")
-    private Long subscriptionSourceId;
-
-    /**
-     * 订阅价格计划ID
-     */
-    @Column(name = "subscription_plan_id")
-    private Long subscriptionPlanId;
-
-    /**
-     * 订单ID
+     * 订单ID(付费才有)
      */
     @Column(name = "subscription_order_id")
     private Long subscriptionOrderId;
 
     /**
      * 付费选项(FREE-免费、PAID-付费)
+     * @see PaidOptionEnum
      */
     @Column(name = "paid_option")
-    private String paidOption;
-
-    /**
-     * 订阅价格(单位:元)
-     */
-    @Column(name = "subscription_price")
-    private BigDecimal subscriptionPrice;
-
-    /**
-     * 本次订阅时长(单位:天)
-     */
-    @Column(name = "subscription_duration")
-    private Integer subscriptionDuration;
+    private PaidOptionEnum paidOption;
 
     /**
      * 订阅前开始时间
      */
-    @Column(name = "start_time")
-    private Date startTime;
+    @Column(name = "start_date")
+    private LocalDate startDate;
 
     /**
      * 订阅前结束时间
      */
-    @Column(name = "before_end_time")
-    private Date beforeEndTime;
+    @Column(name = "before_end_date")
+    private LocalDate beforeEndDate;
 
     /**
      * 订阅后结束时间
      */
-    @Column(name = "after_end_time")
-    private Date afterEndTime;
+    @Column(name = "after_end_date")
+    private LocalDate afterEndDate;
 }

+ 7 - 0
data-easy/src/main/java/com/dataeasy/server/atomic/service/ISubscriptionUserConfigService.java

@@ -3,6 +3,7 @@ package com.dataeasy.server.atomic.service;
 import com.dataeasy.server.atomic.entity.SubscriptionUserConfig;
 import com.dataeasy.server.pojo.subscription.SubscriptionUserConfigQuery;
 
+import java.time.LocalDate;
 import java.util.List;
 
 /**
@@ -31,4 +32,10 @@ public interface ISubscriptionUserConfigService {
      * @param subscriptionUserConfig
      */
     void insert(SubscriptionUserConfig subscriptionUserConfig);
+
+    /**
+     * 删除过期的记录,根据订阅结束时间判断,小于当前时间即为过期
+     * @param currentDate
+     */
+    void deleteExpireConfig(LocalDate currentDate);
 }

+ 6 - 0
data-easy/src/main/java/com/dataeasy/server/atomic/service/ISubscriptionUserLogService.java

@@ -1,5 +1,7 @@
 package com.dataeasy.server.atomic.service;
 
+import com.dataeasy.server.atomic.entity.SubscriptionUserLog;
+
 /**
  * @author tyuio
  * @version 1.0.0
@@ -8,4 +10,8 @@ package com.dataeasy.server.atomic.service;
  */
 public interface ISubscriptionUserLogService {
 
+    /**
+     * 新增记录
+     */
+    void insert(SubscriptionUserLog subscriptionUserLog);
 }

+ 2 - 3
data-easy/src/main/java/com/dataeasy/server/atomic/service/impl/SubscriptionSourceServiceImpl.java

@@ -9,7 +9,6 @@ import org.springframework.stereotype.Service;
 import com.dataeasy.server.atomic.mapper.SubscriptionSourceMapper;
 import com.dataeasy.server.atomic.service.ISubscriptionSourceService;
 import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
 import tk.mybatis.mapper.weekend.Weekend;
 import tk.mybatis.mapper.weekend.WeekendCriteria;
 
@@ -36,8 +35,8 @@ public class SubscriptionSourceServiceImpl implements ISubscriptionSourceService
 
         Weekend<SubscriptionSource> weekend = WeekendUtils.createExcludeAuditFields(SubscriptionSource.class);
         WeekendCriteria<SubscriptionSource, Object> weekendCriteria = weekend.weekendCriteria();
-        if (!CollectionUtils.isEmpty(query.getIds())) {
-            weekendCriteria.andIn(SubscriptionSource::getId, query.getIds());
+        if (!CollectionUtils.isEmpty(query.getSubscriptionSourceCodeList())) {
+            weekendCriteria.andIn(SubscriptionSource::getCode, query.getSubscriptionSourceCodeList());
         }
         return subscriptionSourceMapper.selectByExample(weekend);
     }

+ 16 - 5
data-easy/src/main/java/com/dataeasy/server/atomic/service/impl/SubscriptionUserConfigServiceImpl.java

@@ -13,6 +13,7 @@ import org.springframework.util.CollectionUtils;
 import tk.mybatis.mapper.weekend.Weekend;
 import tk.mybatis.mapper.weekend.WeekendCriteria;
 
+import java.time.LocalDate;
 import java.util.List;
 import java.util.Objects;
 
@@ -35,15 +36,15 @@ public class SubscriptionUserConfigServiceImpl implements ISubscriptionUserConfi
         }
         Weekend<SubscriptionUserConfig> weekend = WeekendUtils.createExcludeAuditFields(SubscriptionUserConfig.class);
         WeekendCriteria<SubscriptionUserConfig, Object> weekendCriteria = weekend.weekendCriteria();
-        if (!CollectionUtils.isEmpty(query.getSubscriptionSourceIds())) {
-            weekendCriteria.andIn(SubscriptionUserConfig::getSubscriptionSourceId, query.getSubscriptionSourceIds());
+        if (!CollectionUtils.isEmpty(query.getSubscriptionSourceCodeList())) {
+            weekendCriteria.andIn(SubscriptionUserConfig::getSubscriptionSourceCode, query.getSubscriptionSourceCodeList());
         }
         if (Objects.nonNull(query.getPushOption())) {
             weekendCriteria.andEqualTo(SubscriptionUserConfig::getPushOption, query.getPushOption());
         }
-        if (Objects.nonNull(query.getCurrentTime())) {
-            weekendCriteria.andLessThanOrEqualTo(SubscriptionUserConfig::getStartTime, query.getCurrentTime());
-            weekendCriteria.andGreaterThanOrEqualTo(SubscriptionUserConfig::getEndTime, query.getCurrentTime());
+        if (Objects.nonNull(query.getCurrentDate())) {
+            weekendCriteria.andLessThanOrEqualTo(SubscriptionUserConfig::getStartDate, query.getCurrentDate());
+            weekendCriteria.andGreaterThanOrEqualTo(SubscriptionUserConfig::getEndDate, query.getCurrentDate());
         }
         if (Objects.nonNull(query.getUserId())) {
             weekendCriteria.andEqualTo(SubscriptionUserConfig::getUserId, query.getUserId());
@@ -62,4 +63,14 @@ public class SubscriptionUserConfigServiceImpl implements ISubscriptionUserConfi
         Assert.isNull(subscriptionUserConfig);
         subscriptionUserConfigMapper.insertSelective(subscriptionUserConfig);
     }
+
+    @Override
+    public void deleteExpireConfig(LocalDate currentDate) {
+        Assert.isNull(currentDate);
+
+        Weekend<SubscriptionUserConfig> weekend = Weekend.of(SubscriptionUserConfig.class);
+        WeekendCriteria<SubscriptionUserConfig, Object> criteria = weekend.weekendCriteria();
+        criteria.andLessThan(SubscriptionUserConfig::getEndDate, currentDate);
+        subscriptionUserConfigMapper.deleteByExample(weekend);
+    }
 }

+ 8 - 1
data-easy/src/main/java/com/dataeasy/server/atomic/service/impl/SubscriptionUserLogServiceImpl.java

@@ -1,5 +1,7 @@
 package com.dataeasy.server.atomic.service.impl;
 
+import com.dataeasy.server.atomic.entity.SubscriptionUserLog;
+import com.dataeasy.server.common.utils.Assert;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -16,6 +18,11 @@ import com.dataeasy.server.atomic.service.ISubscriptionUserLogService;
 public class SubscriptionUserLogServiceImpl implements ISubscriptionUserLogService {
 
     @Autowired
-    private SubscriptionUserLogMapper mapper;
+    private SubscriptionUserLogMapper subscriptionUserLogMapper;
 
+    @Override
+    public void insert(SubscriptionUserLog subscriptionUserLog) {
+        Assert.isNull(subscriptionUserLog);
+        subscriptionUserLogMapper.insert(subscriptionUserLog);
+    }
 }

+ 25 - 0
data-easy/src/main/java/com/dataeasy/server/common/annotation/DataAuth.java

@@ -0,0 +1,25 @@
+package com.dataeasy.server.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/3/18 15:29
+ * @description 数据访问权限注解
+ */
+@Documented
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DataAuth {
+
+    /**
+     * 订阅源编码
+     * @return
+     */
+    String value();
+}

+ 8 - 0
data-easy/src/main/java/com/dataeasy/server/constant/CacheNameConstant.java

@@ -58,5 +58,13 @@ public class CacheNameConstant {
      */
     public static final String DATA_SHUANG_SE_QIU_LIST = "dataShuangSeQiuList";
 
+    /**
+     * 微信关注事件
+     */
+    public static final String WX_SUBSCRIBE_EVENT = "wxSubscribeEvent";
 
+    /**
+     * 微信取消关注事件
+     */
+    public static final String WX_UNSUBSCRIBE_EVENT = "wxUnsubscribeEvent";
 }

+ 2 - 1
data-easy/src/main/java/com/dataeasy/server/constant/ScheduleTaskEnum.java

@@ -21,7 +21,8 @@ public enum ScheduleTaskEnum {
     IPO_BOND("新债定时任务"),
     IPO_STOCK("新股定时任务"),
     PRODUCT_HUNT("ProductHunt热榜定时任务"),
-    AUTO_CLOSE_PAY_ORDER("支付订单自动关闭定时任务");
+    AUTO_CLOSE_PAY_ORDER("支付订单自动关闭定时任务"),
+    AUTO_DELETE_SUBSCRIPTION_USER_CONFIG("用户订阅源配置过期自动删除");
 
     private String name;
 

+ 71 - 0
data-easy/src/main/java/com/dataeasy/server/core/aop/DataAuthAspect.java

@@ -0,0 +1,71 @@
+package com.dataeasy.server.core.aop;
+
+import java.lang.reflect.Method;
+import java.time.LocalDate;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import com.dataeasy.server.atomic.entity.SubscriptionUserConfig;
+import com.dataeasy.server.atomic.service.ISubscriptionUserConfigService;
+import com.dataeasy.server.common.annotation.DataAuth;
+import com.dataeasy.server.common.exception.BusinessException;
+import com.dataeasy.server.pojo.subscription.SubscriptionUserConfigQuery;
+import com.dataeasy.server.utiis.UserUtils;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/3/18 15:32
+ * @description 数据访问权限切面
+ */
+@Slf4j
+@Aspect
+@Component
+public class DataAuthAspect {
+
+    @Autowired
+    private ISubscriptionUserConfigService subscriptionUserConfigService;
+
+    @Pointcut("execution(* com.dataeasy.server.service.manager.impl.DataManagerImpl.*(..)) and @annotation(com.dataeasy.server.common.annotation.DataAuth)")
+    public void pointcut() {}
+
+    @Around("pointcut()")
+    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
+        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+        Method method = methodSignature.getMethod();
+
+        // 获取方法上的注解
+        DataAuth dataAuth = method.getAnnotation(DataAuth.class);
+
+        // 不存在则放行
+        if (Objects.isNull(dataAuth)) {
+            return joinPoint.proceed();
+        }
+
+        SubscriptionUserConfigQuery subscriptionUserConfigQuery = new SubscriptionUserConfigQuery();
+        subscriptionUserConfigQuery.setUserId(UserUtils.getCurrentUserId());
+        subscriptionUserConfigQuery.setCurrentDate(LocalDate.now());
+        subscriptionUserConfigQuery.setSubscriptionSourceCodeList(Arrays.asList(dataAuth.value()));
+        List<SubscriptionUserConfig> subscriptionUserConfigList = subscriptionUserConfigService.getByCondition(subscriptionUserConfigQuery);
+        if (CollectionUtils.isEmpty(subscriptionUserConfigList)) {
+            throw BusinessException.fail("您没有权限访问该数据,请先订阅数据源");
+        }
+        if (subscriptionUserConfigList.size() > 1) {
+            throw BusinessException.fail("数据访问异常,订阅源配置错误,订阅源数量大于1");
+        }
+
+        return joinPoint.proceed();
+    }
+}

+ 5 - 2
data-easy/src/main/java/com/dataeasy/server/core/handler/WxMpSubscribeHandler.java

@@ -3,9 +3,8 @@ package com.dataeasy.server.core.handler;
 import java.util.Map;
 import java.util.Objects;
 
-import me.chanjar.weixin.mp.api.WxMpUserService;
-import me.chanjar.weixin.mp.bean.result.WxMpUser;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.CacheManager;
 import org.springframework.stereotype.Component;
 
 import com.dataeasy.server.atomic.entity.User;
@@ -18,6 +17,7 @@ import me.chanjar.weixin.mp.api.WxMpMessageHandler;
 import me.chanjar.weixin.mp.api.WxMpService;
 import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
 import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.result.WxMpUser;
 import me.chanjar.weixin.mp.builder.outxml.TextBuilder;
 
 /**
@@ -33,6 +33,9 @@ public class WxMpSubscribeHandler implements WxMpMessageHandler {
     @Autowired
     private IUserService userService;
 
+    @Autowired
+    private CacheManager cacheManager;
+
     @Override
     public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                     Map<String, Object> context, WxMpService weixinService,

+ 2 - 2
data-easy/src/main/java/com/dataeasy/server/pojo/subscription/SubscriptionSourceQuery.java

@@ -14,7 +14,7 @@ import lombok.Data;
 public class SubscriptionSourceQuery {
 
     /**
-     * 订阅源ID
+     * 订阅源编码列表
      */
-    private Collection<Long> ids;
+    private Collection<String> subscriptionSourceCodeList;
 }

+ 3 - 3
data-easy/src/main/java/com/dataeasy/server/pojo/subscription/SubscriptionUserConfigQuery.java

@@ -1,6 +1,6 @@
 package com.dataeasy.server.pojo.subscription;
 
-import java.sql.Timestamp;
+import java.time.LocalDate;
 import java.util.Collection;
 
 import com.dataeasy.server.constant.PushOptionEnum;
@@ -24,7 +24,7 @@ public class SubscriptionUserConfigQuery {
     /**
      * 订阅源ID
      */
-    private Collection<Long> subscriptionSourceIds;
+    private Collection<String> subscriptionSourceCodeList;
 
     /**
      * 消息推送选项(ENABLE-开启、DISABLE-关闭)
@@ -35,5 +35,5 @@ public class SubscriptionUserConfigQuery {
     /**
      * 推送时间/当前时间
      */
-    private Timestamp currentTime;
+    private LocalDate currentDate;
 }

+ 2 - 2
data-easy/src/main/java/com/dataeasy/server/service/controller/DataController.java

@@ -54,7 +54,7 @@ public class DataController {
      * 查询大乐透开奖数据
      */
     @GetMapping("/queryDaLeTou")
-    public DaLeTouVO queryDaLeTou(@RequestParam @NotBlank(message = "开奖期不能为空") String drawDate) {
+    public DaLeTouVO queryDaLeTou(@RequestParam @NotBlank(message = "开奖期不能为空") String drawDate) {
         return dataManager.queryDaLeTou(drawDate);
     }
 
@@ -62,7 +62,7 @@ public class DataController {
      * 查询双色球数据
      */
     @GetMapping("/queryShuangSeQiu")
-    public ShuangSeQiuVO queryShuangSeQiu(@RequestParam @NotBlank(message = "开奖期不能为空") String drawDate) {
+    public ShuangSeQiuVO queryShuangSeQiu(@RequestParam @NotBlank(message = "开奖期不能为空") String drawDate) {
         return dataManager.queryShuangSeQiu(drawDate);
     }
 

+ 9 - 0
data-easy/src/main/java/com/dataeasy/server/service/controller/TaskOpController.java

@@ -1,6 +1,7 @@
 package com.dataeasy.server.service.controller;
 
 import com.dataeasy.server.task.AutoCLosePayOrderTask;
+import com.dataeasy.server.task.AutoDeleteSubscriptionUserConfigTask;
 import com.dataeasy.server.task.DaLeTouTask;
 import com.dataeasy.server.task.IpoBondTask;
 import com.dataeasy.server.task.IpoStockTask;
@@ -39,6 +40,9 @@ public class TaskOpController {
     @Autowired
     private AutoCLosePayOrderTask autoCLosePayOrderTask;
 
+    @Autowired
+    private AutoDeleteSubscriptionUserConfigTask autoDeleteSubscriptionUserConfigTask;
+
     /**
      * 大乐透定时任务
      */
@@ -83,4 +87,9 @@ public class TaskOpController {
     public void autoCloseOrderTask() {
         autoCLosePayOrderTask.execute();
     }
+
+    @GetMapping("autoDeleteSubscriptionUserConfigTask")
+    public void autoDeleteSubscriptionUserConfigTask() {
+        autoDeleteSubscriptionUserConfigTask.execute();
+    }
 }

+ 7 - 0
data-easy/src/main/java/com/dataeasy/server/service/manager/IOrderManager.java

@@ -18,4 +18,11 @@ public interface IOrderManager {
      * @return
      */
     WxPayUnifiedOrderV3Result.JsapiResult createOrder(SubscriptionOrderRequest request) throws WxPayException;
+
+    /**
+     * 处理订单
+     * @param orderNo 订单号
+     * @param transactionId 微信支付订单号
+     */
+    void successHandler(String orderNo, String transactionId);
 }

+ 0 - 12
data-easy/src/main/java/com/dataeasy/server/service/manager/IOrderService.java

@@ -1,12 +0,0 @@
-package com.dataeasy.server.service.manager;
-
-/**
- * @author tyuio
- * @version 1.0.0
- * @date 2025/3/11 11:17
- * @description 订单服务类
- */
-public interface IOrderService {
-
-
-}

+ 6 - 0
data-easy/src/main/java/com/dataeasy/server/service/manager/impl/DataManagerImpl.java

@@ -10,6 +10,7 @@ import com.dataeasy.server.atomic.service.IDataIpoBondService;
 import com.dataeasy.server.atomic.service.IDataIpoStockService;
 import com.dataeasy.server.atomic.service.IDataProductHuntPostService;
 import com.dataeasy.server.atomic.service.IDataShuangSeQiuService;
+import com.dataeasy.server.common.annotation.DataAuth;
 import com.dataeasy.server.constant.CacheNameConstant;
 import com.dataeasy.server.pojo.data.DaLeTouVO;
 import com.dataeasy.server.pojo.data.IpoBondVO;
@@ -55,6 +56,7 @@ public class DataManagerImpl implements IDataManager {
     private IDataShuangSeQiuService shuangSeQiuService;
 
     @Override
+    @DataAuth("IPO_BOND")
     @Cacheable(cacheNames = CacheNameConstant.DATA_IPO_BOND_LIST, key = "#subscriptionDate",
             condition = "#subscriptionDate != null and !#subscriptionDate.isBlank()")
     public List<IpoBondVO> queryIpoBond(String subscriptionDate) {
@@ -71,6 +73,7 @@ public class DataManagerImpl implements IDataManager {
     }
 
     @Override
+    @DataAuth("IPO_STOCK")
     @Cacheable(cacheNames = CacheNameConstant.DATA_IPO_STOCK_LIST, key = "#subscriptionDate",
             condition = "#subscriptionDate != null and !#subscriptionDate.isBlank()")
     public List<IpoStockVO> queryIpoStock(String subscriptionDate) {
@@ -87,6 +90,7 @@ public class DataManagerImpl implements IDataManager {
     }
 
     @Override
+    @DataAuth("DA_LE_TOU")
     @Cacheable(cacheNames = CacheNameConstant.DATA_DA_LE_TOU_LIST, key = "#drawDate",
             condition = "#drawDate != null and !#drawDate.isBlank()")
     public DaLeTouVO queryDaLeTou(String drawDate) {
@@ -101,6 +105,7 @@ public class DataManagerImpl implements IDataManager {
     }
 
     @Override
+    @DataAuth("SHUANG_SE_QIU")
     @Cacheable(cacheNames = CacheNameConstant.DATA_SHUANG_SE_QIU_LIST, key = "#drawDate",
             condition = "#drawDate != null and !#drawDate.isBlank()")
     public ShuangSeQiuVO queryShuangSeQiu(String drawDate) {
@@ -115,6 +120,7 @@ public class DataManagerImpl implements IDataManager {
     }
 
     @Override
+    @DataAuth("PRODUCT_HUNT_POST")
     @Cacheable(cacheNames = CacheNameConstant.DATA_PRODUCT_HUNT_POST_LIST, key = "#rankDate",
             condition = "#rankDate != null and !#rankDate.isBlank()")
     public List<ProductHuntPostVO> queryProductHuntPost(String rankDate) {

+ 102 - 4
data-easy/src/main/java/com/dataeasy/server/service/manager/impl/OrderManagerImpl.java

@@ -1,13 +1,25 @@
 package com.dataeasy.server.service.manager.impl;
 
 import java.math.BigDecimal;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import com.dataeasy.server.atomic.entity.SubscriptionUserConfig;
+import com.dataeasy.server.atomic.entity.SubscriptionUserLog;
+import com.dataeasy.server.atomic.service.ISubscriptionUserLogService;
+import com.dataeasy.server.common.utils.Assert;
+import com.dataeasy.server.constant.CacheNameConstant;
+import com.dataeasy.server.constant.PaidOptionEnum;
+import com.dataeasy.server.constant.PushOptionEnum;
+import com.dataeasy.server.pojo.subscription.SubscriptionUserConfigQuery;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.cache.CacheManager;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -36,6 +48,7 @@ import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
 
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.CollectionUtils;
 
 /**
  * @author tyuio
@@ -78,6 +91,12 @@ public class OrderManagerImpl implements IOrderManager {
     @Autowired
     private WxPayService wxPayService;
 
+    @Autowired
+    private ISubscriptionUserLogService subscriptionUserLogService;
+
+    @Autowired
+    private CacheManager cacheManager;
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public WxPayUnifiedOrderV3Result.JsapiResult createOrder(SubscriptionOrderRequest request) throws WxPayException {
@@ -104,6 +123,10 @@ public class OrderManagerImpl implements IOrderManager {
 
         User user = Optional.ofNullable(userService.getById(UserUtils.getCurrentUserId())).orElseThrow(() -> BusinessException.fail("找不到当前用户的信息"));
 
+        // 设置订单的过期时间
+        LocalDateTime expireDateTime = LocalDateTime.now().plusMinutes(bizProperties.getOrderExpire());
+        String timeExpire = expireDateTime.format(DateUtils.YYYYMMDDTHHMMSS_OFFSET_ZONE_FORMATTER);
+
         // 订单记录
         SubscriptionOrder subscriptionOrder = new SubscriptionOrder();
         subscriptionOrder.setUserId(UserUtils.getCurrentUserId());
@@ -113,6 +136,7 @@ public class OrderManagerImpl implements IOrderManager {
         subscriptionOrder.setSubscriptionDuration(subscriptionPlan.getSubscriptionDuration());
         subscriptionOrder.setPaymentStatus(PaymentStatusEnum.NOTPAY);
         subscriptionOrder.setOrderNo(generateOrderNo(OrderTypeEnum.SOO));
+        subscriptionOrder.setCloseTime(expireDateTime);
         subscriptionOrderService.insert(subscriptionOrder);
 
         // 设置金额,微信的单位为分,因此先转换成分
@@ -124,10 +148,6 @@ public class OrderManagerImpl implements IOrderManager {
         WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
         payer.setOpenid(user.getMaOpenId());
 
-        // 设置订单的过期时间
-        LocalDateTime expireDateTime = LocalDateTime.now().plusMinutes(bizProperties.getOrderExpire());
-        String timeExpire = expireDateTime.format(DateUtils.YYYYMMDDTHHMMSS_OFFSET_ZONE_FORMATTER);
-
         // 发送到微信的报文
         WxPayUnifiedOrderV3Request wxOrderV3 = new WxPayUnifiedOrderV3Request();
         wxOrderV3.setDescription(String.format("%s-%s天", subscriptionSource.getTitle(), subscriptionPlan.getSubscriptionDuration()));
@@ -155,4 +175,82 @@ public class OrderManagerImpl implements IOrderManager {
         }
         return String.format("%s%03d", orderPrefix, orderNoSequence.getAndIncrement());
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void successHandler(String orderNo, String transactionId) {
+        Assert.isNullInBusiness(orderNo, "请传入有效的订单号");
+        // 查找订单
+        SubscriptionOrder subscriptionOrder =
+                Optional.ofNullable(subscriptionOrderService.getByOrderNo(orderNo)).orElseThrow(
+                        () -> BusinessException.fail(String.format("根据订单号:{} 查找不到订单", orderNo)));
+
+        // 防止重复处理
+        if (!PaymentStatusEnum.NOTPAY.equals(subscriptionOrder.getPaymentStatus())) {
+            return;
+        }
+
+        // 查找订阅源
+        SubscriptionSource subscriptionSource = Optional.ofNullable(subscriptionSourceService.getById(subscriptionOrder.getSubscriptionSourceId())).orElseThrow(
+                () -> BusinessException.fail(String.format("根据订单号:{} 查找不到订阅源", orderNo)));
+
+        // 查询用户历史配置
+        SubscriptionUserConfigQuery subscriptionUserConfigQuery = new SubscriptionUserConfigQuery();
+        subscriptionUserConfigQuery.setUserId(subscriptionOrder.getUserId());
+        subscriptionUserConfigQuery.setSubscriptionSourceCodeList(Arrays.asList(subscriptionSource.getCode()));
+        subscriptionUserConfigQuery.setCurrentDate(LocalDate.now());
+        List<SubscriptionUserConfig> subscriptionUserConfigList = subscriptionUserConfigService.getByCondition(subscriptionUserConfigQuery);
+        if (!CollectionUtils.isEmpty(subscriptionUserConfigList) && subscriptionUserConfigList.size() > 1) {
+            BusinessException.throwFail(String.format("根据订单号:{} 用户对同一个订阅源存在多个配置,无法完成支付订单的配置", orderNo));
+        }
+
+        // 更新订单状态
+        SubscriptionOrder updateSubscriptionOrder = new SubscriptionOrder();
+        updateSubscriptionOrder.setId(subscriptionOrder.getId());
+        updateSubscriptionOrder.setTransactionId(transactionId);
+        updateSubscriptionOrder.setPaymentStatus(PaymentStatusEnum.SUCCESS);
+        subscriptionOrderService.updateById(updateSubscriptionOrder);
+
+        // 设置月日志
+        SubscriptionUserLog subscriptionUserLog = new SubscriptionUserLog();
+        subscriptionUserLog.setUserId(subscriptionOrder.getUserId());
+        subscriptionUserLog.setSubscriptionOrderId(subscriptionOrder.getId());
+        subscriptionUserLog.setPaidOption(PaidOptionEnum.PAID);
+
+        // 不存在历史配置,则新创建用户配置,否则在原有配置上更新数据
+        if (CollectionUtils.isEmpty(subscriptionUserConfigList)) {
+            LocalDate startDate = LocalDate.now();
+            LocalDate endDate = startDate.plusDays(subscriptionOrder.getSubscriptionDuration());
+            SubscriptionUserConfig addSubscriptionUserConfig = new SubscriptionUserConfig();
+            addSubscriptionUserConfig.setPushOption(PushOptionEnum.ENABLED);
+            addSubscriptionUserConfig.setUserId(subscriptionOrder.getUserId());
+            addSubscriptionUserConfig.setSubscriptionSourceCode(subscriptionSource.getCode());
+            addSubscriptionUserConfig.setStartDate(LocalDate.now());
+            addSubscriptionUserConfig.setEndDate(endDate);
+            subscriptionUserConfigService.insert(addSubscriptionUserConfig);
+
+            subscriptionUserLog.setStartDate(addSubscriptionUserConfig.getStartDate());
+            subscriptionUserLog.setAfterEndDate(addSubscriptionUserConfig.getEndDate());
+        }  else {
+            // 历史配置
+            SubscriptionUserConfig subscriptionUserConfig = subscriptionUserConfigList.get(0);
+            // 结束时间延期
+            LocalDate endDate = subscriptionUserConfig.getEndDate().plusDays(subscriptionOrder.getSubscriptionDuration());
+
+            SubscriptionUserConfig updateSubscriptionUserConfig = new SubscriptionUserConfig();
+            updateSubscriptionUserConfig.setId(subscriptionUserConfig.getId());
+            updateSubscriptionUserConfig.setEndDate(endDate);
+            subscriptionUserConfigService.updateById(updateSubscriptionUserConfig);
+
+            subscriptionUserLog.setStartDate(subscriptionUserConfig.getStartDate());
+            subscriptionUserLog.setBeforeEndDate(subscriptionUserConfig.getEndDate());
+            subscriptionUserLog.setAfterEndDate(updateSubscriptionUserConfig.getEndDate());
+        }
+
+        subscriptionUserLogService.insert(subscriptionUserLog);
+
+        // 清除缓存
+        cacheManager.getCache(CacheNameConstant.SUBSCRIPTION_USER_CONFIG_LIST).evict(subscriptionOrder.getUserId());
+
+    }
 }

+ 6 - 7
data-easy/src/main/java/com/dataeasy/server/service/manager/impl/SubscriptionManagerImpl.java

@@ -125,27 +125,26 @@ public class SubscriptionManagerImpl implements ISubscriptionManager {
         }
 
         //查询订阅源信息
-        Set<Long> subscriptionSourceIds = userConfigList.stream().map(SubscriptionUserConfig::getSubscriptionSourceId).collect(Collectors.toSet());
+        Set<String> subscriptionSourceCodeList = userConfigList.stream().map(SubscriptionUserConfig::getSubscriptionSourceCode).collect(Collectors.toSet());
         SubscriptionSourceQuery subscriptionSourceQuery = new SubscriptionSourceQuery();
-        subscriptionSourceQuery.setIds(subscriptionSourceIds);
+        subscriptionSourceQuery.setSubscriptionSourceCodeList(subscriptionSourceCodeList);
         List<SubscriptionSource> subscriptionSourceList = subscriptionSourceService.getByCondition(subscriptionSourceQuery);
         if (CollectionUtils.isEmpty(subscriptionSourceList)) {
             throw BusinessException.fail("根据配置找不到对应的订阅源信息");
         }
 
-        Map<Long, SubscriptionSource> subscriptionSourceMap = subscriptionSourceList.stream().collect(Collectors.toMap(SubscriptionSource::getId, Function.identity()));
+        Map<String, SubscriptionSource> subscriptionSourceMap = subscriptionSourceList.stream().collect(Collectors.toMap(SubscriptionSource::getCode, Function.identity()));
         return userConfigList.stream().map(userConfig -> {
             SubscriptionUserConfigVO subscriptionUserConfigVO = new SubscriptionUserConfigVO();
             BeanUtils.copyProperties(userConfig, subscriptionUserConfigVO);
-            SubscriptionSource subscriptionSource = subscriptionSourceMap.get(userConfig.getSubscriptionSourceId());
+            SubscriptionSource subscriptionSource = subscriptionSourceMap.get(userConfig.getSubscriptionSourceCode());
             if (Objects.nonNull(subscriptionSource)) {
                 subscriptionUserConfigVO.setTitle(subscriptionSource.getTitle());
                 subscriptionUserConfigVO.setSubTitle(subscriptionSource.getSubTitle());
+                subscriptionUserConfigVO.setSubscriptionSourceId(subscriptionSource.getId());
             }
 
-            LocalDateTime startTime = userConfig.getStartTime().toLocalDateTime();
-            LocalDateTime endTime = userConfig.getEndTime().toLocalDateTime();
-            long remainingDays = ChronoUnit.DAYS.between(startTime, endTime);
+            long remainingDays = ChronoUnit.DAYS.between(userConfig.getStartDate(), userConfig.getEndDate());
             subscriptionUserConfigVO.setRemainingDays(remainingDays);
 
             return subscriptionUserConfigVO;

+ 2 - 1
data-easy/src/main/java/com/dataeasy/server/service/manager/impl/UserManagerImpl.java

@@ -53,7 +53,7 @@ public class UserManagerImpl implements IUserManager {
         WxMaJscode2SessionResult wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(request.getCode());
 
         // 获取用户记录
-        User user = userService.getByMaOpenId(wxMaJscode2SessionResult.getOpenid());
+        User user = userService.getByUnionId(wxMaJscode2SessionResult.getUnionid());
 
         // 存在责更新用户信息,没有则创建新用户
         if (Objects.isNull(user)) {
@@ -68,6 +68,7 @@ public class UserManagerImpl implements IUserManager {
         } else {
             User updateUser = new User();
             updateUser.setId(user.getId());
+            updateUser.setMaOpenId(wxMaJscode2SessionResult.getOpenid());
             updateUser.setNickname(request.getNickname());
             userService.updateById(updateUser);
 

+ 13 - 48
data-easy/src/main/java/com/dataeasy/server/service/manager/impl/WxManagerImpl.java

@@ -1,27 +1,19 @@
 package com.dataeasy.server.service.manager.impl;
 
-import com.dataeasy.server.atomic.entity.SubscriptionOrder;
-import com.dataeasy.server.atomic.entity.SubscriptionUserConfig;
-import com.dataeasy.server.atomic.service.ISubscriptionOrderService;
-import com.dataeasy.server.atomic.service.ISubscriptionUserConfigService;
-import com.dataeasy.server.common.exception.BusinessException;
-import com.dataeasy.server.constant.CacheNameConstant;
-import com.dataeasy.server.constant.PaymentStatusEnum;
-import com.dataeasy.server.constant.PushOptionEnum;
-import com.dataeasy.server.utiis.DateUtils;
-import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
-import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Response;
-import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result;
-import com.github.binarywang.wxpay.service.WxPayService;
-import jakarta.servlet.http.HttpServletRequest;
+import com.dataeasy.server.service.manager.IOrderManager;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.cache.CacheManager;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import com.dataeasy.server.service.manager.IWxManager;
+import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
+import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Response;
+import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result;
+import com.github.binarywang.wxpay.service.WxPayService;
 
+import jakarta.servlet.http.HttpServletRequest;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.mp.api.WxMpMessageRouter;
@@ -29,9 +21,6 @@ import me.chanjar.weixin.mp.api.WxMpService;
 import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
 import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.Optional;
 
 /**
  * @author tyuio
@@ -53,13 +42,7 @@ public class WxManagerImpl implements IWxManager {
     private WxPayService wxPayService;
 
     @Autowired
-    private ISubscriptionOrderService subscriptionOrderService;
-
-    @Autowired
-    private ISubscriptionUserConfigService subscriptionUserConfigService;
-
-    @Autowired
-    private CacheManager cacheManager;
+    private IOrderManager orderManager;
 
     @Override
     public String mpEntry(String signature, String timestamp, String nonce, String echoStr) {
@@ -125,34 +108,16 @@ public class WxManagerImpl implements IWxManager {
             signatureHeader.setSignature(request.getHeader("Wechatpay-Signature"));
             signatureHeader.setSerial(request.getHeader("Wechatpay-Serial"));
             signatureHeader.setTimeStamp(request.getHeader("Wechatpay-Timestamp"));
-            log.info("signatureHeader: {}", signatureHeader);
+            log.debug("signatureHeader: {}", signatureHeader);
             // 获取回调结果
             WxPayNotifyV3Result payResult1 = wxPayService.parseOrderNotifyV3Result(xmlResult, signatureHeader);
             log.info("回调结果:{}", payResult1);
 
             WxPayNotifyV3Result.DecryptNotifyResult payResult = payResult1.getResult();
-
-            // 查找订单
-            SubscriptionOrder subscriptionOrder = Optional.ofNullable(subscriptionOrderService.getByOrderNo(payResult.getOutTradeNo())).orElseThrow(() -> BusinessException.fail(String.format("根据订单号:{} 查找不到订单", payResult.getOutTradeNo())));
-            // 更新订单状态
-            SubscriptionOrder updateSubscriptionOrder = new SubscriptionOrder();
-            updateSubscriptionOrder.setId(subscriptionOrder.getId());
-            updateSubscriptionOrder.setPaymentStatus(PaymentStatusEnum.SUCCESS);
-            subscriptionOrderService.updateById(updateSubscriptionOrder);
-
-            // 支付成功创建用户配置
-            SubscriptionUserConfig addSubscriptionUserConfig = new SubscriptionUserConfig();
-            addSubscriptionUserConfig.setPushOption(PushOptionEnum.ENABLED);
-            addSubscriptionUserConfig.setUserId(subscriptionOrder.getUserId());
-            addSubscriptionUserConfig.setSubscriptionSourceId(subscriptionOrder.getSubscriptionSourceId());
-            addSubscriptionUserConfig.setStartTime(DateUtils.getCurrentTimestamp());
-            addSubscriptionUserConfig.setEndTime(DateUtils.getTimestampSpecial(subscriptionOrder.getSubscriptionDuration()));
-            subscriptionUserConfigService.insert(addSubscriptionUserConfig);
-
-            // 清除缓存
-            cacheManager.getCache(CacheNameConstant.SUBSCRIPTION_USER_CONFIG_LIST).evict(subscriptionOrder.getUserId());
-
-            // TODO 这里要回写订单信息
+            if ("SUCCESS".equals(payResult.getTradeState())) {
+                orderManager.successHandler(payResult.getOutTradeNo(), payResult.getTransactionId());
+            }
+            log.info("微信支付回调通知,订单:{},交易状态:{}", payResult.getOutTradeNo(), payResult.getTradeState());
             return WxPayNotifyV3Response.success("处理成功!");
         } catch (Exception e) {
             log.error("微信支付回调处理失败", e);

+ 5 - 5
data-easy/src/main/java/com/dataeasy/server/task/AbstractDataTask.java

@@ -1,19 +1,18 @@
 package com.dataeasy.server.task;
 
-import java.sql.Timestamp;
+import java.time.LocalDate;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
 
-import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties;
-import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cache.CacheManager;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
+import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties;
 import com.dataeasy.server.atomic.entity.SubscriptionTaskConfig;
 import com.dataeasy.server.atomic.entity.SubscriptionUserConfig;
 import com.dataeasy.server.atomic.entity.User;
@@ -30,6 +29,7 @@ import com.dataeasy.server.service.manager.IWxManager;
 
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
+import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
 
 /**
  * @author tyuio
@@ -79,9 +79,9 @@ public abstract class AbstractDataTask {
 
         // 寻找要推送数据的用户
         SubscriptionUserConfigQuery userConfigQuery = new SubscriptionUserConfigQuery();
-        userConfigQuery.setSubscriptionSourceIds(Arrays.asList(subscriptionTaskConfig.getId()));
+        userConfigQuery.setSubscriptionSourceCodeList(Arrays.asList(subscriptionTaskConfig.getTaskCode()));
         userConfigQuery.setPushOption(PushOptionEnum.ENABLED);
-        userConfigQuery.setCurrentTime(new Timestamp(System.currentTimeMillis()));
+        userConfigQuery.setCurrentDate(LocalDate.now());
         List<SubscriptionUserConfig> userConfigList = userConfigService.getByCondition(userConfigQuery);
         if (CollectionUtils.isEmpty(userConfigList)) {
             log.warn("任务:{},任务编码:{},没有找到推送状态为启用的用户配置,结束执行", task.getName(), task);

+ 31 - 0
data-easy/src/main/java/com/dataeasy/server/task/AutoDeleteSubscriptionUserConfigTask.java

@@ -0,0 +1,31 @@
+package com.dataeasy.server.task;
+
+import com.dataeasy.server.atomic.service.ISubscriptionUserConfigService;
+import com.dataeasy.server.common.annotation.ScheduleTask;
+import com.dataeasy.server.constant.ScheduleTaskEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDate;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/3/18 19:08
+ * @description 用户订阅源配置过期自动删除 定时任务
+ */
+@Slf4j
+@Component
+@ScheduleTask(ScheduleTaskEnum.AUTO_DELETE_SUBSCRIPTION_USER_CONFIG)
+public class AutoDeleteSubscriptionUserConfigTask {
+
+    @Autowired
+    private ISubscriptionUserConfigService subscriptionUserConfigService;
+
+    @Scheduled(cron = "0 5 0 * * *")
+    public void execute() {
+        subscriptionUserConfigService.deleteExpireConfig(LocalDate.now());
+    }
+}

+ 0 - 24
data-easy/src/main/java/com/dataeasy/server/utiis/DateUtils.java

@@ -37,28 +37,4 @@ public class DateUtils {
      */
     public static final DateTimeFormatter YYYYMMDDTHHMMSS_OFFSET_ZONE_FORMATTER =
         DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss+08:00");
-
-    /**
-     * 获取当前时间
-     * 
-     * @return
-     */
-    public static Timestamp getCurrentTimestamp() {
-        return new Timestamp(System.currentTimeMillis());
-    }
-
-    /**
-     * 获取在当前时间时间的基础上加上指定天数的时间,并且时分秒为23:59:59
-     * @param plusDays 加的天数
-     * @return
-     */
-    public static Timestamp getTimestampSpecial(Integer plusDays) {
-        LocalDateTime adjustedDateTime = LocalDateTime.now()
-                .plusDays(plusDays)
-                .withHour(23)
-                .withMinute(59)
-                .withSecond(59)
-                .withNano(999999999);
-        return Timestamp.valueOf(adjustedDateTime);
-    }
 }

File diff suppressed because it is too large
+ 3 - 3
doc/sql/data.sql


+ 25 - 0
doc/sql/schema.sql

@@ -430,3 +430,28 @@ ALTER TABLE data_easy.data_ipo_bond MODIFY COLUMN issue_par_value decimal(20,2)
 ALTER TABLE data_easy.data_ipo_bond MODIFY COLUMN actual_issue_amount decimal(22,4) NULL COMMENT '实际发行总量';
 ALTER TABLE data_easy.data_ipo_bond MODIFY COLUMN planned_issue_amount decimal(22,4) NULL COMMENT '计划发行总量';
 ALTER TABLE data_easy.data_ipo_stock CHANGE profit_rer_winning_lot profit_per_winning_lot decimal(20,2) NULL COMMENT '每中一签获利';
+ALTER TABLE data_easy.subscription_user_config CHANGE subscription_source_id subscription_source_code varchar(30) NOT NULL COMMENT '订阅源编码';
+ALTER TABLE data_easy.subscription_user_config MODIFY COLUMN subscription_source_code varchar(30) NOT NULL COMMENT '订阅源编码';
+ALTER TABLE data_easy.subscription_user_config CHANGE start_time start_date DATE NOT NULL COMMENT '订阅开始时间';
+ALTER TABLE data_easy.subscription_user_config MODIFY COLUMN start_date DATE NOT NULL COMMENT '订阅开始时间';
+ALTER TABLE data_easy.subscription_user_config CHANGE end_time end_date DATE NOT NULL COMMENT '订阅结束时间';
+ALTER TABLE data_easy.subscription_user_config MODIFY COLUMN end_date DATE NOT NULL COMMENT '订阅结束时间';
+ALTER TABLE data_easy.subscription_source ADD code varchar(30) NOT NULL COMMENT '唯一编码';
+ALTER TABLE data_easy.subscription_source CHANGE code code varchar(30) NOT NULL COMMENT '唯一编码' AFTER id;
+ALTER TABLE data_easy.subscription_user_log DROP COLUMN subscription_source_id;
+ALTER TABLE data_easy.subscription_user_log DROP COLUMN subscription_plan_id;
+ALTER TABLE data_easy.subscription_user_log DROP COLUMN subscription_price;
+ALTER TABLE data_easy.subscription_user_log DROP COLUMN subscription_duration;
+ALTER TABLE data_easy.subscription_user_log CHANGE start_time start_date DATE NOT NULL COMMENT '订阅前开始时间';
+ALTER TABLE data_easy.subscription_user_log MODIFY COLUMN start_date DATE NOT NULL COMMENT '订阅前开始时间';
+ALTER TABLE data_easy.subscription_user_log CHANGE before_end_time before_end_date DATE NULL COMMENT '订阅前结束时间';
+ALTER TABLE data_easy.subscription_user_log MODIFY COLUMN before_end_date DATE NULL COMMENT '订阅前结束时间';
+ALTER TABLE data_easy.subscription_user_log CHANGE after_end_time after_end_date DATE NOT NULL COMMENT '订阅后结束时间';
+ALTER TABLE data_easy.subscription_user_log MODIFY COLUMN after_end_date DATE NOT NULL COMMENT '订阅后结束时间';
+ALTER TABLE data_easy.subscription_order ADD transaction_id varchar(40) NULL COMMENT '微信支付订单号';
+ALTER TABLE data_easy.subscription_order CHANGE transaction_id transaction_id varchar(40) NULL COMMENT '微信支付订单号' AFTER order_no;
+ALTER TABLE data_easy.subscription_task_config MODIFY COLUMN subscription_source_id bigint NULL COMMENT '订阅源ID';
+ALTER TABLE data_easy.subscription_task_config MODIFY COLUMN task_code varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '定时任务编码';
+ALTER TABLE data_easy.subscription_order MODIFY COLUMN close_time DATETIME NOT NULL COMMENT '订单关闭时间';
+
+

+ 42 - 43
doc/技术文档.md

@@ -41,14 +41,15 @@
 
 ## 定时任务
 
-| 定时任务名称             | 执行时间                     | cron表达式           | 实现类             |
-| ------------------------ | ---------------------------- | -------------------- | ------------------ |
-| 大乐透定时任务           | 每周一、三、六,晚上21:25    | 0 25 21 * * 1,3,6    | DaLeTouTask        |
-| 双色球定时任务           | 每周二、周四、周日 晚上21:35 | 0 35 21 * * 2,4,7    | ShuangSeQiuTask    |
-| 新债定时任务             | 每天早上8:35执行一次         | 0 35 8 * * *         | IpoBondTask        |
-| 新股定时任务             | 每天早上8:40执行一次         | 0 40 8 * * *         | IpoStockTask       |
-| ProductHunt热榜定时任务  | 每天下午16:05执行一次        | 0 5 16 * * *         | ProductHuntTask    |
-| 支付订单自动关闭定时任务 | 每15分钟执行一次             | 0 0,15,30,45 * * * * | AutoCloseOrderTask |
+| 定时任务名称               | 执行时间                     | cron表达式           | 实现类                              |
+| -------------------------- | ---------------------------- | -------------------- | ----------------------------------- |
+| 大乐透定时任务             | 每周一、三、六,晚上21:25    | 0 25 21 * * 1,3,6    | DaLeTouTask                         |
+| 双色球定时任务             | 每周二、周四、周日 晚上21:35 | 0 35 21 * * 2,4,7    | ShuangSeQiuTask                     |
+| 新债定时任务               | 每天早上8:35执行一次         | 0 35 8 * * *         | IpoBondTask                         |
+| 新股定时任务               | 每天早上8:40执行一次         | 0 40 8 * * *         | IpoStockTask                        |
+| ProductHunt热榜定时任务    | 每天下午16:05执行一次        | 0 5 16 * * *         | ProductHuntTask                     |
+| 支付订单自动关闭定时任务   | 每15分钟执行一次             | 0 0,15,30,45 * * * * | AutoCloseOrderTask                  |
+| 用户订阅源配置过期自动删除 | 每天凌晨00:05分执行一次      | 0 5 0 * * *          | AutoCloseSubscriptionUserConfigTask |
 
 
 
@@ -322,6 +323,7 @@
 | 字段             | 类型          | 描述                               |
 | ---------------- | ------------- | ---------------------------------- |
 | id               | bigint        | 主键                               |
+| code             | varchar(30)   | 唯一编码                           |
 | title            | varchar(100)  | 主标题                             |
 | sub_title        | varchar(300)  | 副标题                             |
 | push_channel     | varchar(10)   | 推送渠道(WXMP-微信服务号)        |
@@ -361,20 +363,20 @@
 
 表名:subscription_user_config
 
-| 字段                   | 类型        | 描述                                    |
-| ---------------------- | ----------- | --------------------------------------- |
-| id                     | bigint      | 主键                                    |
-| user_id                | bigint      | 用户ID                                  |
-| subscription_source_id | bigint      | 订阅源ID                                |
-| start_time             | timestamp   | 订阅开始时间                            |
-| end_time               | timestamp   | 订阅结束时间                            |
-| push_option            | varchar(10) | 消息推送选项(ENABLE-开启、DISABLE-关闭) |
-| created_by             | bigint      | 创建人                                  |
-| creation_time          | timestamp   | 创建时间                                |
-| last_updated_by        | bigint      | 最后更新人                              |
-| last_update_time       | timestamp   | 最后更新时间                            |
-| version                | bigint      | 版本号                                  |
-| delete_flag            | tinyint     | 逻辑删除标志(0-未删除,1-已删除)      |
+| 字段                     | 类型        | 描述                                    |
+| ------------------------ | ----------- | --------------------------------------- |
+| id                       | bigint      | 主键                                    |
+| user_id                  | bigint      | 用户ID                                  |
+| subscription_source_code | varchar(30) | 订阅源编码                              |
+| start_date               | date        | 订阅开始时间(包含当天)                  |
+| end_date                 | date        | 订阅结束时间(包含当天)                  |
+| push_option              | varchar(10) | 消息推送选项(ENABLE-开启、DISABLE-关闭) |
+| created_by               | bigint      | 创建人                                  |
+| creation_time            | timestamp   | 创建时间                                |
+| last_updated_by          | bigint      | 最后更新人                              |
+| last_update_time         | timestamp   | 最后更新时间                            |
+| version                  | bigint      | 版本号                                  |
+| delete_flag              | tinyint     | 逻辑删除标志(0-未删除,1-已删除)      |
 
 
 
@@ -385,7 +387,7 @@
 | 字段                   | 类型         | 描述                                  |
 | ---------------------- | ------------ | ------------------------------------- |
 | id                     | bigint       | 主键                                  |
-| task_code              | varchar(30)  | 定时任务编码                          |
+| task_code              | varchar(100) | 定时任务编码                          |
 | task_name              | varchar(100) | 定时任务名称                          |
 | subscription_source_id | bigint       | 订阅源ID                              |
 | execute_option         | varchar(10)  | 执行选项(ENABLED-开启、DISABLED-关闭) |
@@ -427,25 +429,21 @@
 
 表名:subscription_user_log
 
-| 字段                   | 类型          | 描述                               |
-| ---------------------- | ------------- | ---------------------------------- |
-| id                     | bigint        | 主键                               |
-| user_id                | bigint        | 用户ID                             |
-| subscription_source_id | bigint        | 订阅源ID                           |
-| subscription_plan_id   | bigint        | 订阅价格计划ID                     |
-| subscription_order_id  | bigint        | 订单ID                             |
-| paid_option            | varchar(10)   | 付费选项(FREE-免费、PAID-付费)   |
-| subscription_price     | decimal(12,2) | 订阅价格(单位:元)               |
-| subscription_duration  | int           | 本次订阅时长(单位:天)           |
-| start_time             | timestamp     | 订阅前开始时间                     |
-| before_end_time        | timestamp     | 订阅前结束时间                     |
-| after_end_time         | timestamp     | 订阅后结束时间                     |
-| created_by             | bigint        | 创建人                             |
-| creation_time          | timestamp     | 创建时间                           |
-| last_updated_by        | bigint        | 最后更新人                         |
-| last_update_time       | timestamp     | 最后更新时间                       |
-| version                | bigint        | 版本号                             |
-| delete_flag            | tinyint       | 逻辑删除标志(0-未删除,1-已删除) |
+| 字段                  | 类型        | 描述                               |
+| --------------------- | ----------- | ---------------------------------- |
+| id                    | bigint      | 主键                               |
+| user_id               | bigint      | 用户ID                             |
+| subscription_order_id | bigint      | 订单ID(付费才有)                 |
+| paid_option           | varchar(10) | 付费选项(FREE-免费、PAID-付费)   |
+| start_date            | date        | 订阅前开始时间                     |
+| before_end_date       | date        | 订阅前结束时间                     |
+| after_end_date        | date        | 订阅后结束时间                     |
+| created_by            | bigint      | 创建人                             |
+| creation_time         | timestamp   | 创建时间                           |
+| last_updated_by       | bigint      | 最后更新人                         |
+| last_update_time      | timestamp   | 最后更新时间                       |
+| version               | bigint      | 版本号                             |
+| delete_flag           | tinyint     | 逻辑删除标志(0-未删除,1-已删除) |
 
 
 
@@ -460,9 +458,10 @@
 | subscription_source_id | bigint        | 订阅源ID                                                     |
 | subscription_plan_id   | bigint        | 订阅价格计划ID                                               |
 | order_no               | varchar(30)   | 订单号(格式:3位业务编码 + yyMMddHHmmss + 3位序列号)       |
+| transaction_id         | varchar(32)   | 微信支付订单号                                               |
 | subscription_price     | decimal(12,2) | 订阅价格(单位:元)                                         |
 | subscription_duration  | int           | 订阅时长(单位:天)                                         |
-| close_time             | timestamp     | 订单关闭时间                                                 |
+| close_time             | datetime      | 订单关闭时间                                                 |
 | payment_status         | varchar(10)   | 支付状态(NOTPAY-未支付,SUCCESS-支付成功、REFUND-转入退款、CLOSED-已关闭、REVOKED-已撤销) |
 | created_by             | bigint        | 创建人                                                       |
 | creation_time          | timestamp     | 创建时间                                                     |

Some files were not shown because too many files changed in this diff