Merge branch 'dev/dev_xp' into dev/3.1_release_merge
This commit is contained in:
@@ -3,6 +3,7 @@ package com.ai.da.common.task;
|
|||||||
import com.ai.da.common.utils.RedisUtil;
|
import com.ai.da.common.utils.RedisUtil;
|
||||||
import com.ai.da.mapper.primary.entity.Account;
|
import com.ai.da.mapper.primary.entity.Account;
|
||||||
import com.ai.da.service.AccountService;
|
import com.ai.da.service.AccountService;
|
||||||
|
import com.ai.da.service.SubscriptionPlanService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -18,6 +19,8 @@ public class AccountTask {
|
|||||||
private AccountService accountService;
|
private AccountService accountService;
|
||||||
@Resource
|
@Resource
|
||||||
private RedisUtil redisUtil;
|
private RedisUtil redisUtil;
|
||||||
|
@Resource
|
||||||
|
private SubscriptionPlanService subscriptionPlanService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每周日晚上刷新 年付用户、月付用户的积分
|
* 每周日晚上刷新 年付用户、月付用户的积分
|
||||||
@@ -86,4 +89,14 @@ public class AccountTask {
|
|||||||
public void checkEduAdminExpireStatus() {
|
public void checkEduAdminExpireStatus() {
|
||||||
accountService.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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.ai.da.controller;
|
package com.ai.da.controller;
|
||||||
|
|
||||||
import com.ai.da.common.response.Response;
|
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.mapper.primary.entity.SubscriptionPlan;
|
||||||
import com.ai.da.model.dto.SubscriptionPlanDTO;
|
import com.ai.da.model.dto.SubscriptionPlanDTO;
|
||||||
import com.ai.da.model.dto.SubscriptionPlanPageQuery;
|
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.model.vo.SubscriptionPlanVO;
|
||||||
import com.ai.da.service.SubscriptionPlanService;
|
import com.ai.da.service.SubscriptionPlanService;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
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.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
@@ -26,6 +28,8 @@ public class SubscriptionPlanController {
|
|||||||
|
|
||||||
private final SubscriptionPlanService subscriptionPlanService;
|
private final SubscriptionPlanService subscriptionPlanService;
|
||||||
|
|
||||||
|
private final SubscriptionReminderTask subscriptionReminderTask;
|
||||||
|
|
||||||
@Operation(summary = "创建订阅计划")
|
@Operation(summary = "创建订阅计划")
|
||||||
@PostMapping("/createPlan")
|
@PostMapping("/createPlan")
|
||||||
public Response<String> createPlan(@Valid @RequestBody SubscriptionPlanDTO subscriptionPlanDTO) {
|
public Response<String> createPlan(@Valid @RequestBody SubscriptionPlanDTO subscriptionPlanDTO) {
|
||||||
@@ -74,6 +78,7 @@ public class SubscriptionPlanController {
|
|||||||
return Response.success();
|
return Response.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Hidden
|
||||||
@Operation(summary = "activeSubscriptionPlan")
|
@Operation(summary = "activeSubscriptionPlan")
|
||||||
@GetMapping("/activeSubscriptionPlan")
|
@GetMapping("/activeSubscriptionPlan")
|
||||||
public Response<String> activeSubscriptionPlan() {
|
public Response<String> activeSubscriptionPlan() {
|
||||||
@@ -81,6 +86,7 @@ public class SubscriptionPlanController {
|
|||||||
return Response.success();
|
return Response.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Hidden
|
||||||
@Operation(summary = "expireSubscription")
|
@Operation(summary = "expireSubscription")
|
||||||
@GetMapping("/expireSubscription")
|
@GetMapping("/expireSubscription")
|
||||||
public Response<String> expireSubscription() {
|
public Response<String> expireSubscription() {
|
||||||
@@ -88,5 +94,19 @@ public class SubscriptionPlanController {
|
|||||||
return Response.success();
|
return Response.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "subscriptionReminder")
|
||||||
|
@GetMapping("/subscriptionReminder")
|
||||||
|
public Response<String> subscriptionReminder() {
|
||||||
|
subscriptionReminderTask.subscriptionReminder();
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "trialReminder")
|
||||||
|
@GetMapping("/trialReminder")
|
||||||
|
public Response<String> trialReminder() {
|
||||||
|
subscriptionReminderTask.trialReminder();
|
||||||
|
return Response.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,14 @@ public interface SubscriptionPlanMapper extends BaseMapper<SubscriptionPlan> {
|
|||||||
/**
|
/**
|
||||||
* 关联查询订阅计划信息(包含管理员邮箱)- 分页
|
* 关联查询订阅计划信息(包含管理员邮箱)- 分页
|
||||||
*/
|
*/
|
||||||
@Select("SELECT sp.*, a.user_email as adminAccEmail, a.user_name as adminAccName " +
|
@Select("""
|
||||||
"FROM t_subscription_plan sp " +
|
SELECT sp.*,
|
||||||
"LEFT JOIN t_account a ON sp.admin_acc_id = a.id " +
|
a.user_email AS adminAccEmail,
|
||||||
"WHERE sp.is_deleted = 0 " +
|
a.user_name AS adminAccName
|
||||||
"${ew.customSqlSegment}")
|
FROM t_subscription_plan sp
|
||||||
|
LEFT JOIN t_account a ON sp.admin_acc_id = a.id
|
||||||
|
${ew.customSqlSegment}
|
||||||
|
""")
|
||||||
Page<SubscriptionPlanVO> selectWithEmailPage(Page<SubscriptionPlanVO> page,
|
Page<SubscriptionPlanVO> selectWithEmailPage(Page<SubscriptionPlanVO> page,
|
||||||
@Param(Constants.WRAPPER) Wrapper<?> wrapper);
|
@Param(Constants.WRAPPER) Wrapper<?> wrapper);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,4 +83,6 @@ public class AccountLoginVO {
|
|||||||
|
|
||||||
private String organizationName;
|
private String organizationName;
|
||||||
|
|
||||||
|
private Long subscriptionPlanId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2421,6 +2421,9 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
|
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
|
||||||
Account adminAcc = accountMapper.selectById(authPrincipalVo.getId());
|
Account adminAcc = accountMapper.selectById(authPrincipalVo.getId());
|
||||||
int subUserRole = getSubUserRole(adminAcc.getSystemUser());
|
int subUserRole = getSubUserRole(adminAcc.getSystemUser());
|
||||||
|
if (Objects.isNull(adminAcc.getSubscriptionPlanId())) {
|
||||||
|
throw new BusinessException("relate.to.any.subscription");
|
||||||
|
}
|
||||||
|
|
||||||
if (addSubAccountDTO.getId() == null) {
|
if (addSubAccountDTO.getId() == null) {
|
||||||
return createSubAccount(addSubAccountDTO, adminAcc, subUserRole);
|
return createSubAccount(addSubAccountDTO, adminAcc, subUserRole);
|
||||||
@@ -3177,6 +3180,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
response.setUsernameModify(getNicknameModifyTimes());
|
response.setUsernameModify(getNicknameModifyTimes());
|
||||||
response.setOrganizationId(account.getOrganizationId());
|
response.setOrganizationId(account.getOrganizationId());
|
||||||
response.setOrganizationName(account.getOrganizationName());
|
response.setOrganizationName(account.getOrganizationName());
|
||||||
|
response.setSubscriptionPlanId(account.getSubscriptionPlanId());
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1029,14 +1029,16 @@ public class StripeServiceImpl implements StripeService {
|
|||||||
}else {
|
}else {
|
||||||
List<SubscriptionInfo> activeSubscriptions = subscriptionInfoList.stream()
|
List<SubscriptionInfo> activeSubscriptions = subscriptionInfoList.stream()
|
||||||
.filter(subscription -> "active".equals(subscription.getStatus()))
|
.filter(subscription -> "active".equals(subscription.getStatus()))
|
||||||
.collect(Collectors.toList());
|
.toList();
|
||||||
if (!StringUtil.isNullOrEmpty(type) && type.equals("cancel")){
|
if (!StringUtil.isNullOrEmpty(type) && type.equals("cancel")){
|
||||||
subscriptionInfo = subscriptionInfoList.get(0);
|
subscriptionInfo = subscriptionInfoList.getFirst();
|
||||||
}else if (activeSubscriptions.isEmpty()){
|
} else if (!StringUtil.isNullOrEmpty(type) && type.equals("reminder_expire")) {
|
||||||
|
subscriptionInfo = subscriptionInfoList.getFirst();
|
||||||
|
} else if (activeSubscriptions.isEmpty() && type.equals("cancel")){
|
||||||
log.info("不发送邮件,原因:【当前邮件类型:{}, 但是状态为active的subscriptionInfo为空】", type);
|
log.info("不发送邮件,原因:【当前邮件类型:{}, 但是状态为active的subscriptionInfo为空】", type);
|
||||||
return false;
|
return false;
|
||||||
}else {
|
} else {
|
||||||
subscriptionInfo = activeSubscriptions.get(0);
|
subscriptionInfo = activeSubscriptions.getFirst();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else if (!StringUtil.isNullOrEmpty(orderNo)) {
|
}else if (!StringUtil.isNullOrEmpty(orderNo)) {
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
public List<SubscriptionPlan> searchByOrganizationIdAndStatus(SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
public List<SubscriptionPlan> searchByOrganizationIdAndStatus(SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
||||||
QueryWrapper<SubscriptionPlan> queryWrapper = new QueryWrapper<>();
|
QueryWrapper<SubscriptionPlan> queryWrapper = new QueryWrapper<>();
|
||||||
|
|
||||||
|
queryWrapper.lambda().eq(SubscriptionPlan::getAdminAccId, UserContext.getUserHolder().getId());
|
||||||
if (Objects.nonNull(subscriptionPlanPageQuery.getOrganizationId())){
|
if (Objects.nonNull(subscriptionPlanPageQuery.getOrganizationId())){
|
||||||
queryWrapper.lambda().eq(SubscriptionPlan::getOrganizationId, subscriptionPlanPageQuery.getOrganizationId());
|
queryWrapper.lambda().eq(SubscriptionPlan::getOrganizationId, subscriptionPlanPageQuery.getOrganizationId());
|
||||||
} else {
|
} else {
|
||||||
@@ -163,7 +164,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
validatePageQuery(subscriptionPlanPageQuery);
|
validatePageQuery(subscriptionPlanPageQuery);
|
||||||
|
|
||||||
// 2. 构建查询条件(不需要包含is_deleted条件,因为SQL中已包含)
|
// 2. 构建查询条件(不需要包含is_deleted条件,因为SQL中已包含)
|
||||||
LambdaQueryWrapper<SubscriptionPlan> queryWrapper = buildQueryWrapperWithoutDeleted(subscriptionPlanPageQuery);
|
QueryWrapper<SubscriptionPlan> queryWrapper = buildQueryWrapperWithoutDeleted(subscriptionPlanPageQuery);
|
||||||
|
|
||||||
// 3. 执行自定义的分页查询
|
// 3. 执行自定义的分页查询
|
||||||
Page<SubscriptionPlanVO> page = new Page<>(
|
Page<SubscriptionPlanVO> page = new Page<>(
|
||||||
@@ -178,37 +179,38 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
/**
|
/**
|
||||||
* 构建查询条件(不包含is_deleted条件,因为SQL中已包含)
|
* 构建查询条件(不包含is_deleted条件,因为SQL中已包含)
|
||||||
*/
|
*/
|
||||||
private LambdaQueryWrapper<SubscriptionPlan> buildQueryWrapperWithoutDeleted(SubscriptionPlanPageQuery query) {
|
private QueryWrapper<SubscriptionPlan> buildQueryWrapperWithoutDeleted(SubscriptionPlanPageQuery query) {
|
||||||
LambdaQueryWrapper<SubscriptionPlan> wrapper = new LambdaQueryWrapper<>();
|
QueryWrapper<SubscriptionPlan> wrapper = new QueryWrapper<>();
|
||||||
|
|
||||||
// 精确匹配条件
|
// 精确匹配条件 - 需要指定表别名
|
||||||
if (query.getId() != null) {
|
if (query.getId() != null) {
|
||||||
wrapper.eq(SubscriptionPlan::getId, query.getId());
|
wrapper.eq("sp.id", query.getId());
|
||||||
}
|
}
|
||||||
if (query.getOrganizationId() != null) {
|
if (query.getOrganizationId() != null) {
|
||||||
wrapper.eq(SubscriptionPlan::getOrganizationId, query.getOrganizationId());
|
wrapper.eq("sp.organization_id", query.getOrganizationId());
|
||||||
}
|
}
|
||||||
if (query.getAdminAccId() != null) {
|
if (query.getAdminAccId() != null) {
|
||||||
wrapper.eq(SubscriptionPlan::getAdminAccId, query.getAdminAccId());
|
wrapper.eq("sp.admin_acc_id", query.getAdminAccId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 时间范围查询
|
// 时间范围查询
|
||||||
if (StringUtils.isNotBlank(query.getStartTime())) {
|
if (StringUtils.isNotBlank(query.getStartTime())) {
|
||||||
LocalDateTime startTime = parseDateTime(query.getStartTime());
|
LocalDateTime startTime = parseDateTime(query.getStartTime());
|
||||||
wrapper.ge(SubscriptionPlan::getCreateTime, startTime);
|
wrapper.ge("sp.create_time", startTime);
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotBlank(query.getEndTime())) {
|
if (StringUtils.isNotBlank(query.getEndTime())) {
|
||||||
LocalDateTime endTime = parseDateTime(query.getEndTime());
|
LocalDateTime endTime = parseDateTime(query.getEndTime());
|
||||||
wrapper.le(SubscriptionPlan::getCreateTime, endTime);
|
wrapper.le("sp.create_time", endTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 状态匹配
|
// 状态匹配
|
||||||
if (!CollectionUtils.isEmpty(query.getStatus())) {
|
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;
|
return wrapper;
|
||||||
}
|
}
|
||||||
@@ -752,6 +754,8 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
// 5. 管理员当前未使用这个订阅,只处理订阅关系状态
|
// 5. 管理员当前未使用这个订阅,只处理订阅关系状态
|
||||||
log.info("订阅{}已过期,但管理员{}未激活此订阅", plan.getId(), adminAccount.getId());
|
log.info("订阅{}已过期,但管理员{}未激活此订阅", plan.getId(), adminAccount.getId());
|
||||||
}
|
}
|
||||||
|
// 6. 处理该订阅下的子账号
|
||||||
|
processChildAccountsForExpiredSubscription(plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -800,14 +804,10 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
log.info("管理员{}没有其他活跃订阅,降级为游客", adminAccount.getId());
|
log.info("管理员{}没有其他活跃订阅,降级为游客", adminAccount.getId());
|
||||||
|
|
||||||
// downgradeAccountToVisitor(adminAccount);
|
// downgradeAccountToVisitor(adminAccount);
|
||||||
// todo toVisitor 需要更新其他字段,如subscriptionPlanId, parentId
|
|
||||||
accountMapper.toVisitor(adminAccount.getId());
|
accountMapper.toVisitor(adminAccount.getId());
|
||||||
log.info("管理员账号{}已降级为游客", adminAccount.getId());
|
log.info("管理员账号{}已降级为游客", adminAccount.getId());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. 处理该订阅下的子账号
|
|
||||||
processChildAccountsForExpiredSubscription(expiringPlan);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -926,7 +926,9 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
if (Objects.isNull(subscriptionPlan)) {
|
if (Objects.isNull(subscriptionPlan)) {
|
||||||
throw new BusinessException("unknown.subscription.plan");
|
throw new BusinessException("unknown.subscription.plan");
|
||||||
}
|
}
|
||||||
if (subscriptionPlan.getStatus().equals(SubscriptionPlan.SubscriptionStatus.EXPIRED.name())) {
|
long now = System.currentTimeMillis() / 1000;
|
||||||
|
if (subscriptionPlan.getStatus().equals(SubscriptionPlan.SubscriptionStatus.EXPIRED.name())
|
||||||
|
|| subscriptionPlan.getCurrentPeriodEnd() <= now) {
|
||||||
throw new BusinessException("subscription.has.expired");
|
throw new BusinessException("subscription.has.expired");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ the.workspaceName.already.exists=A workspace with this name already exists.
|
|||||||
unable.to.delete.the.workspace.you.are.currently.using=The workspace you are currently using cannot be deleted. Please select another workspace before trying to delete.
|
unable.to.delete.the.workspace.you.are.currently.using=The workspace you are currently using cannot be deleted. Please select another workspace before trying to delete.
|
||||||
classificationName.already.exists=The label name you've entered already exists. Please enter a different label name to avoid duplication.
|
classificationName.already.exists=The label name you've entered already exists. Please enter a different label name to avoid duplication.
|
||||||
account.expired=Your subscription has expired, and your account has been reset to a visitor account. Please log in again from the [Individual] entry. If you have any questions, please contact us at info@code-create.com.hk
|
account.expired=Your subscription has expired, and your account has been reset to a visitor account. Please log in again from the [Individual] entry. If you have any questions, please contact us at info@code-create.com.hk
|
||||||
|
relate.to.any.subscription=Your administrator account is not currently linked to any subscription. If you have any questions, please contact us at info@code-create.com.hk
|
||||||
|
|
||||||
# Warnings:
|
# Warnings:
|
||||||
# 用来提醒用户可能会导致不良后果的操作,但不一定是错误。用户需要认真考虑是否继续当前操作。
|
# 用来提醒用户可能会导致不良后果的操作,但不一定是错误。用户需要认真考虑是否继续当前操作。
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ chat-bot.interface.exception=聊天机器人接口出现错误。(请稍后再
|
|||||||
compose-layer.interface.exception=图层合并时出现问题。(请稍后再试。如果问题持续,请联系我们的help@aida.com.hk)
|
compose-layer.interface.exception=图层合并时出现问题。(请稍后再试。如果问题持续,请联系我们的help@aida.com.hk)
|
||||||
cloth-classification.interface.exception=获取服装类别时出现问题。(请稍后再试。如果问题持续,请联系我们的help@aida.com.hk)
|
cloth-classification.interface.exception=获取服装类别时出现问题。(请稍后再试。如果问题持续,请联系我们的help@aida.com.hk)
|
||||||
account.expired=您的订阅已过期,账号已被重置为访客身份,请从【个人账号】入口重新登录。如有疑问,请联系 info@code-create.com.hk。
|
account.expired=您的订阅已过期,账号已被重置为访客身份,请从【个人账号】入口重新登录。如有疑问,请联系 info@code-create.com.hk。
|
||||||
|
relate.to.any.subscription=您的管理员账号暂未关联任何订阅,如有疑问,请联系我们 info@code-create.com.hk
|
||||||
|
|
||||||
# 多语言返回
|
# 多语言返回
|
||||||
OVERALL=整体
|
OVERALL=整体
|
||||||
|
|||||||
Reference in New Issue
Block a user