@@ -2,6 +2,7 @@ package com.ai.da.service.impl;
import com.ai.da.common.config.exception.BusinessException ;
import com.ai.da.common.context.UserContext ;
import com.ai.da.common.response.ResultEnum ;
import com.ai.da.common.utils.CopyUtil ;
import com.ai.da.common.utils.RedisUtil ;
import com.ai.da.mapper.primary.AccountMapper ;
@@ -51,7 +52,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
// 创建
@Override
public void createPlan ( SubscriptionPlanDTO subscriptionPlanDTO ) {
public void createPlan ( SubscriptionPlanDTO subscriptionPlanDTO ) {
SubscriptionPlan subscriptionPlan = CopyUtil . copyObject ( subscriptionPlanDTO , SubscriptionPlan . class ) ;
subscriptionPlan . setStatus ( SubscriptionPlan . SubscriptionStatus . PENDING . name ( ) ) ;
subscriptionPlan . setName ( " DEFAULT_NAME " ) ;
@@ -66,7 +67,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
// 更新 到期时间、积分总量、已使用积分量
@Override
public void updatePlan ( UpdateSubscriptionPlanDTO updateDTO ) {
public void updatePlan ( UpdateSubscriptionPlanDTO updateDTO ) {
if ( Objects . isNull ( updateDTO . getId ( ) ) ) {
throw new BusinessException ( " id.cannot.be.empty " ) ;
}
@@ -101,7 +102,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
}
public void updatePlan ( ) {
public void updatePlan ( ) {
}
@@ -120,7 +121,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
IPage < SubscriptionPlan > resultPage = baseMapper . selectPage ( page , queryWrapper ) ;
// 4. 转换为VO并返回
return resultPage . convert ( ( Function < SubscriptionPlan , SubscriptionPlanVO > ) plan - > CopyUtil . copyObject ( plan , SubscriptionPlanVO . class ) ) ;
return resultPage . convert ( ( Function < SubscriptionPlan , SubscriptionPlanVO > ) plan - > CopyUtil . copyObject ( plan , SubscriptionPlanVO . class ) ) ;
}
/**
@@ -129,10 +130,10 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
private void validatePageQuery ( SubscriptionPlanPageQuery query ) {
// 基本分页参数校验( JSR-303已校验, 这里做额外业务校验)
if ( query . getPage ( ) < = 0 ) {
throw new BusinessException ( " 页码必须大于0 " ) ;
throw new BusinessException ( " page.num.limit " ) ;
}
if ( query . getSize ( ) < = 0 | | query . getSize ( ) > 100 ) {
throw new BusinessException ( " 每页数量必须在1-100之间 " ) ;
throw new BusinessException ( " page.size.limit " ) ;
}
// 时间格式校验
@@ -142,10 +143,10 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
LocalDateTime end = parseDateTime ( query . getEndTime ( ) ) ;
assert start ! = null ;
if ( start . isAfter ( end ) ) {
throw new BusinessException ( " 开始时间不能晚于结束时间 " ) ;
throw new BusinessException ( " the.start.time.cannot.be.later.than.the.end.time " ) ;
}
} catch ( DateTimeParseException e ) {
throw new BusinessException ( " 时间格式错误, 请使用yyyy-MM-dd HH:mm:ss格式 " ) ;
throw new BusinessException ( " invalid.time.format " ) ;
}
}
@@ -154,7 +155,8 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
try {
SubscriptionPlan . SubscriptionStatus . valueOf ( status . toUpperCase ( ) ) ;
} catch ( IllegalArgumentException e ) {
throw new BusinessException ( " 未知订阅状态: " + status ) ;
log . error ( " 未知订阅状态:{} " , status ) ;
throw new BusinessException ( " unknown.subscription.status " ) ;
}
}
@@ -229,18 +231,18 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
Long adminAccountId = UserContext . getUserHolder ( ) . getId ( ) ;
// 1. 参数基础校验
if ( id = = null | | id < = 0 ) {
throw new BusinessException ( " ID不能为空且必须大于 0 " ) ;
throw new BusinessException ( " ID.cannot.be.empty.and.must.be.greater.than. 0 " ) ;
}
// 2. 检查数据是否存在
SubscriptionPlan plan = baseMapper . selectById ( id ) ;
if ( plan = = null ) {
throw new BusinessException ( " 订阅计划不存在 " ) ;
throw new BusinessException ( " subscription.plan.does.not.exist " ) ;
}
// 3. 检查是否已被删除(防止重复删除) 一般情况下走不到, 逻辑删除的数据通过mybatis-plus查不到
if ( plan . getIsDeleted ( ) = = 1 ) {
throw new BusinessException ( " 该订阅计划已被删除 " ) ;
throw new BusinessException ( " subscription.plan.has.been.deleted " ) ;
}
// 4. 检查业务约束条件(例如:是否有正在使用的订单等)
@@ -254,7 +256,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
int rows = baseMapper . update ( null , wrapper ) ;
if ( rows = = 0 ) {
throw new BusinessException ( " 删除失败,请稍后重试 " ) ;
throw new BusinessException ( " deletion.failed.please.try.again.later " ) ;
}
// 6. 记录操作日志
@@ -269,12 +271,12 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
// 检查是否有活跃的用户关联
Long activeSubAcc = countActiveSubAccByPlanId ( plan . getId ( ) ) ;
if ( activeSubAcc > 0 ) {
throw new BusinessException ( " 存在 " + activeSubAcc + " 个用户使用此计划,无法删除 " ) ;
throw new BusinessException ( " users.currently.using.this.plan " ) ;
}
// 检查是否在有效期内
if ( plan . getCurrentPeriodEnd ( ) ! = null & & isExpired ( plan . getCurrentPeriodEnd ( ) ) ) {
throw new BusinessException ( " 计划仍在有效期内,请到期后再删除 " ) ;
throw new BusinessException ( " valid.subscription.period " ) ;
}
}
@@ -321,6 +323,10 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
for ( SubscriptionPlan plan : todayActivePlans ) {
try {
processActiveSubscriptionPlan ( plan ) ;
// 3. 修改订阅状态
plan . setStatus ( SubscriptionPlan . SubscriptionStatus . ACTIVE . name ( ) ) ;
plan . setUpdateTime ( LocalDateTime . now ( ) ) ;
baseMapper . updateById ( plan ) ;
} catch ( Exception e ) {
log . error ( " 处理订阅计划失败, ID: {}, 错误: {} " , plan . getId ( ) , e . getMessage ( ) , e ) ;
// 继续处理其他计划,不中断整体流程
@@ -366,14 +372,12 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
// 3. 检查管理员当前是否处于其他有效订阅中
if ( isAccountInActiveSubscription ( adminAccount , plan . getId ( ) ) ) {
log . info ( " 管理员ID: {} 已处于有效订阅中,本次不修改账户信息 " , adminAccount . getId ( ) ) ;
return ;
}
// 4. 更新管理员账号信息
updateAdminAccount ( adminAccount , plan ) ;
// 5. 修改订阅状态
plan . setStatus ( SubscriptionPlan . SubscriptionStatus . ACTIVE . name ( ) ) ;
log . info ( " 订阅计划处理完成, ID: {} " , plan . getId ( ) ) ;
}
@@ -385,14 +389,19 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
updateAccount . setId ( account . getId ( ) ) ;
// ① 根据订阅结束时间延长管理员账号有效期validEndTime
Long newValidEndTime = calculateNewValidEndTime( account, plan ) ;
updateAccount . setValidEndTime ( newValidEndTime ) ;
// Long newValidEndTime = calculateNewValidEndTime( account, plan) ;
updateAccount . setValidEndTime ( plan . getCurrentPeriodEnd ( ) * 1000 ) ;
// ② 根据积分上限更新管理员的积分credits和身份systemUser
// 暂时保留管理员自己购买的积分
if ( Objects . nonNull ( account . getCreditsUsageLimit ( ) ) ) {
if ( ( account . getSystemUser ( ) = = 5 | | account . getSystemUser ( ) = = 7 )
& & Objects . nonNull ( account . getCreditsUsageLimit ( ) ) ) {
BigDecimal leftCredits = account . getCredits ( ) . add ( account . getCreditsUsage ( ) ) . subtract ( account . getCreditsUsageLimit ( ) ) ;
updateAccount . setCredits ( plan . getCreditLimit ( ) . add ( leftCredits ) ) ;
if ( leftCredits . compareTo ( BigDecimal . ZERO ) > 0 ) {
updateAccount . setCredits ( plan . getCreditLimit ( ) . add ( leftCredits ) ) ;
} else {
updateAccount . setCredits ( plan . getCreditLimit ( ) ) ;
}
} else {
updateAccount . setCredits ( plan . getCreditLimit ( ) . add ( account . getCredits ( ) ) ) ;
}
@@ -422,7 +431,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
if ( rows > 0 ) {
log . info ( " 管理员账号更新成功, ID: {}, 有效期至: {}, 用户类型: {}, 积分: {} " ,
account . getId ( ) ,
formatTimestamp ( newValidEndTime ) ,
formatTimestamp ( plan . getCurrentPeriodEnd ( ) ) ,
newSystemUser ,
plan . getCreditLimit ( ) ) ;
@@ -461,7 +470,8 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
Organization organization = organizationMapper . selectById ( orgId ) ;
if ( Objects . isNull ( organization ) ) {
throw new BusinessException ( " 未知组织id: " + orgId ) ;
log . error ( " 未知组织id: {} " , orgId ) ;
throw new BusinessException ( " unknown.organization " ) ;
}
if ( organization . getType ( ) . equals ( " Enterprise " ) ) {
return 5 ; // 学校管理员
@@ -525,9 +535,20 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
public void expireSubscription ( ) {
// 1. 查询有哪些已过期订阅
List < SubscriptionPlan > recentlyExpiredPlans = findRecentlyExpiredPlans ( ) ;
if ( CollectionUtils . isEmpty ( recentlyExpiredPlans ) ) {
log . info ( " 过去24h没有过期的订阅计划 " ) ;
return ;
}
log . info ( " 发现{}个过去24h过期的订阅计划 " , recentlyExpiredPlans . size ( ) ) ;
// 2. 更新与订阅相关账号的状态
for ( SubscriptionPlan subscriptionPlan : recentlyExpiredPlans ) {
processExpiringSubscriptionPlan ( subscriptionPlan ) ;
// 6. 修改订阅状态
subscriptionPlan . setStatus ( SubscriptionPlan . SubscriptionStatus . EXPIRED . name ( ) ) ;
subscriptionPlan . setUpdateTime ( LocalDateTime . now ( ) ) ;
baseMapper . updateById ( subscriptionPlan ) ;
}
}
@@ -538,6 +559,8 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
long now = System . currentTimeMillis ( ) / 1000 ;
long yesterday = now - ( 24 * 60 * 60 ) ; // 24小时前
log . debug ( " 扫描时间范围: {} - {} (过去24h) " , formatTimestamp ( yesterday ) , formatTimestamp ( now ) ) ;
QueryWrapper < SubscriptionPlan > queryWrapper = new QueryWrapper < > ( ) ;
queryWrapper . eq ( " is_deleted " , 0 )
. between ( " current_period_end " , yesterday , now ) // 过去24小时内到期
@@ -577,9 +600,6 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
// 5. 管理员当前未使用这个订阅,只处理订阅关系状态
log . info ( " 订阅{}已过期,但管理员{}未激活此订阅 " , plan . getId ( ) , adminAccount . getId ( ) ) ;
}
// 6. 修改订阅状态
plan . setStatus ( SubscriptionPlan . SubscriptionStatus . EXPIRED . name ( ) ) ;
}
/**
@@ -595,11 +615,6 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
return null ;
}
long now = System . currentTimeMillis ( ) / 1000 ;
if ( plan . getCurrentPeriodStart ( ) > now | | plan . getCurrentPeriodEnd ( ) < now ) {
return null ; // 不在有效期内
}
return plan ;
}
@@ -623,6 +638,11 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
// 3. 切换到开始最早的订阅
updateAdminAccount ( adminAccount , earliestActivePlan ) ;
// 4. 修改订阅状态
earliestActivePlan . setStatus ( SubscriptionPlan . SubscriptionStatus . ACTIVE . name ( ) ) ;
earliestActivePlan . setUpdateTime ( LocalDateTime . now ( ) ) ;
baseMapper . updateById ( earliestActivePlan ) ;
} else {
// 5. 没有其他活跃订阅,将管理员降级为游客
log . info ( " 管理员{}没有其他活跃订阅,降级为游客 " , adminAccount . getId ( ) ) ;
@@ -692,6 +712,9 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
if ( Objects . isNull ( subscriptionPlan ) ) {
throw new BusinessException ( " unknown.subscription.plan " ) ;
}
if ( subscriptionPlan . getStatus ( ) . equals ( SubscriptionPlan . SubscriptionStatus . EXPIRED . name ( ) ) ) {
throw new BusinessException ( " subscription.has.expired " ) ;
}
if ( ! accountId . equals ( subscriptionPlan . getAdminAccId ( ) ) & & ! accountId . equals ( 87L ) ) {
throw new BusinessException ( " have.no.permission " ) ;
}
@@ -702,7 +725,15 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
}
Account account = accountMapper . selectById ( adminAccId ) ;
if ( Objects . isNull ( account ) ) {
throw new BusinessException ( " 切换失败,未知管理员用户 " ) ;
throw new BusinessException ( " unknown.administrator.user " ) ;
}
if ( ! adminAccId . equals ( subscriptionPlan . getAdminAccId ( ) ) ) {
log . info ( " 用户:{} 没有权限管理订阅:{} " , adminAccId , subscriptionPlanId ) ;
throw new BusinessException ( " no.permission.manage.subscription " , ResultEnum . PROMPT . getCode ( ) ) ;
}
if ( account . getSubscriptionPlanId ( ) . equals ( subscriptionPlanId ) ) {
log . info ( " 用户:{} 当前正在管理订阅 {} " , adminAccId , subscriptionPlanId ) ;
return ;
}
updateAdminAccount ( account , subscriptionPlan ) ;