Merge branch 'dev/dev_xp' into dev/3.1_release_merge
# Conflicts: # src/main/java/com/ai/da/model/dto/SubscriptionPlanDTO.java # src/main/java/com/ai/da/model/vo/SubscriptionPlanVO.java
This commit is contained in:
@@ -308,7 +308,7 @@ public class MyTaskScheduler {
|
||||
private MinioUtil minioUtil;
|
||||
@Resource
|
||||
private UserLikeService userLikeService;
|
||||
public void clearMinio() {
|
||||
/* public void clearMinio() {
|
||||
List<CollectionElement> collectionElements = collectionElementMapper.selectDeleteList();
|
||||
for (CollectionElement collectionElement : collectionElements) {
|
||||
String url = collectionElement.getUrl();
|
||||
@@ -472,7 +472,7 @@ public class MyTaskScheduler {
|
||||
// }
|
||||
// String preSignedUrl = minioUtil.getPreSignedUrl("aida-clothing/image/image_1698374859.3031476.png", 10000);
|
||||
// System.out.println(preSignedUrl);
|
||||
}
|
||||
}*/
|
||||
|
||||
@Resource
|
||||
private AttributeRetrievalMapper attributeRetrievalMapper;
|
||||
|
||||
@@ -883,8 +883,8 @@ public class SendEmailUtil {
|
||||
|
||||
if (!type.equals("cancel") && !type.equals("fail_new")) {
|
||||
// 返回的resp是一个SendEmailResponse的实例,与请求对象对应
|
||||
// SendEmailResponse respUser = client.SendEmail(user);
|
||||
log.info("邮件主题:{},发送结果toUser###{}, email:{}", user.getSubject(), /*SendEmailResponse.toJsonString(respUser)*/null, receiverAddress);
|
||||
SendEmailResponse respUser = client.SendEmail(user);
|
||||
log.info("邮件主题:{},发送结果toUser###{}, email:{}", user.getSubject(), SendEmailResponse.toJsonString(respUser), receiverAddress);
|
||||
}
|
||||
if (!type.startsWith("reminder")) {
|
||||
SendEmailResponse respMerchant = client.SendEmail(merchant);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ai.da.controller;
|
||||
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.mapper.primary.entity.SubscriptionPlan;
|
||||
import com.ai.da.model.dto.SubscriptionPlanDTO;
|
||||
import com.ai.da.model.dto.SubscriptionPlanPageQuery;
|
||||
import com.ai.da.model.dto.UpdateSubscriptionPlanDTO;
|
||||
@@ -14,6 +15,8 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "订阅计划模块")
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@@ -38,6 +41,12 @@ public class SubscriptionPlanController {
|
||||
}
|
||||
|
||||
@Operation(summary = "搜索订阅计划")
|
||||
@PostMapping("/searchByOrganizationIdAndStatus")
|
||||
public Response<List<SubscriptionPlan>> searchByOrganizationIdAndStatus(@Valid @RequestBody SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
||||
return Response.success(subscriptionPlanService.searchByOrganizationIdAndStatus(subscriptionPlanPageQuery));
|
||||
}
|
||||
|
||||
@Operation(summary = "分页搜索订阅计划")
|
||||
@PostMapping("/searchByPage")
|
||||
public Response<IPage<SubscriptionPlanVO>> searchByPage(@Valid @RequestBody SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
||||
IPage<SubscriptionPlanVO> subscriptionPlanVOIPage = subscriptionPlanService.searchByPage(subscriptionPlanPageQuery);
|
||||
@@ -53,8 +62,15 @@ public class SubscriptionPlanController {
|
||||
|
||||
@Operation(summary = "管理员切换订阅计划")
|
||||
@GetMapping("/switchSubscriptionPlan")
|
||||
public Response<String> switchSubscriptionPlan(@RequestParam Long subscriptionPlanId, @RequestParam Long adminAccId) {
|
||||
subscriptionPlanService.switchSubscriptionPlan(subscriptionPlanId, adminAccId);
|
||||
public Response<String> switchSubscriptionPlan(@RequestParam Long targetSubscriptionPlanId, @RequestParam(required = false) Long adminAccId) {
|
||||
subscriptionPlanService.switchSubscriptionPlan(targetSubscriptionPlanId, adminAccId);
|
||||
return Response.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "子账号切换订阅计划")
|
||||
@GetMapping("/switchSubAccSubscriptionPlan")
|
||||
public Response<String> switchSubAccSubscriptionPlan(@RequestParam Long targetSubscriptionPlanId, @RequestParam Long subAccId) {
|
||||
subscriptionPlanService.switchSubAccSubscriptionPlan(targetSubscriptionPlanId, subAccId);
|
||||
return Response.success();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,24 @@
|
||||
package com.ai.da.mapper.primary;
|
||||
|
||||
import com.ai.da.mapper.primary.entity.SubscriptionPlan;
|
||||
import com.ai.da.model.vo.SubscriptionPlanVO;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
public interface SubscriptionPlanMapper extends BaseMapper<SubscriptionPlan> {
|
||||
|
||||
/**
|
||||
* 关联查询订阅计划信息(包含管理员邮箱)- 分页
|
||||
*/
|
||||
@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}")
|
||||
Page<SubscriptionPlanVO> selectWithEmailPage(Page<SubscriptionPlanVO> page,
|
||||
@Param(Constants.WRAPPER) Wrapper<?> wrapper);
|
||||
}
|
||||
|
||||
@@ -14,4 +14,6 @@ public class SubAccountPageDTO extends PageQueryBaseVo {
|
||||
private List<String> email;
|
||||
|
||||
private List<String> userName;
|
||||
|
||||
private Long subscriptionPlanId;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package com.ai.da.model.dto;
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Positive;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -13,18 +15,22 @@ public class SubscriptionPlanDTO {
|
||||
|
||||
@Schema(description = "组织id")
|
||||
@NotNull(message = "Please select an organizationId.")
|
||||
@Positive(message = "组织ID必须大于0")
|
||||
private Long organizationId;
|
||||
|
||||
@Schema(description = "当前订阅开始时间")
|
||||
@NotNull(message = "Please set a subscription start time.")
|
||||
@Min(value = 0, message = "开始时间不能小于0")
|
||||
private Long currentPeriodStart;
|
||||
|
||||
@Schema(description = "当前订阅结束时间")
|
||||
@NotNull(message = "Please set a subscription end time.")
|
||||
@Min(value = 0, message = "结束时间不能小于0")
|
||||
private Long currentPeriodEnd;
|
||||
|
||||
@Schema(description = "当前订阅总的子账号数量")
|
||||
@NotNull(message = "Please set the sub-account number.")
|
||||
@Min(value = 0, message = "子账号数量不能小于0")
|
||||
private Integer accountNum;
|
||||
|
||||
@Schema(description = "当前订阅可用积分上限")
|
||||
@@ -33,6 +39,10 @@ public class SubscriptionPlanDTO {
|
||||
|
||||
@Schema(description = "管理员账户id")
|
||||
@NotNull(message = "Please assign an administrator account.")
|
||||
@Positive(message = "管理员账号ID必须大于0")
|
||||
private Long adminAccId;
|
||||
|
||||
@Schema(description = "订阅计划命名")
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
@@ -29,4 +29,7 @@ public class UpdateSubscriptionPlanDTO {
|
||||
@Schema(description = "管理员账户id")
|
||||
private Long adminAccId;
|
||||
|
||||
@ApiModelProperty("订阅重命名")
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
@@ -30,8 +30,16 @@ public class SubscriptionPlanVO {
|
||||
@Schema(description = "管理员账户id")
|
||||
private Long adminAccId;
|
||||
|
||||
@Schema(description = "管理员账户邮箱")
|
||||
private String adminAccEmail;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "命名")
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
@@ -8,18 +8,24 @@ import com.ai.da.model.vo.SubscriptionPlanVO;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SubscriptionPlanService extends IService<SubscriptionPlan> {
|
||||
|
||||
void createPlan(SubscriptionPlanDTO subscriptionPlanDTO);
|
||||
|
||||
void updatePlan(UpdateSubscriptionPlanDTO updateDTO);
|
||||
|
||||
List<SubscriptionPlan> searchByOrganizationIdAndStatus(SubscriptionPlanPageQuery subscriptionPlanPageQuery);
|
||||
|
||||
IPage<SubscriptionPlanVO> searchByPage(SubscriptionPlanPageQuery subscriptionPlanPageQuery);
|
||||
|
||||
void deletePlan(Long id);
|
||||
|
||||
void switchSubscriptionPlan(Long subscriptionPlanId, Long adminAccId);
|
||||
|
||||
void switchSubAccSubscriptionPlan(Long subscriptionPlanId, Long subAccId);
|
||||
|
||||
void activeSubscriptionPlan();
|
||||
|
||||
void expireSubscription();
|
||||
|
||||
@@ -2443,7 +2443,8 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean createSubAccount(AddSubAccountDTO addSubAccountDTO, Account adminAcc, int subUserRole) {
|
||||
QueryWrapper<Account> qw = new QueryWrapper<>();
|
||||
qw.lambda().eq(Account::getOrganizationId, adminAcc.getOrganizationId());
|
||||
qw.lambda().eq(Account::getOrganizationId, adminAcc.getOrganizationId())
|
||||
.eq(Account::getSubscriptionPlanId, adminAcc.getSubscriptionPlanId());
|
||||
List<Account> accounts = accountMapper.selectList(qw);
|
||||
|
||||
// 校验子账号总数是否达上限
|
||||
@@ -2493,6 +2494,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
|
||||
subAccount.setSystemUser(subUserRole);
|
||||
subAccount.setOrganizationId(adminAcc.getOrganizationId());
|
||||
subAccount.setOrganizationName(adminAcc.getOrganizationName());
|
||||
subAccount.setParentId(adminAcc.getId());
|
||||
subAccount.setSubscriptionPlanId(adminAcc.getSubscriptionPlanId());
|
||||
if (Objects.nonNull(addSubAccountDTO.getCreditsUsageLimit())) {
|
||||
@@ -2557,7 +2559,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
subAccount.setIsTrial(0);
|
||||
subAccount.setIsBeginner(1);
|
||||
subAccount.setParentId(adminAcc.getId());
|
||||
// subAccount.setOrganizationName(adminAcc.getOrganizationName());
|
||||
subAccount.setOrganizationName(adminAcc.getOrganizationName());
|
||||
subAccount.setOrganizationId(adminAcc.getOrganizationId());
|
||||
subAccount.setSubscriptionPlanId(adminAcc.getSubscriptionPlanId());
|
||||
accountMapper.insert(subAccount);
|
||||
@@ -2732,7 +2734,9 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
for (Long id : addSubAccountDTO.getDeleteIdList()) {
|
||||
Account account = baseMapper.selectById(id);
|
||||
if (Objects.nonNull(account.getParentId()) && account.getParentId().equals(adminAccId)) {
|
||||
BigDecimal unusedCredits = account.getCreditsUsageLimit().subtract(Objects.isNull(account.getCreditsUsage()) ? BigDecimal.ZERO : account.getCreditsUsage());
|
||||
BigDecimal unusedCredits =
|
||||
Objects.requireNonNullElse(account.getCreditsUsageLimit(), BigDecimal.ZERO)
|
||||
.subtract(Objects.requireNonNullElse(account.getCreditsUsage(), BigDecimal.ZERO));
|
||||
BigDecimal finalCredits = calculateFinalCredits(account, unusedCredits);
|
||||
|
||||
int userRole = determineUserRole(account.getId());
|
||||
@@ -2805,7 +2809,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
|
||||
Account account = accountMapper.selectById(authPrincipalVo);
|
||||
QueryWrapper<Account> qw = new QueryWrapper<>();
|
||||
qw.lambda().ne(Account::getId, account.getId());
|
||||
qw.lambda().ne(Account::getId, account.getId()).ne(Account::getSystemUser, 7);
|
||||
qw.lambda().eq(Account::getOrganizationId, account.getOrganizationId());
|
||||
if (StringUtils.isNotBlank(subAccountPageDTO.getStartTime())) {
|
||||
qw.lambda().ge(Account::getCreateDate, subAccountPageDTO.getStartTime());
|
||||
@@ -2823,6 +2827,9 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
} else if (subAccountPageDTO.getUserName() != null && subAccountPageDTO.getUserName().size() > 1) {
|
||||
qw.lambda().in(Account::getUserName, subAccountPageDTO.getUserName());
|
||||
}
|
||||
if (Objects.nonNull(subAccountPageDTO.getSubscriptionPlanId())) {
|
||||
qw.lambda().eq(Account::getSubscriptionPlanId, subAccountPageDTO.getSubscriptionPlanId());
|
||||
}
|
||||
|
||||
// 执行分页查询
|
||||
IPage<Account> page = accountMapper.selectPage(new Page<>(subAccountPageDTO.getPage(), subAccountPageDTO.getSize()), qw);
|
||||
|
||||
@@ -11,10 +11,12 @@ import com.ai.da.mapper.primary.SubscriptionPlanMapper;
|
||||
import com.ai.da.mapper.primary.entity.Account;
|
||||
import com.ai.da.mapper.primary.entity.Organization;
|
||||
import com.ai.da.mapper.primary.entity.SubscriptionPlan;
|
||||
import com.ai.da.model.dto.AddSubAccountDTO;
|
||||
import com.ai.da.model.dto.SubscriptionPlanDTO;
|
||||
import com.ai.da.model.dto.SubscriptionPlanPageQuery;
|
||||
import com.ai.da.model.dto.UpdateSubscriptionPlanDTO;
|
||||
import com.ai.da.model.vo.SubscriptionPlanVO;
|
||||
import com.ai.da.service.AccountService;
|
||||
import com.ai.da.service.SubscriptionPlanService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
@@ -22,7 +24,6 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.common.base.Function;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -36,6 +37,7 @@ import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -46,6 +48,8 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
|
||||
private final AccountMapper accountMapper;
|
||||
|
||||
private final AccountService accountService;
|
||||
|
||||
private final OrganizationMapper organizationMapper;
|
||||
|
||||
private final RedisUtil redisUtil;
|
||||
@@ -53,9 +57,14 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
// 创建
|
||||
@Override
|
||||
public void createPlan(SubscriptionPlanDTO subscriptionPlanDTO) {
|
||||
// 参数校验
|
||||
validateCreatePlanParams(subscriptionPlanDTO);
|
||||
|
||||
SubscriptionPlan subscriptionPlan = CopyUtil.copyObject(subscriptionPlanDTO, SubscriptionPlan.class);
|
||||
subscriptionPlan.setStatus(SubscriptionPlan.SubscriptionStatus.PENDING.name());
|
||||
subscriptionPlan.setName("DEFAULT_NAME");
|
||||
if (Objects.isNull(subscriptionPlan.getName())) {
|
||||
subscriptionPlan.setName("DEFAULT_NAME");
|
||||
}
|
||||
subscriptionPlan.setCreditUsage(BigDecimal.ZERO);
|
||||
subscriptionPlan.setCreateTime(LocalDateTime.now());
|
||||
if (Objects.isNull(subscriptionPlanDTO.getCreditLimit())) {
|
||||
@@ -65,6 +74,25 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
baseMapper.insert(subscriptionPlan);
|
||||
}
|
||||
|
||||
private void validateCreatePlanParams(SubscriptionPlanDTO subscriptionPlanDTO) {
|
||||
// 校验组织是否存在
|
||||
Organization organization = organizationMapper.selectById(subscriptionPlanDTO.getOrganizationId());
|
||||
if (Objects.isNull(organization)) {
|
||||
throw new BusinessException("unknown.organization");
|
||||
}
|
||||
|
||||
// 校验结束时间是否大于开始时间
|
||||
if (subscriptionPlanDTO.getCurrentPeriodEnd() <= subscriptionPlanDTO.getCurrentPeriodStart()) {
|
||||
throw new BusinessException("end.time.must.be.later.than.the.start.time");
|
||||
}
|
||||
|
||||
// 校验管理员账号id是否存在
|
||||
Account account = accountMapper.selectById(subscriptionPlanDTO.getAdminAccId());
|
||||
if (Objects.isNull(account)) {
|
||||
throw new BusinessException("unknown.administrator.user");
|
||||
}
|
||||
}
|
||||
|
||||
// 更新 到期时间、积分总量、已使用积分量
|
||||
@Override
|
||||
public void updatePlan(UpdateSubscriptionPlanDTO updateDTO) {
|
||||
@@ -97,6 +125,10 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
subscriptionPlan.setAdminAccId(updateDTO.getAdminAccId());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(updateDTO.getName()) && !updateDTO.getName().equals(subscriptionPlan.getName())) {
|
||||
subscriptionPlan.setName(updateDTO.getName());
|
||||
}
|
||||
|
||||
subscriptionPlan.setUpdateTime(LocalDateTime.now());
|
||||
updateById(subscriptionPlan);
|
||||
|
||||
@@ -107,8 +139,83 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
|
||||
}
|
||||
|
||||
// 查找 根据入参提供的参数进行分页查询
|
||||
@Override
|
||||
public List<SubscriptionPlan> searchByOrganizationIdAndStatus(SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
||||
QueryWrapper<SubscriptionPlan> queryWrapper = new QueryWrapper<>();
|
||||
|
||||
if (Objects.nonNull(subscriptionPlanPageQuery.getOrganizationId())){
|
||||
queryWrapper.lambda().eq(SubscriptionPlan::getOrganizationId, subscriptionPlanPageQuery.getOrganizationId());
|
||||
} else {
|
||||
throw new BusinessException("please.specify.the.organizationId");
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(subscriptionPlanPageQuery.getStatus())) {
|
||||
queryWrapper.lambda().in(SubscriptionPlan::getStatus, subscriptionPlanPageQuery.getStatus());
|
||||
}
|
||||
|
||||
return baseMapper.selectList(queryWrapper);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<SubscriptionPlanVO> searchByPage(SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
||||
// 1. 参数校验
|
||||
validatePageQuery(subscriptionPlanPageQuery);
|
||||
|
||||
// 2. 构建查询条件(不需要包含is_deleted条件,因为SQL中已包含)
|
||||
LambdaQueryWrapper<SubscriptionPlan> queryWrapper = buildQueryWrapperWithoutDeleted(subscriptionPlanPageQuery);
|
||||
|
||||
// 3. 执行自定义的分页查询
|
||||
Page<SubscriptionPlanVO> page = new Page<>(
|
||||
subscriptionPlanPageQuery.getPage(),
|
||||
subscriptionPlanPageQuery.getSize()
|
||||
);
|
||||
|
||||
// 查询数据
|
||||
return baseMapper.selectWithEmailPage(page, queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询条件(不包含is_deleted条件,因为SQL中已包含)
|
||||
*/
|
||||
private LambdaQueryWrapper<SubscriptionPlan> buildQueryWrapperWithoutDeleted(SubscriptionPlanPageQuery query) {
|
||||
LambdaQueryWrapper<SubscriptionPlan> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 精确匹配条件
|
||||
if (query.getId() != null) {
|
||||
wrapper.eq(SubscriptionPlan::getId, query.getId());
|
||||
}
|
||||
if (query.getOrganizationId() != null) {
|
||||
wrapper.eq(SubscriptionPlan::getOrganizationId, query.getOrganizationId());
|
||||
}
|
||||
if (query.getAdminAccId() != null) {
|
||||
wrapper.eq(SubscriptionPlan::getAdminAccId, query.getAdminAccId());
|
||||
}
|
||||
|
||||
// 时间范围查询
|
||||
if (StringUtils.isNotBlank(query.getStartTime())) {
|
||||
LocalDateTime startTime = parseDateTime(query.getStartTime());
|
||||
wrapper.ge(SubscriptionPlan::getCreateTime, startTime);
|
||||
}
|
||||
if (StringUtils.isNotBlank(query.getEndTime())) {
|
||||
LocalDateTime endTime = parseDateTime(query.getEndTime());
|
||||
wrapper.le(SubscriptionPlan::getCreateTime, endTime);
|
||||
}
|
||||
|
||||
// 状态匹配
|
||||
if (!CollectionUtils.isEmpty(query.getStatus())) {
|
||||
wrapper.in(SubscriptionPlan::getStatus, query.getStatus());
|
||||
}
|
||||
|
||||
// 按创建时间倒序排序
|
||||
wrapper.orderByDesc(SubscriptionPlan::getCreateTime);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
||||
// 查找 根据入参提供的参数进行分页查询
|
||||
/* @Override
|
||||
public IPage<SubscriptionPlanVO> searchByPage(SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
||||
// 1. 参数校验
|
||||
validatePageQuery(subscriptionPlanPageQuery);
|
||||
@@ -121,8 +228,9 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
IPage<SubscriptionPlan> resultPage = baseMapper.selectPage(page, queryWrapper);
|
||||
|
||||
// 4. 转换为VO并返回
|
||||
// todo 用户邮箱
|
||||
return resultPage.convert((Function<SubscriptionPlan, SubscriptionPlanVO>) plan -> CopyUtil.copyObject(plan, SubscriptionPlanVO.class));
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 参数校验
|
||||
@@ -295,17 +403,6 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
return currentPeriodEnd < currentTimestamp;
|
||||
}
|
||||
|
||||
// todo 切换管理员的账号
|
||||
|
||||
// 定时器更新管理员状态
|
||||
/* public void updateEduAdminAccount() {
|
||||
// 1. 扫描所有的订阅计划的开始时间currentPeriodStart
|
||||
|
||||
// 2. 当检测到有今天内开始有效的订阅,更新绑定的管理员的账号
|
||||
|
||||
// 3. 更新管理的信息包括,①根据订阅结束时间延长管理员账号有效期 ②根据积分上限更新管理员的积分,如果当前管理员正处于一个订阅中,则不做更新,但是允许切换
|
||||
}*/
|
||||
|
||||
public void activeSubscriptionPlan() {
|
||||
log.info("开始执行订阅计划生效检查...");
|
||||
|
||||
@@ -376,68 +473,120 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
}
|
||||
|
||||
// 4. 更新管理员账号信息
|
||||
updateAdminAccount(adminAccount, plan);
|
||||
updateAccount(adminAccount, plan, true);
|
||||
|
||||
log.info("订阅计划处理完成,ID: {}", plan.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新管理员账号信息
|
||||
* 更新账号信息(管理员和子账号)
|
||||
*/
|
||||
private void updateAdminAccount(Account account, SubscriptionPlan plan) {
|
||||
private void updateAccount(Account account, SubscriptionPlan plan, boolean isAdmin) {
|
||||
Account updateAccount = new Account();
|
||||
updateAccount.setId(account.getId());
|
||||
|
||||
// ① 根据订阅结束时间延长管理员账号有效期validEndTime
|
||||
// Long newValidEndTime = calculateNewValidEndTime(account, plan);
|
||||
// 通用更新逻辑
|
||||
updateAccount.setValidEndTime(plan.getCurrentPeriodEnd() * 1000);
|
||||
|
||||
// ② 根据积分上限更新管理员的积分credits和身份systemUser
|
||||
// 暂时保留管理员自己购买的积分
|
||||
if ((account.getSystemUser() == 5 || account.getSystemUser() == 7)
|
||||
&& Objects.nonNull(account.getCreditsUsageLimit())) {
|
||||
BigDecimal leftCredits = account.getCredits().add(account.getCreditsUsage()).subtract(account.getCreditsUsageLimit());
|
||||
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()));
|
||||
}
|
||||
|
||||
// 根据组织ID判断用户类型
|
||||
Integer newSystemUser = determineSystemUserType(plan);
|
||||
updateAccount.setSystemUser(newSystemUser);
|
||||
|
||||
// 更新子账号数量限制
|
||||
updateAccount.setCreditsUsage(plan.getCreditUsage());
|
||||
updateAccount.setCreditsUsageLimit(plan.getCreditLimit());
|
||||
updateAccount.setSubAccountNum(plan.getAccountNum());
|
||||
|
||||
// 关联订阅计划ID
|
||||
updateAccount.setSubscriptionPlanId(plan.getId());
|
||||
|
||||
// 更新组织信息
|
||||
updateAccount.setOrganizationId(plan.getOrganizationId());
|
||||
Organization organization = organizationMapper.selectById(plan.getOrganizationId());
|
||||
if (Objects.nonNull(organization)) {
|
||||
updateAccount.setOrganizationId(plan.getOrganizationId());
|
||||
updateAccount.setOrganizationName(organization.getName());
|
||||
} else {
|
||||
log.error("organization id为 {} 的组织,在表中找不到对应记录", plan.getOrganizationId());
|
||||
throw new BusinessException("unknown.organization");
|
||||
}
|
||||
|
||||
// 如果是组织管理员,设置isAdmin标志
|
||||
/* if (isOrganizationAdmin(newSystemUser)) {
|
||||
updateAccount.setIsAdmin(1);
|
||||
}*/
|
||||
// 根据用户类型设置不同的业务逻辑
|
||||
if (isAdmin) {
|
||||
updateAdminSpecificFields(updateAccount, account, plan);
|
||||
} else {
|
||||
updateSubAccountSpecificFields(updateAccount, account, plan);
|
||||
}
|
||||
|
||||
// 执行更新
|
||||
int rows = accountMapper.updateById(updateAccount);
|
||||
if (rows > 0) {
|
||||
log.info("管理员账号更新成功,ID: {}, 有效期至: {}, 用户类型: {}, 积分: {}",
|
||||
log.info("{}更新成功,ID: {}, 有效期至: {}, 用户类型: {}, 积分: {}",
|
||||
isAdmin ? "管理员账号" : "子账号",
|
||||
account.getId(),
|
||||
formatTimestamp(plan.getCurrentPeriodEnd()),
|
||||
newSystemUser,
|
||||
plan.getCreditLimit());
|
||||
|
||||
updateAccount.getSystemUser(),
|
||||
updateAccount.getCredits());
|
||||
} else {
|
||||
log.error("管理员账号更新失败,ID: {}", account.getId());
|
||||
log.error("{}更新失败,ID: {}", isAdmin ? "管理员账号" : "子账号", account.getId());
|
||||
}
|
||||
|
||||
// 仅子账号需要更新订阅计划的使用量
|
||||
if (!isAdmin) {
|
||||
updateSubscriptionPlanUsage(plan, updateAccount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新管理员特有的字段
|
||||
*/
|
||||
private void updateAdminSpecificFields(Account updateAccount, Account originalAccount, SubscriptionPlan plan) {
|
||||
// 保留管理员自己购买的积分
|
||||
if ((originalAccount.getSystemUser() == 5 || originalAccount.getSystemUser() == 7)
|
||||
&& Objects.nonNull(originalAccount.getCreditsUsageLimit())) {
|
||||
BigDecimal leftCredits = originalAccount.getCredits()
|
||||
.add(originalAccount.getCreditsUsage())
|
||||
.subtract(originalAccount.getCreditsUsageLimit());
|
||||
|
||||
updateAccount.setCredits(leftCredits.compareTo(BigDecimal.ZERO) > 0
|
||||
? plan.getCreditLimit().subtract(plan.getCreditUsage()).add(leftCredits)
|
||||
: plan.getCreditLimit().subtract(plan.getCreditUsage()));
|
||||
} else {
|
||||
updateAccount.setCredits(plan.getCreditLimit().subtract(plan.getCreditUsage()).add(originalAccount.getCredits()));
|
||||
}
|
||||
|
||||
// 设置用户类型和其他字段
|
||||
updateAccount.setSystemUser(determineSystemUserType(plan, true));
|
||||
updateAccount.setCreditsUsage(plan.getCreditUsage());
|
||||
updateAccount.setCreditsUsageLimit(plan.getCreditLimit());
|
||||
updateAccount.setSubAccountNum(plan.getAccountNum());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新子账号特有的字段
|
||||
*/
|
||||
private void updateSubAccountSpecificFields(Account updateAccount, Account originalAccount, SubscriptionPlan plan) {
|
||||
// 计算可分配的积分
|
||||
BigDecimal remainingCredits = plan.getCreditLimit().subtract(plan.getCreditUsage());
|
||||
BigDecimal allocatedCredits = calculateAllocatedCredits(remainingCredits);
|
||||
|
||||
updateAccount.setParentId(plan.getAdminAccId());
|
||||
updateAccount.setCreditsUsageLimit(allocatedCredits);
|
||||
updateAccount.setCredits(allocatedCredits.add(originalAccount.getCredits()));
|
||||
updateAccount.setCreditsUsage(BigDecimal.ZERO);
|
||||
updateAccount.setSystemUser(determineSystemUserType(plan, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算分配给子账号的积分
|
||||
*/
|
||||
private BigDecimal calculateAllocatedCredits(BigDecimal remainingCredits) {
|
||||
if (remainingCredits.compareTo(new BigDecimal(1000)) > 0) {
|
||||
return new BigDecimal(1000);
|
||||
} else if (remainingCredits.compareTo(new BigDecimal(100)) > 0) {
|
||||
return new BigDecimal(100);
|
||||
} else if (remainingCredits.compareTo(BigDecimal.ZERO) > 0) {
|
||||
return remainingCredits;
|
||||
} else {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订阅计划使用量(仅子账号)
|
||||
*/
|
||||
private void updateSubscriptionPlanUsage(SubscriptionPlan plan, Account updatedAccount) {
|
||||
plan.setCreditUsage(plan.getCreditUsage().add(updatedAccount.getCreditsUsageLimit()));
|
||||
plan.setUpdateTime(LocalDateTime.now());
|
||||
baseMapper.updateById(plan);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -463,7 +612,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
/**
|
||||
* 根据计划确定用户类型
|
||||
*/
|
||||
private Integer determineSystemUserType(SubscriptionPlan plan) {
|
||||
private Integer determineSystemUserType(SubscriptionPlan plan, boolean isAdmin) {
|
||||
// 根据组织ID, 去organization表中查询判断是学校还是企业
|
||||
Long orgId = plan.getOrganizationId();
|
||||
|
||||
@@ -473,16 +622,18 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
log.error("未知组织id: {}", orgId);
|
||||
throw new BusinessException("unknown.organization");
|
||||
}
|
||||
if (organization.getType().equals("Enterprise")) {
|
||||
return 5; // 学校管理员
|
||||
if (organization.getType().equals("Enterprise") && isAdmin) {
|
||||
return 5; // 企业管理员
|
||||
} else if (organization.getType().equals("Enterprise")) {
|
||||
return 6; // 企业子账号
|
||||
} else if (organization.getType().equals("Education") && isAdmin) {
|
||||
return 7; // 学校管理员
|
||||
} else if (organization.getType().equals("Education")) {
|
||||
return 7; // 企业管理员
|
||||
return 8; // 学校子账号
|
||||
} else {
|
||||
log.error("组织id未知组织类型");
|
||||
throw new BusinessException("unknown.type");
|
||||
}
|
||||
|
||||
// 默认为教育管理员
|
||||
return 7;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -636,7 +787,7 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
adminAccount.getId(), otherActiveSubscriptions.size(), earliestActivePlan.getId());
|
||||
|
||||
// 3. 切换到开始最早的订阅
|
||||
updateAdminAccount(adminAccount, earliestActivePlan);
|
||||
updateAccount(adminAccount, earliestActivePlan, true);
|
||||
|
||||
// 4. 修改订阅状态
|
||||
earliestActivePlan.setStatus(SubscriptionPlan.SubscriptionStatus.ACTIVE.name());
|
||||
@@ -703,40 +854,136 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员切换当前管理的订阅
|
||||
* 切换订阅计划(管理员和子账号)
|
||||
* @param subscriptionPlanId 订阅计划ID
|
||||
* @param targetAccId 目标账号ID(管理员或子账号ID)
|
||||
* @param isAdmin 是否是管理员切换
|
||||
*/
|
||||
public void switchSubscriptionPlan(Long subscriptionPlanId, Long targetAccId, boolean isAdmin) {
|
||||
// 1. 获取当前用户和基础数据校验
|
||||
Long currentUserId = UserContext.getUserHolder().getId();
|
||||
|
||||
// 获取订阅计划
|
||||
SubscriptionPlan subscriptionPlan = baseMapper.selectById(subscriptionPlanId);
|
||||
validateSubscriptionPlan(subscriptionPlan);
|
||||
|
||||
// 权限校验
|
||||
validatePermission(currentUserId, subscriptionPlan);
|
||||
|
||||
// 确定目标账号ID
|
||||
Long finalTargetAccId = determineTargetAccountId(currentUserId, targetAccId, isAdmin);
|
||||
|
||||
// 获取目标账号
|
||||
Account targetAccount = accountMapper.selectById(finalTargetAccId);
|
||||
if (Objects.isNull(targetAccount)) {
|
||||
throw new BusinessException(isAdmin ? "unknown.administrator.user" : "unknown.sub.account");
|
||||
}
|
||||
|
||||
// 管理员权限校验
|
||||
if (isAdmin) {
|
||||
validateAdminPermission(finalTargetAccId, subscriptionPlan);
|
||||
} else {
|
||||
validateSubAccountPermission(currentUserId, subscriptionPlan, targetAccount);
|
||||
}
|
||||
|
||||
// 检查是否已经是当前管理的订阅
|
||||
if (targetAccount.getSubscriptionPlanId() != null &&
|
||||
targetAccount.getSubscriptionPlanId().equals(subscriptionPlanId)) {
|
||||
log.info("用户:{} 当前正在订阅 {} 中", finalTargetAccId, subscriptionPlanId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 执行切换操作
|
||||
if (isAdmin) {
|
||||
// 管理员直接更新
|
||||
updateAccount(targetAccount, subscriptionPlan, true);
|
||||
} else {
|
||||
// 子账号需要先从原订阅移除
|
||||
accountService.removeSubAccount(new AddSubAccountDTO(Collections.singletonList(finalTargetAccId)), currentUserId);
|
||||
updateAccount(accountMapper.selectById(finalTargetAccId), subscriptionPlan, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员切换当前管理的订阅(保持原有接口)
|
||||
*/
|
||||
public void switchSubscriptionPlan(Long subscriptionPlanId, Long adminAccId) {
|
||||
// 1. 权限校验
|
||||
Long accountId = UserContext.getUserHolder().getId();
|
||||
SubscriptionPlan subscriptionPlan = baseMapper.selectById(subscriptionPlanId);
|
||||
switchSubscriptionPlan(subscriptionPlanId, adminAccId, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 子账号切换订阅计划(保持原有接口)
|
||||
*/
|
||||
public void switchSubAccSubscriptionPlan(Long subscriptionPlanId, Long subAccId) {
|
||||
switchSubscriptionPlan(subscriptionPlanId, subAccId, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验订阅计划
|
||||
*/
|
||||
private void validateSubscriptionPlan(SubscriptionPlan subscriptionPlan) {
|
||||
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)) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限校验
|
||||
*/
|
||||
private void validatePermission(Long userId, SubscriptionPlan subscriptionPlan) {
|
||||
// 87L是特殊权限用户
|
||||
if (!userId.equals(subscriptionPlan.getAdminAccId()) && !userId.equals(87L)) {
|
||||
throw new BusinessException("have.no.permission");
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 更新管理员积分
|
||||
if (!accountId.equals(87L)) {
|
||||
adminAccId = accountId;
|
||||
}
|
||||
Account account = accountMapper.selectById(adminAccId);
|
||||
if (Objects.isNull(account)) {
|
||||
throw new BusinessException("unknown.administrator.user");
|
||||
/**
|
||||
* 确定目标账号ID
|
||||
*/
|
||||
private Long determineTargetAccountId(Long currentUserId, Long targetAccId, boolean isAdmin) {
|
||||
// 如果是管理员切换且当前用户不是特殊权限用户,则使用当前用户ID
|
||||
if (isAdmin && !currentUserId.equals(87L)) {
|
||||
return currentUserId;
|
||||
}
|
||||
return targetAccId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员权限校验
|
||||
*/
|
||||
private void validateAdminPermission(Long adminAccId, SubscriptionPlan subscriptionPlan) {
|
||||
if (!adminAccId.equals(subscriptionPlan.getAdminAccId())) {
|
||||
log.info("用户:{} 没有权限管理订阅:{}", adminAccId, subscriptionPlanId);
|
||||
log.info("用户:{} 没有权限管理订阅:{}", adminAccId, subscriptionPlan.getId());
|
||||
throw new BusinessException("no.permission.manage.subscription", ResultEnum.PROMPT.getCode());
|
||||
}
|
||||
if (account.getSubscriptionPlanId().equals(subscriptionPlanId)) {
|
||||
log.info("用户:{} 当前正在管理订阅 {}", adminAccId, subscriptionPlanId);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* 子账号权限校验
|
||||
*/
|
||||
private void validateSubAccountPermission(Long adminAccId, SubscriptionPlan subscriptionPlan, Account subAccount) {
|
||||
// 验证管理员是否有权限
|
||||
validateAdminPermission(adminAccId, subscriptionPlan);
|
||||
|
||||
Account adminAcc = accountMapper.selectById(adminAccId);
|
||||
if (!subAccount.getSubscriptionPlanId().equals(adminAcc.getSubscriptionPlanId())) {
|
||||
throw new BusinessException("switch.failed.sub-account.not.under.your.active.subscription");
|
||||
}
|
||||
|
||||
updateAdminAccount(account, subscriptionPlan);
|
||||
// 校验子账号总数是否达上限
|
||||
QueryWrapper<Account> qw = new QueryWrapper<>();
|
||||
qw.lambda().eq(Account::getOrganizationId, subscriptionPlan.getOrganizationId())
|
||||
.eq(Account::getSubscriptionPlanId, subscriptionPlan.getId());
|
||||
List<Account> accounts = accountMapper.selectList(qw);
|
||||
|
||||
if (accounts.size() >= subscriptionPlan.getAccountNum()) {
|
||||
|
||||
throw new BusinessException("Error: Sub-account quota reached (Max: " +
|
||||
adminAcc.getSubAccountNum() + "). Upgrade to create more.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user