diff --git a/src/main/java/com/ai/da/common/task/AccountTask.java b/src/main/java/com/ai/da/common/task/AccountTask.java index 542837ce..ed60feb4 100644 --- a/src/main/java/com/ai/da/common/task/AccountTask.java +++ b/src/main/java/com/ai/da/common/task/AccountTask.java @@ -3,6 +3,7 @@ package com.ai.da.common.task; import com.ai.da.common.utils.RedisUtil; import com.ai.da.mapper.primary.entity.Account; import com.ai.da.service.AccountService; +import com.ai.da.service.SubscriptionPlanService; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -18,6 +19,8 @@ public class AccountTask { private AccountService accountService; @Resource private RedisUtil redisUtil; + @Resource + private SubscriptionPlanService subscriptionPlanService; /** * 每周日晚上刷新 年付用户、月付用户的积分 @@ -86,4 +89,14 @@ public class AccountTask { public void checkEduAdminExpireStatus() { accountService.checkEduAdminExpireStatus(); } + + @Scheduled(cron = "0 5 0 * * ?") + public void activeSubscriptionPlan() { + subscriptionPlanService.activeSubscriptionPlan(); + } + + @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes + public void expireSubscription() { + subscriptionPlanService.expireSubscription(); + } } diff --git a/src/main/java/com/ai/da/controller/SubscriptionPlanController.java b/src/main/java/com/ai/da/controller/SubscriptionPlanController.java index e071b830..a5fab146 100644 --- a/src/main/java/com/ai/da/controller/SubscriptionPlanController.java +++ b/src/main/java/com/ai/da/controller/SubscriptionPlanController.java @@ -1,6 +1,7 @@ package com.ai.da.controller; import com.ai.da.common.response.Response; +import com.ai.da.common.task.SubscriptionReminderTask; import com.ai.da.mapper.primary.entity.SubscriptionPlan; import com.ai.da.model.dto.SubscriptionPlanDTO; import com.ai.da.model.dto.SubscriptionPlanPageQuery; @@ -8,6 +9,7 @@ import com.ai.da.model.dto.UpdateSubscriptionPlanDTO; import com.ai.da.model.vo.SubscriptionPlanVO; import com.ai.da.service.SubscriptionPlanService; import com.baomidou.mybatisplus.core.metadata.IPage; +import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -26,6 +28,8 @@ public class SubscriptionPlanController { private final SubscriptionPlanService subscriptionPlanService; + private final SubscriptionReminderTask subscriptionReminderTask; + @Operation(summary = "创建订阅计划") @PostMapping("/createPlan") public Response createPlan(@Valid @RequestBody SubscriptionPlanDTO subscriptionPlanDTO) { @@ -74,6 +78,7 @@ public class SubscriptionPlanController { return Response.success(); } +// @Hidden @Operation(summary = "activeSubscriptionPlan") @GetMapping("/activeSubscriptionPlan") public Response activeSubscriptionPlan() { @@ -81,6 +86,7 @@ public class SubscriptionPlanController { return Response.success(); } +// @Hidden @Operation(summary = "expireSubscription") @GetMapping("/expireSubscription") public Response expireSubscription() { @@ -88,5 +94,19 @@ public class SubscriptionPlanController { return Response.success(); } + @Operation(summary = "subscriptionReminder") + @GetMapping("/subscriptionReminder") + public Response subscriptionReminder() { + subscriptionReminderTask.subscriptionReminder(); + return Response.success(); + } + + @Operation(summary = "trialReminder") + @GetMapping("/trialReminder") + public Response trialReminder() { + subscriptionReminderTask.trialReminder(); + return Response.success(); + } + } diff --git a/src/main/java/com/ai/da/mapper/primary/SubscriptionPlanMapper.java b/src/main/java/com/ai/da/mapper/primary/SubscriptionPlanMapper.java index 2e9df012..cfb0727c 100644 --- a/src/main/java/com/ai/da/mapper/primary/SubscriptionPlanMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/SubscriptionPlanMapper.java @@ -14,11 +14,14 @@ public interface SubscriptionPlanMapper extends BaseMapper { /** * 关联查询订阅计划信息(包含管理员邮箱)- 分页 */ - @Select("SELECT sp.*, a.user_email as adminAccEmail, a.user_name as adminAccName " + - "FROM t_subscription_plan sp " + - "LEFT JOIN t_account a ON sp.admin_acc_id = a.id " + - "WHERE sp.is_deleted = 0 " + - "${ew.customSqlSegment}") + @Select(""" + SELECT sp.*, + a.user_email AS adminAccEmail, + a.user_name AS adminAccName + FROM t_subscription_plan sp + LEFT JOIN t_account a ON sp.admin_acc_id = a.id + ${ew.customSqlSegment} + """) Page selectWithEmailPage(Page page, @Param(Constants.WRAPPER) Wrapper wrapper); } diff --git a/src/main/java/com/ai/da/model/vo/AccountLoginVO.java b/src/main/java/com/ai/da/model/vo/AccountLoginVO.java index d643f2cd..6c48b525 100644 --- a/src/main/java/com/ai/da/model/vo/AccountLoginVO.java +++ b/src/main/java/com/ai/da/model/vo/AccountLoginVO.java @@ -83,4 +83,6 @@ public class AccountLoginVO { private String organizationName; + private Long subscriptionPlanId; + } diff --git a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java index 4d8556f6..4becada3 100644 --- a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java @@ -2421,6 +2421,9 @@ public class AccountServiceImpl extends ServiceImpl impl AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder(); Account adminAcc = accountMapper.selectById(authPrincipalVo.getId()); int subUserRole = getSubUserRole(adminAcc.getSystemUser()); + if (Objects.isNull(adminAcc.getSubscriptionPlanId())) { + throw new BusinessException("relate.to.any.subscription"); + } if (addSubAccountDTO.getId() == null) { return createSubAccount(addSubAccountDTO, adminAcc, subUserRole); @@ -3177,6 +3180,7 @@ public class AccountServiceImpl extends ServiceImpl impl response.setUsernameModify(getNicknameModifyTimes()); response.setOrganizationId(account.getOrganizationId()); response.setOrganizationName(account.getOrganizationName()); + response.setSubscriptionPlanId(account.getSubscriptionPlanId()); return response; } diff --git a/src/main/java/com/ai/da/service/impl/StripeServiceImpl.java b/src/main/java/com/ai/da/service/impl/StripeServiceImpl.java index 17c4596b..ea3c758c 100644 --- a/src/main/java/com/ai/da/service/impl/StripeServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/StripeServiceImpl.java @@ -1029,14 +1029,16 @@ public class StripeServiceImpl implements StripeService { }else { List activeSubscriptions = subscriptionInfoList.stream() .filter(subscription -> "active".equals(subscription.getStatus())) - .collect(Collectors.toList()); + .toList(); if (!StringUtil.isNullOrEmpty(type) && type.equals("cancel")){ - subscriptionInfo = subscriptionInfoList.get(0); - }else if (activeSubscriptions.isEmpty()){ + subscriptionInfo = subscriptionInfoList.getFirst(); + } else if (!StringUtil.isNullOrEmpty(type) && type.equals("reminder_expire")) { + subscriptionInfo = subscriptionInfoList.getFirst(); + } else if (activeSubscriptions.isEmpty() && type.equals("cancel")){ log.info("不发送邮件,原因:【当前邮件类型:{}, 但是状态为active的subscriptionInfo为空】", type); return false; - }else { - subscriptionInfo = activeSubscriptions.get(0); + } else { + subscriptionInfo = activeSubscriptions.getFirst(); } } }else if (!StringUtil.isNullOrEmpty(orderNo)) { diff --git a/src/main/java/com/ai/da/service/impl/SubscriptionPlanServiceImpl.java b/src/main/java/com/ai/da/service/impl/SubscriptionPlanServiceImpl.java index 87d5f012..5713d585 100644 --- a/src/main/java/com/ai/da/service/impl/SubscriptionPlanServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/SubscriptionPlanServiceImpl.java @@ -143,6 +143,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl searchByOrganizationIdAndStatus(SubscriptionPlanPageQuery subscriptionPlanPageQuery) { QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.lambda().eq(SubscriptionPlan::getAdminAccId, UserContext.getUserHolder().getId()); if (Objects.nonNull(subscriptionPlanPageQuery.getOrganizationId())){ queryWrapper.lambda().eq(SubscriptionPlan::getOrganizationId, subscriptionPlanPageQuery.getOrganizationId()); } else { @@ -163,7 +164,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl queryWrapper = buildQueryWrapperWithoutDeleted(subscriptionPlanPageQuery); + QueryWrapper queryWrapper = buildQueryWrapperWithoutDeleted(subscriptionPlanPageQuery); // 3. 执行自定义的分页查询 Page page = new Page<>( @@ -178,37 +179,38 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl buildQueryWrapperWithoutDeleted(SubscriptionPlanPageQuery query) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + private QueryWrapper buildQueryWrapperWithoutDeleted(SubscriptionPlanPageQuery query) { + QueryWrapper wrapper = new QueryWrapper<>(); - // 精确匹配条件 + // 精确匹配条件 - 需要指定表别名 if (query.getId() != null) { - wrapper.eq(SubscriptionPlan::getId, query.getId()); + wrapper.eq("sp.id", query.getId()); } if (query.getOrganizationId() != null) { - wrapper.eq(SubscriptionPlan::getOrganizationId, query.getOrganizationId()); + wrapper.eq("sp.organization_id", query.getOrganizationId()); } if (query.getAdminAccId() != null) { - wrapper.eq(SubscriptionPlan::getAdminAccId, query.getAdminAccId()); + wrapper.eq("sp.admin_acc_id", query.getAdminAccId()); } // 时间范围查询 if (StringUtils.isNotBlank(query.getStartTime())) { LocalDateTime startTime = parseDateTime(query.getStartTime()); - wrapper.ge(SubscriptionPlan::getCreateTime, startTime); + wrapper.ge("sp.create_time", startTime); } if (StringUtils.isNotBlank(query.getEndTime())) { LocalDateTime endTime = parseDateTime(query.getEndTime()); - wrapper.le(SubscriptionPlan::getCreateTime, endTime); + wrapper.le("sp.create_time", endTime); } // 状态匹配 if (!CollectionUtils.isEmpty(query.getStatus())) { - wrapper.in(SubscriptionPlan::getStatus, query.getStatus()); + wrapper.in("sp.status", query.getStatus()); } // 按创建时间倒序排序 - wrapper.orderByDesc(SubscriptionPlan::getCreateTime); + wrapper.ne("sp.is_deleted", 1) + .orderByDesc("sp.create_time"); return wrapper; } @@ -752,6 +754,8 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl