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;
|
private MinioUtil minioUtil;
|
||||||
@Resource
|
@Resource
|
||||||
private UserLikeService userLikeService;
|
private UserLikeService userLikeService;
|
||||||
public void clearMinio() {
|
/* public void clearMinio() {
|
||||||
List<CollectionElement> collectionElements = collectionElementMapper.selectDeleteList();
|
List<CollectionElement> collectionElements = collectionElementMapper.selectDeleteList();
|
||||||
for (CollectionElement collectionElement : collectionElements) {
|
for (CollectionElement collectionElement : collectionElements) {
|
||||||
String url = collectionElement.getUrl();
|
String url = collectionElement.getUrl();
|
||||||
@@ -472,7 +472,7 @@ public class MyTaskScheduler {
|
|||||||
// }
|
// }
|
||||||
// String preSignedUrl = minioUtil.getPreSignedUrl("aida-clothing/image/image_1698374859.3031476.png", 10000);
|
// String preSignedUrl = minioUtil.getPreSignedUrl("aida-clothing/image/image_1698374859.3031476.png", 10000);
|
||||||
// System.out.println(preSignedUrl);
|
// System.out.println(preSignedUrl);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private AttributeRetrievalMapper attributeRetrievalMapper;
|
private AttributeRetrievalMapper attributeRetrievalMapper;
|
||||||
|
|||||||
@@ -883,8 +883,8 @@ public class SendEmailUtil {
|
|||||||
|
|
||||||
if (!type.equals("cancel") && !type.equals("fail_new")) {
|
if (!type.equals("cancel") && !type.equals("fail_new")) {
|
||||||
// 返回的resp是一个SendEmailResponse的实例,与请求对象对应
|
// 返回的resp是一个SendEmailResponse的实例,与请求对象对应
|
||||||
// SendEmailResponse respUser = client.SendEmail(user);
|
SendEmailResponse respUser = client.SendEmail(user);
|
||||||
log.info("邮件主题:{},发送结果toUser###{}, email:{}", user.getSubject(), /*SendEmailResponse.toJsonString(respUser)*/null, receiverAddress);
|
log.info("邮件主题:{},发送结果toUser###{}, email:{}", user.getSubject(), SendEmailResponse.toJsonString(respUser), receiverAddress);
|
||||||
}
|
}
|
||||||
if (!type.startsWith("reminder")) {
|
if (!type.startsWith("reminder")) {
|
||||||
SendEmailResponse respMerchant = client.SendEmail(merchant);
|
SendEmailResponse respMerchant = client.SendEmail(merchant);
|
||||||
|
|||||||
@@ -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.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;
|
||||||
import com.ai.da.model.dto.UpdateSubscriptionPlanDTO;
|
import com.ai.da.model.dto.UpdateSubscriptionPlanDTO;
|
||||||
@@ -14,6 +15,8 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Tag(name = "订阅计划模块")
|
@Tag(name = "订阅计划模块")
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -38,6 +41,12 @@ public class SubscriptionPlanController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "搜索订阅计划")
|
@Operation(summary = "搜索订阅计划")
|
||||||
|
@PostMapping("/searchByOrganizationIdAndStatus")
|
||||||
|
public Response<List<SubscriptionPlan>> searchByOrganizationIdAndStatus(@Valid @RequestBody SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
||||||
|
return Response.success(subscriptionPlanService.searchByOrganizationIdAndStatus(subscriptionPlanPageQuery));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "分页搜索订阅计划")
|
||||||
@PostMapping("/searchByPage")
|
@PostMapping("/searchByPage")
|
||||||
public Response<IPage<SubscriptionPlanVO>> searchByPage(@Valid @RequestBody SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
public Response<IPage<SubscriptionPlanVO>> searchByPage(@Valid @RequestBody SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
||||||
IPage<SubscriptionPlanVO> subscriptionPlanVOIPage = subscriptionPlanService.searchByPage(subscriptionPlanPageQuery);
|
IPage<SubscriptionPlanVO> subscriptionPlanVOIPage = subscriptionPlanService.searchByPage(subscriptionPlanPageQuery);
|
||||||
@@ -53,8 +62,15 @@ public class SubscriptionPlanController {
|
|||||||
|
|
||||||
@Operation(summary = "管理员切换订阅计划")
|
@Operation(summary = "管理员切换订阅计划")
|
||||||
@GetMapping("/switchSubscriptionPlan")
|
@GetMapping("/switchSubscriptionPlan")
|
||||||
public Response<String> switchSubscriptionPlan(@RequestParam Long subscriptionPlanId, @RequestParam Long adminAccId) {
|
public Response<String> switchSubscriptionPlan(@RequestParam Long targetSubscriptionPlanId, @RequestParam(required = false) Long adminAccId) {
|
||||||
subscriptionPlanService.switchSubscriptionPlan(subscriptionPlanId, 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();
|
return Response.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,24 @@
|
|||||||
package com.ai.da.mapper.primary;
|
package com.ai.da.mapper.primary;
|
||||||
|
|
||||||
import com.ai.da.mapper.primary.entity.SubscriptionPlan;
|
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.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> {
|
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> email;
|
||||||
|
|
||||||
private List<String> userName;
|
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 io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Positive;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -13,18 +15,22 @@ public class SubscriptionPlanDTO {
|
|||||||
|
|
||||||
@Schema(description = "组织id")
|
@Schema(description = "组织id")
|
||||||
@NotNull(message = "Please select an organizationId.")
|
@NotNull(message = "Please select an organizationId.")
|
||||||
|
@Positive(message = "组织ID必须大于0")
|
||||||
private Long organizationId;
|
private Long organizationId;
|
||||||
|
|
||||||
@Schema(description = "当前订阅开始时间")
|
@Schema(description = "当前订阅开始时间")
|
||||||
@NotNull(message = "Please set a subscription start time.")
|
@NotNull(message = "Please set a subscription start time.")
|
||||||
|
@Min(value = 0, message = "开始时间不能小于0")
|
||||||
private Long currentPeriodStart;
|
private Long currentPeriodStart;
|
||||||
|
|
||||||
@Schema(description = "当前订阅结束时间")
|
@Schema(description = "当前订阅结束时间")
|
||||||
@NotNull(message = "Please set a subscription end time.")
|
@NotNull(message = "Please set a subscription end time.")
|
||||||
|
@Min(value = 0, message = "结束时间不能小于0")
|
||||||
private Long currentPeriodEnd;
|
private Long currentPeriodEnd;
|
||||||
|
|
||||||
@Schema(description = "当前订阅总的子账号数量")
|
@Schema(description = "当前订阅总的子账号数量")
|
||||||
@NotNull(message = "Please set the sub-account number.")
|
@NotNull(message = "Please set the sub-account number.")
|
||||||
|
@Min(value = 0, message = "子账号数量不能小于0")
|
||||||
private Integer accountNum;
|
private Integer accountNum;
|
||||||
|
|
||||||
@Schema(description = "当前订阅可用积分上限")
|
@Schema(description = "当前订阅可用积分上限")
|
||||||
@@ -33,6 +39,10 @@ public class SubscriptionPlanDTO {
|
|||||||
|
|
||||||
@Schema(description = "管理员账户id")
|
@Schema(description = "管理员账户id")
|
||||||
@NotNull(message = "Please assign an administrator account.")
|
@NotNull(message = "Please assign an administrator account.")
|
||||||
|
@Positive(message = "管理员账号ID必须大于0")
|
||||||
private Long adminAccId;
|
private Long adminAccId;
|
||||||
|
|
||||||
|
@Schema(description = "订阅计划命名")
|
||||||
|
private String name;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,4 +29,7 @@ public class UpdateSubscriptionPlanDTO {
|
|||||||
@Schema(description = "管理员账户id")
|
@Schema(description = "管理员账户id")
|
||||||
private Long adminAccId;
|
private Long adminAccId;
|
||||||
|
|
||||||
|
@ApiModelProperty("订阅重命名")
|
||||||
|
private String name;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,16 @@ public class SubscriptionPlanVO {
|
|||||||
@Schema(description = "管理员账户id")
|
@Schema(description = "管理员账户id")
|
||||||
private Long adminAccId;
|
private Long adminAccId;
|
||||||
|
|
||||||
|
@Schema(description = "管理员账户邮箱")
|
||||||
|
private String adminAccEmail;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
private LocalDateTime createTime;
|
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.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface SubscriptionPlanService extends IService<SubscriptionPlan> {
|
public interface SubscriptionPlanService extends IService<SubscriptionPlan> {
|
||||||
|
|
||||||
void createPlan(SubscriptionPlanDTO subscriptionPlanDTO);
|
void createPlan(SubscriptionPlanDTO subscriptionPlanDTO);
|
||||||
|
|
||||||
void updatePlan(UpdateSubscriptionPlanDTO updateDTO);
|
void updatePlan(UpdateSubscriptionPlanDTO updateDTO);
|
||||||
|
|
||||||
|
List<SubscriptionPlan> searchByOrganizationIdAndStatus(SubscriptionPlanPageQuery subscriptionPlanPageQuery);
|
||||||
|
|
||||||
IPage<SubscriptionPlanVO> searchByPage(SubscriptionPlanPageQuery subscriptionPlanPageQuery);
|
IPage<SubscriptionPlanVO> searchByPage(SubscriptionPlanPageQuery subscriptionPlanPageQuery);
|
||||||
|
|
||||||
void deletePlan(Long id);
|
void deletePlan(Long id);
|
||||||
|
|
||||||
void switchSubscriptionPlan(Long subscriptionPlanId, Long adminAccId);
|
void switchSubscriptionPlan(Long subscriptionPlanId, Long adminAccId);
|
||||||
|
|
||||||
|
void switchSubAccSubscriptionPlan(Long subscriptionPlanId, Long subAccId);
|
||||||
|
|
||||||
void activeSubscriptionPlan();
|
void activeSubscriptionPlan();
|
||||||
|
|
||||||
void expireSubscription();
|
void expireSubscription();
|
||||||
|
|||||||
@@ -2443,7 +2443,8 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Boolean createSubAccount(AddSubAccountDTO addSubAccountDTO, Account adminAcc, int subUserRole) {
|
public Boolean createSubAccount(AddSubAccountDTO addSubAccountDTO, Account adminAcc, int subUserRole) {
|
||||||
QueryWrapper<Account> qw = new QueryWrapper<>();
|
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);
|
List<Account> accounts = accountMapper.selectList(qw);
|
||||||
|
|
||||||
// 校验子账号总数是否达上限
|
// 校验子账号总数是否达上限
|
||||||
@@ -2493,6 +2494,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
|
|
||||||
subAccount.setSystemUser(subUserRole);
|
subAccount.setSystemUser(subUserRole);
|
||||||
subAccount.setOrganizationId(adminAcc.getOrganizationId());
|
subAccount.setOrganizationId(adminAcc.getOrganizationId());
|
||||||
|
subAccount.setOrganizationName(adminAcc.getOrganizationName());
|
||||||
subAccount.setParentId(adminAcc.getId());
|
subAccount.setParentId(adminAcc.getId());
|
||||||
subAccount.setSubscriptionPlanId(adminAcc.getSubscriptionPlanId());
|
subAccount.setSubscriptionPlanId(adminAcc.getSubscriptionPlanId());
|
||||||
if (Objects.nonNull(addSubAccountDTO.getCreditsUsageLimit())) {
|
if (Objects.nonNull(addSubAccountDTO.getCreditsUsageLimit())) {
|
||||||
@@ -2557,7 +2559,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
subAccount.setIsTrial(0);
|
subAccount.setIsTrial(0);
|
||||||
subAccount.setIsBeginner(1);
|
subAccount.setIsBeginner(1);
|
||||||
subAccount.setParentId(adminAcc.getId());
|
subAccount.setParentId(adminAcc.getId());
|
||||||
// subAccount.setOrganizationName(adminAcc.getOrganizationName());
|
subAccount.setOrganizationName(adminAcc.getOrganizationName());
|
||||||
subAccount.setOrganizationId(adminAcc.getOrganizationId());
|
subAccount.setOrganizationId(adminAcc.getOrganizationId());
|
||||||
subAccount.setSubscriptionPlanId(adminAcc.getSubscriptionPlanId());
|
subAccount.setSubscriptionPlanId(adminAcc.getSubscriptionPlanId());
|
||||||
accountMapper.insert(subAccount);
|
accountMapper.insert(subAccount);
|
||||||
@@ -2732,7 +2734,9 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
for (Long id : addSubAccountDTO.getDeleteIdList()) {
|
for (Long id : addSubAccountDTO.getDeleteIdList()) {
|
||||||
Account account = baseMapper.selectById(id);
|
Account account = baseMapper.selectById(id);
|
||||||
if (Objects.nonNull(account.getParentId()) && account.getParentId().equals(adminAccId)) {
|
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);
|
BigDecimal finalCredits = calculateFinalCredits(account, unusedCredits);
|
||||||
|
|
||||||
int userRole = determineUserRole(account.getId());
|
int userRole = determineUserRole(account.getId());
|
||||||
@@ -2805,7 +2809,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
|
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
|
||||||
Account account = accountMapper.selectById(authPrincipalVo);
|
Account account = accountMapper.selectById(authPrincipalVo);
|
||||||
QueryWrapper<Account> qw = new QueryWrapper<>();
|
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());
|
qw.lambda().eq(Account::getOrganizationId, account.getOrganizationId());
|
||||||
if (StringUtils.isNotBlank(subAccountPageDTO.getStartTime())) {
|
if (StringUtils.isNotBlank(subAccountPageDTO.getStartTime())) {
|
||||||
qw.lambda().ge(Account::getCreateDate, 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) {
|
} else if (subAccountPageDTO.getUserName() != null && subAccountPageDTO.getUserName().size() > 1) {
|
||||||
qw.lambda().in(Account::getUserName, subAccountPageDTO.getUserName());
|
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);
|
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.Account;
|
||||||
import com.ai.da.mapper.primary.entity.Organization;
|
import com.ai.da.mapper.primary.entity.Organization;
|
||||||
import com.ai.da.mapper.primary.entity.SubscriptionPlan;
|
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.SubscriptionPlanDTO;
|
||||||
import com.ai.da.model.dto.SubscriptionPlanPageQuery;
|
import com.ai.da.model.dto.SubscriptionPlanPageQuery;
|
||||||
import com.ai.da.model.dto.UpdateSubscriptionPlanDTO;
|
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.AccountService;
|
||||||
import com.ai.da.service.SubscriptionPlanService;
|
import com.ai.da.service.SubscriptionPlanService;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
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.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.google.common.base.Function;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -36,6 +37,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@@ -46,6 +48,8 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
|
|
||||||
private final AccountMapper accountMapper;
|
private final AccountMapper accountMapper;
|
||||||
|
|
||||||
|
private final AccountService accountService;
|
||||||
|
|
||||||
private final OrganizationMapper organizationMapper;
|
private final OrganizationMapper organizationMapper;
|
||||||
|
|
||||||
private final RedisUtil redisUtil;
|
private final RedisUtil redisUtil;
|
||||||
@@ -53,9 +57,14 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
// 创建
|
// 创建
|
||||||
@Override
|
@Override
|
||||||
public void createPlan(SubscriptionPlanDTO subscriptionPlanDTO) {
|
public void createPlan(SubscriptionPlanDTO subscriptionPlanDTO) {
|
||||||
|
// 参数校验
|
||||||
|
validateCreatePlanParams(subscriptionPlanDTO);
|
||||||
|
|
||||||
SubscriptionPlan subscriptionPlan = CopyUtil.copyObject(subscriptionPlanDTO, SubscriptionPlan.class);
|
SubscriptionPlan subscriptionPlan = CopyUtil.copyObject(subscriptionPlanDTO, SubscriptionPlan.class);
|
||||||
subscriptionPlan.setStatus(SubscriptionPlan.SubscriptionStatus.PENDING.name());
|
subscriptionPlan.setStatus(SubscriptionPlan.SubscriptionStatus.PENDING.name());
|
||||||
subscriptionPlan.setName("DEFAULT_NAME");
|
if (Objects.isNull(subscriptionPlan.getName())) {
|
||||||
|
subscriptionPlan.setName("DEFAULT_NAME");
|
||||||
|
}
|
||||||
subscriptionPlan.setCreditUsage(BigDecimal.ZERO);
|
subscriptionPlan.setCreditUsage(BigDecimal.ZERO);
|
||||||
subscriptionPlan.setCreateTime(LocalDateTime.now());
|
subscriptionPlan.setCreateTime(LocalDateTime.now());
|
||||||
if (Objects.isNull(subscriptionPlanDTO.getCreditLimit())) {
|
if (Objects.isNull(subscriptionPlanDTO.getCreditLimit())) {
|
||||||
@@ -65,6 +74,25 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
baseMapper.insert(subscriptionPlan);
|
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
|
@Override
|
||||||
public void updatePlan(UpdateSubscriptionPlanDTO updateDTO) {
|
public void updatePlan(UpdateSubscriptionPlanDTO updateDTO) {
|
||||||
@@ -97,6 +125,10 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
subscriptionPlan.setAdminAccId(updateDTO.getAdminAccId());
|
subscriptionPlan.setAdminAccId(updateDTO.getAdminAccId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(updateDTO.getName()) && !updateDTO.getName().equals(subscriptionPlan.getName())) {
|
||||||
|
subscriptionPlan.setName(updateDTO.getName());
|
||||||
|
}
|
||||||
|
|
||||||
subscriptionPlan.setUpdateTime(LocalDateTime.now());
|
subscriptionPlan.setUpdateTime(LocalDateTime.now());
|
||||||
updateById(subscriptionPlan);
|
updateById(subscriptionPlan);
|
||||||
|
|
||||||
@@ -107,8 +139,83 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找 根据入参提供的参数进行分页查询
|
|
||||||
@Override
|
@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) {
|
public IPage<SubscriptionPlanVO> searchByPage(SubscriptionPlanPageQuery subscriptionPlanPageQuery) {
|
||||||
// 1. 参数校验
|
// 1. 参数校验
|
||||||
validatePageQuery(subscriptionPlanPageQuery);
|
validatePageQuery(subscriptionPlanPageQuery);
|
||||||
@@ -121,8 +228,9 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
IPage<SubscriptionPlan> resultPage = baseMapper.selectPage(page, queryWrapper);
|
IPage<SubscriptionPlan> resultPage = baseMapper.selectPage(page, queryWrapper);
|
||||||
|
|
||||||
// 4. 转换为VO并返回
|
// 4. 转换为VO并返回
|
||||||
|
// todo 用户邮箱
|
||||||
return resultPage.convert((Function<SubscriptionPlan, SubscriptionPlanVO>) plan -> CopyUtil.copyObject(plan, SubscriptionPlanVO.class));
|
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;
|
return currentPeriodEnd < currentTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo 切换管理员的账号
|
|
||||||
|
|
||||||
// 定时器更新管理员状态
|
|
||||||
/* public void updateEduAdminAccount() {
|
|
||||||
// 1. 扫描所有的订阅计划的开始时间currentPeriodStart
|
|
||||||
|
|
||||||
// 2. 当检测到有今天内开始有效的订阅,更新绑定的管理员的账号
|
|
||||||
|
|
||||||
// 3. 更新管理的信息包括,①根据订阅结束时间延长管理员账号有效期 ②根据积分上限更新管理员的积分,如果当前管理员正处于一个订阅中,则不做更新,但是允许切换
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public void activeSubscriptionPlan() {
|
public void activeSubscriptionPlan() {
|
||||||
log.info("开始执行订阅计划生效检查...");
|
log.info("开始执行订阅计划生效检查...");
|
||||||
|
|
||||||
@@ -376,68 +473,120 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4. 更新管理员账号信息
|
// 4. 更新管理员账号信息
|
||||||
updateAdminAccount(adminAccount, plan);
|
updateAccount(adminAccount, plan, true);
|
||||||
|
|
||||||
log.info("订阅计划处理完成,ID: {}", plan.getId());
|
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();
|
Account updateAccount = new Account();
|
||||||
updateAccount.setId(account.getId());
|
updateAccount.setId(account.getId());
|
||||||
|
|
||||||
// ① 根据订阅结束时间延长管理员账号有效期validEndTime
|
// 通用更新逻辑
|
||||||
// Long newValidEndTime = calculateNewValidEndTime(account, plan);
|
|
||||||
updateAccount.setValidEndTime(plan.getCurrentPeriodEnd() * 1000);
|
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.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)) {
|
if (isAdmin) {
|
||||||
updateAccount.setIsAdmin(1);
|
updateAdminSpecificFields(updateAccount, account, plan);
|
||||||
}*/
|
} else {
|
||||||
|
updateSubAccountSpecificFields(updateAccount, account, plan);
|
||||||
|
}
|
||||||
|
|
||||||
// 执行更新
|
// 执行更新
|
||||||
int rows = accountMapper.updateById(updateAccount);
|
int rows = accountMapper.updateById(updateAccount);
|
||||||
if (rows > 0) {
|
if (rows > 0) {
|
||||||
log.info("管理员账号更新成功,ID: {}, 有效期至: {}, 用户类型: {}, 积分: {}",
|
log.info("{}更新成功,ID: {}, 有效期至: {}, 用户类型: {}, 积分: {}",
|
||||||
|
isAdmin ? "管理员账号" : "子账号",
|
||||||
account.getId(),
|
account.getId(),
|
||||||
formatTimestamp(plan.getCurrentPeriodEnd()),
|
formatTimestamp(plan.getCurrentPeriodEnd()),
|
||||||
newSystemUser,
|
updateAccount.getSystemUser(),
|
||||||
plan.getCreditLimit());
|
updateAccount.getCredits());
|
||||||
|
|
||||||
} else {
|
} 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表中查询判断是学校还是企业
|
// 根据组织ID, 去organization表中查询判断是学校还是企业
|
||||||
Long orgId = plan.getOrganizationId();
|
Long orgId = plan.getOrganizationId();
|
||||||
|
|
||||||
@@ -473,16 +622,18 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl<SubscriptionPlanMap
|
|||||||
log.error("未知组织id: {}", orgId);
|
log.error("未知组织id: {}", orgId);
|
||||||
throw new BusinessException("unknown.organization");
|
throw new BusinessException("unknown.organization");
|
||||||
}
|
}
|
||||||
if (organization.getType().equals("Enterprise")) {
|
if (organization.getType().equals("Enterprise") && isAdmin) {
|
||||||
return 5; // 学校管理员
|
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")) {
|
} else if (organization.getType().equals("Education")) {
|
||||||
return 7; // 企业管理员
|
return 8; // 学校子账号
|
||||||
} else {
|
} else {
|
||||||
log.error("组织id未知组织类型");
|
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());
|
adminAccount.getId(), otherActiveSubscriptions.size(), earliestActivePlan.getId());
|
||||||
|
|
||||||
// 3. 切换到开始最早的订阅
|
// 3. 切换到开始最早的订阅
|
||||||
updateAdminAccount(adminAccount, earliestActivePlan);
|
updateAccount(adminAccount, earliestActivePlan, true);
|
||||||
|
|
||||||
// 4. 修改订阅状态
|
// 4. 修改订阅状态
|
||||||
earliestActivePlan.setStatus(SubscriptionPlan.SubscriptionStatus.ACTIVE.name());
|
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) {
|
public void switchSubscriptionPlan(Long subscriptionPlanId, Long adminAccId) {
|
||||||
// 1. 权限校验
|
switchSubscriptionPlan(subscriptionPlanId, adminAccId, true);
|
||||||
Long accountId = UserContext.getUserHolder().getId();
|
}
|
||||||
SubscriptionPlan subscriptionPlan = baseMapper.selectById(subscriptionPlanId);
|
|
||||||
|
/**
|
||||||
|
* 子账号切换订阅计划(保持原有接口)
|
||||||
|
*/
|
||||||
|
public void switchSubAccSubscriptionPlan(Long subscriptionPlanId, Long subAccId) {
|
||||||
|
switchSubscriptionPlan(subscriptionPlanId, subAccId, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验订阅计划
|
||||||
|
*/
|
||||||
|
private void validateSubscriptionPlan(SubscriptionPlan subscriptionPlan) {
|
||||||
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())) {
|
if (subscriptionPlan.getStatus().equals(SubscriptionPlan.SubscriptionStatus.EXPIRED.name())) {
|
||||||
throw new BusinessException("subscription.has.expired");
|
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");
|
throw new BusinessException("have.no.permission");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 2. 更新管理员积分
|
/**
|
||||||
if (!accountId.equals(87L)) {
|
* 确定目标账号ID
|
||||||
adminAccId = accountId;
|
*/
|
||||||
}
|
private Long determineTargetAccountId(Long currentUserId, Long targetAccId, boolean isAdmin) {
|
||||||
Account account = accountMapper.selectById(adminAccId);
|
// 如果是管理员切换且当前用户不是特殊权限用户,则使用当前用户ID
|
||||||
if (Objects.isNull(account)) {
|
if (isAdmin && !currentUserId.equals(87L)) {
|
||||||
throw new BusinessException("unknown.administrator.user");
|
return currentUserId;
|
||||||
}
|
}
|
||||||
|
return targetAccId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员权限校验
|
||||||
|
*/
|
||||||
|
private void validateAdminPermission(Long adminAccId, SubscriptionPlan subscriptionPlan) {
|
||||||
if (!adminAccId.equals(subscriptionPlan.getAdminAccId())) {
|
if (!adminAccId.equals(subscriptionPlan.getAdminAccId())) {
|
||||||
log.info("用户:{} 没有权限管理订阅:{}", adminAccId, subscriptionPlanId);
|
log.info("用户:{} 没有权限管理订阅:{}", adminAccId, subscriptionPlan.getId());
|
||||||
throw new BusinessException("no.permission.manage.subscription", ResultEnum.PROMPT.getCode());
|
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.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ unknown.mode=unknown mode
|
|||||||
unknown.subscription.plan=unknown subscription plan
|
unknown.subscription.plan=unknown subscription plan
|
||||||
unknown.subscription.status=Unknown subscription status.
|
unknown.subscription.status=Unknown subscription status.
|
||||||
subscription.has.expired=Switch failed. The subscription has expired.
|
subscription.has.expired=Switch failed. The subscription has expired.
|
||||||
unknown.administrator.user=Switch failed. Unknown administrator user.
|
unknown.administrator.user=Operation failed. Unknown administrator user.
|
||||||
no.permission.manage.subscription=Switch failed. You do not have permission to manage this subscription.
|
no.permission.manage.subscription=Switch failed. You do not have permission to manage this subscription.
|
||||||
unknown.organization=Unknown organization.
|
unknown.organization=Unknown organization.
|
||||||
valid.subscription.period=The plan is still within its valid period. Please delete it after it expires.
|
valid.subscription.period=The plan is still within its valid period. Please delete it after it expires.
|
||||||
@@ -205,6 +205,9 @@ invalid.time.format=Invalid time format. Please use the yyyy-MM-dd HH:mm:ss form
|
|||||||
the.start.time.cannot.be.later.than.the.end.time=The start time cannot be later than the end time.
|
the.start.time.cannot.be.later.than.the.end.time=The start time cannot be later than the end time.
|
||||||
page.size.limit=The number of items per page must be between 1 and 100.
|
page.size.limit=The number of items per page must be between 1 and 100.
|
||||||
page.num.limit=The page number must be greater than 0.
|
page.num.limit=The page number must be greater than 0.
|
||||||
|
end.time.must.be.later.than.the.start.time=The subscription end time must be later than the start time.
|
||||||
|
please.specify.the.organizationId=Please specify the organizationId.
|
||||||
|
switch.failed.sub-account.not.under.your.active.subscription=Switch failed. Sub-account not under your active subscription.
|
||||||
|
|
||||||
# 可能会报异常
|
# 可能会报异常
|
||||||
# Informative:
|
# Informative:
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ unknown.mode=未知模式
|
|||||||
unknown.subscription.plan=未知订阅计划
|
unknown.subscription.plan=未知订阅计划
|
||||||
unknown.subscription.status=未知订阅状态
|
unknown.subscription.status=未知订阅状态
|
||||||
subscription.has.expired=切换失败,订阅已过期
|
subscription.has.expired=切换失败,订阅已过期
|
||||||
unknown.administrator.user=切换失败,未知管理员用户
|
unknown.administrator.user=操作失败,未知管理员用户
|
||||||
no.permission.manage.subscription=切换失败,您没有权限管理该订阅
|
no.permission.manage.subscription=切换失败,您没有权限管理该订阅
|
||||||
unknown.organization=未知组织
|
unknown.organization=未知组织
|
||||||
valid.subscription.period=计划仍在有效期内,请到期后再删除
|
valid.subscription.period=计划仍在有效期内,请到期后再删除
|
||||||
@@ -201,6 +201,9 @@ invalid.time.format=时间格式错误,请使用yyyy-MM-dd HH:mm:ss格式
|
|||||||
the.start.time.cannot.be.later.than.the.end.time=开始时间不能晚于结束时间
|
the.start.time.cannot.be.later.than.the.end.time=开始时间不能晚于结束时间
|
||||||
page.size.limit=每页数量必须在1-100之间
|
page.size.limit=每页数量必须在1-100之间
|
||||||
page.num.limit=页码必须大于0
|
page.num.limit=页码必须大于0
|
||||||
|
end.time.must.be.later.than.the.start.time=订阅结束时间必须晚于开始时间
|
||||||
|
please.specify.the.organizationId=请指定organizationId
|
||||||
|
switch.failed.sub-account.not.under.your.active.subscription=切换失败,该子账号不属于您当前管理的订阅计划
|
||||||
|
|
||||||
# 可能会报异常
|
# 可能会报异常
|
||||||
# Informative:
|
# Informative:
|
||||||
|
|||||||
Reference in New Issue
Block a user