diff --git a/src/main/java/com/ai/da/common/config/MyTaskScheduler.java b/src/main/java/com/ai/da/common/config/MyTaskScheduler.java index 433bdd11..be6bd63b 100644 --- a/src/main/java/com/ai/da/common/config/MyTaskScheduler.java +++ b/src/main/java/com/ai/da/common/config/MyTaskScheduler.java @@ -308,7 +308,7 @@ public class MyTaskScheduler { private MinioUtil minioUtil; @Resource private UserLikeService userLikeService; - public void clearMinio() { + /* public void clearMinio() { List 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; diff --git a/src/main/java/com/ai/da/common/utils/SendEmailUtil.java b/src/main/java/com/ai/da/common/utils/SendEmailUtil.java index 6712ac2c..f984fc83 100644 --- a/src/main/java/com/ai/da/common/utils/SendEmailUtil.java +++ b/src/main/java/com/ai/da/common/utils/SendEmailUtil.java @@ -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); diff --git a/src/main/java/com/ai/da/controller/SubscriptionPlanController.java b/src/main/java/com/ai/da/controller/SubscriptionPlanController.java index cf4051de..e071b830 100644 --- a/src/main/java/com/ai/da/controller/SubscriptionPlanController.java +++ b/src/main/java/com/ai/da/controller/SubscriptionPlanController.java @@ -1,6 +1,7 @@ package com.ai.da.controller; import com.ai.da.common.response.Response; +import com.ai.da.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> searchByOrganizationIdAndStatus(@Valid @RequestBody SubscriptionPlanPageQuery subscriptionPlanPageQuery) { + return Response.success(subscriptionPlanService.searchByOrganizationIdAndStatus(subscriptionPlanPageQuery)); + } + + @Operation(summary = "分页搜索订阅计划") @PostMapping("/searchByPage") public Response> searchByPage(@Valid @RequestBody SubscriptionPlanPageQuery subscriptionPlanPageQuery) { IPage subscriptionPlanVOIPage = subscriptionPlanService.searchByPage(subscriptionPlanPageQuery); @@ -53,8 +62,15 @@ public class SubscriptionPlanController { @Operation(summary = "管理员切换订阅计划") @GetMapping("/switchSubscriptionPlan") - public Response switchSubscriptionPlan(@RequestParam Long subscriptionPlanId, @RequestParam Long adminAccId) { - subscriptionPlanService.switchSubscriptionPlan(subscriptionPlanId, adminAccId); + public Response switchSubscriptionPlan(@RequestParam Long targetSubscriptionPlanId, @RequestParam(required = false) Long adminAccId) { + subscriptionPlanService.switchSubscriptionPlan(targetSubscriptionPlanId, adminAccId); + return Response.success(); + } + + @Operation(summary = "子账号切换订阅计划") + @GetMapping("/switchSubAccSubscriptionPlan") + public Response switchSubAccSubscriptionPlan(@RequestParam Long targetSubscriptionPlanId, @RequestParam Long subAccId) { + subscriptionPlanService.switchSubAccSubscriptionPlan(targetSubscriptionPlanId, subAccId); return Response.success(); } diff --git a/src/main/java/com/ai/da/mapper/primary/SubscriptionPlanMapper.java b/src/main/java/com/ai/da/mapper/primary/SubscriptionPlanMapper.java index 05c490e8..2e9df012 100644 --- a/src/main/java/com/ai/da/mapper/primary/SubscriptionPlanMapper.java +++ b/src/main/java/com/ai/da/mapper/primary/SubscriptionPlanMapper.java @@ -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 { + + /** + * 关联查询订阅计划信息(包含管理员邮箱)- 分页 + */ + @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 selectWithEmailPage(Page page, + @Param(Constants.WRAPPER) Wrapper wrapper); } diff --git a/src/main/java/com/ai/da/model/dto/SubAccountPageDTO.java b/src/main/java/com/ai/da/model/dto/SubAccountPageDTO.java index 8a0f5762..aac4c227 100644 --- a/src/main/java/com/ai/da/model/dto/SubAccountPageDTO.java +++ b/src/main/java/com/ai/da/model/dto/SubAccountPageDTO.java @@ -14,4 +14,6 @@ public class SubAccountPageDTO extends PageQueryBaseVo { private List email; private List userName; + + private Long subscriptionPlanId; } diff --git a/src/main/java/com/ai/da/model/dto/SubscriptionPlanDTO.java b/src/main/java/com/ai/da/model/dto/SubscriptionPlanDTO.java index 36fe5f0b..aab98e92 100644 --- a/src/main/java/com/ai/da/model/dto/SubscriptionPlanDTO.java +++ b/src/main/java/com/ai/da/model/dto/SubscriptionPlanDTO.java @@ -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; + } diff --git a/src/main/java/com/ai/da/model/dto/UpdateSubscriptionPlanDTO.java b/src/main/java/com/ai/da/model/dto/UpdateSubscriptionPlanDTO.java index bf5f53cd..b5611e51 100644 --- a/src/main/java/com/ai/da/model/dto/UpdateSubscriptionPlanDTO.java +++ b/src/main/java/com/ai/da/model/dto/UpdateSubscriptionPlanDTO.java @@ -29,4 +29,7 @@ public class UpdateSubscriptionPlanDTO { @Schema(description = "管理员账户id") private Long adminAccId; + @ApiModelProperty("订阅重命名") + private String name; + } diff --git a/src/main/java/com/ai/da/model/vo/SubscriptionPlanVO.java b/src/main/java/com/ai/da/model/vo/SubscriptionPlanVO.java index 03ed784c..99d39d3f 100644 --- a/src/main/java/com/ai/da/model/vo/SubscriptionPlanVO.java +++ b/src/main/java/com/ai/da/model/vo/SubscriptionPlanVO.java @@ -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; } diff --git a/src/main/java/com/ai/da/service/SubscriptionPlanService.java b/src/main/java/com/ai/da/service/SubscriptionPlanService.java index c41fe067..67affc27 100644 --- a/src/main/java/com/ai/da/service/SubscriptionPlanService.java +++ b/src/main/java/com/ai/da/service/SubscriptionPlanService.java @@ -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 { void createPlan(SubscriptionPlanDTO subscriptionPlanDTO); void updatePlan(UpdateSubscriptionPlanDTO updateDTO); + List searchByOrganizationIdAndStatus(SubscriptionPlanPageQuery subscriptionPlanPageQuery); + IPage searchByPage(SubscriptionPlanPageQuery subscriptionPlanPageQuery); void deletePlan(Long id); void switchSubscriptionPlan(Long subscriptionPlanId, Long adminAccId); + void switchSubAccSubscriptionPlan(Long subscriptionPlanId, Long subAccId); + void activeSubscriptionPlan(); void expireSubscription(); diff --git a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java index ee9515b1..85e931bf 100644 --- a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java @@ -2443,7 +2443,8 @@ public class AccountServiceImpl extends ServiceImpl impl @Transactional(rollbackFor = Exception.class) public Boolean createSubAccount(AddSubAccountDTO addSubAccountDTO, Account adminAcc, int subUserRole) { QueryWrapper qw = new QueryWrapper<>(); - qw.lambda().eq(Account::getOrganizationId, adminAcc.getOrganizationId()); + qw.lambda().eq(Account::getOrganizationId, adminAcc.getOrganizationId()) + .eq(Account::getSubscriptionPlanId, adminAcc.getSubscriptionPlanId()); List accounts = accountMapper.selectList(qw); // 校验子账号总数是否达上限 @@ -2493,6 +2494,7 @@ public class AccountServiceImpl extends ServiceImpl 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 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 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 impl AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder(); Account account = accountMapper.selectById(authPrincipalVo); QueryWrapper 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 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 page = accountMapper.selectPage(new Page<>(subAccountPageDTO.getPage(), subAccountPageDTO.getSize()), qw); diff --git a/src/main/java/com/ai/da/service/impl/SubscriptionPlanServiceImpl.java b/src/main/java/com/ai/da/service/impl/SubscriptionPlanServiceImpl.java index 020510cd..68748bd8 100644 --- a/src/main/java/com/ai/da/service/impl/SubscriptionPlanServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/SubscriptionPlanServiceImpl.java @@ -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 searchByOrganizationIdAndStatus(SubscriptionPlanPageQuery subscriptionPlanPageQuery) { + QueryWrapper 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 searchByPage(SubscriptionPlanPageQuery subscriptionPlanPageQuery) { + // 1. 参数校验 + validatePageQuery(subscriptionPlanPageQuery); + + // 2. 构建查询条件(不需要包含is_deleted条件,因为SQL中已包含) + LambdaQueryWrapper queryWrapper = buildQueryWrapperWithoutDeleted(subscriptionPlanPageQuery); + + // 3. 执行自定义的分页查询 + Page page = new Page<>( + subscriptionPlanPageQuery.getPage(), + subscriptionPlanPageQuery.getSize() + ); + + // 查询数据 + return baseMapper.selectWithEmailPage(page, queryWrapper); + } + + /** + * 构建查询条件(不包含is_deleted条件,因为SQL中已包含) + */ + private LambdaQueryWrapper buildQueryWrapperWithoutDeleted(SubscriptionPlanPageQuery query) { + LambdaQueryWrapper 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 searchByPage(SubscriptionPlanPageQuery subscriptionPlanPageQuery) { // 1. 参数校验 validatePageQuery(subscriptionPlanPageQuery); @@ -121,8 +228,9 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl resultPage = baseMapper.selectPage(page, queryWrapper); // 4. 转换为VO并返回 + // todo 用户邮箱 return resultPage.convert((Function) plan -> CopyUtil.copyObject(plan, SubscriptionPlanVO.class)); - } + }*/ /** * 参数校验 @@ -295,17 +403,6 @@ public class SubscriptionPlanServiceImpl extends ServiceImpl 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 qw = new QueryWrapper<>(); + qw.lambda().eq(Account::getOrganizationId, subscriptionPlan.getOrganizationId()) + .eq(Account::getSubscriptionPlanId, subscriptionPlan.getId()); + List accounts = accountMapper.selectList(qw); + + if (accounts.size() >= subscriptionPlan.getAccountNum()) { + + throw new BusinessException("Error: Sub-account quota reached (Max: " + + adminAcc.getSubAccountNum() + "). Upgrade to create more."); + } } } diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index a6d53e54..972574a8 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -192,7 +192,7 @@ unknown.mode=unknown mode unknown.subscription.plan=unknown subscription plan unknown.subscription.status=Unknown subscription status. 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. unknown.organization=Unknown organization. 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. 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. +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: diff --git a/src/main/resources/messages_zh.properties b/src/main/resources/messages_zh.properties index d5c5985f..ebba9619 100644 --- a/src/main/resources/messages_zh.properties +++ b/src/main/resources/messages_zh.properties @@ -188,7 +188,7 @@ unknown.mode=未知模式 unknown.subscription.plan=未知订阅计划 unknown.subscription.status=未知订阅状态 subscription.has.expired=切换失败,订阅已过期 -unknown.administrator.user=切换失败,未知管理员用户 +unknown.administrator.user=操作失败,未知管理员用户 no.permission.manage.subscription=切换失败,您没有权限管理该订阅 unknown.organization=未知组织 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=开始时间不能晚于结束时间 page.size.limit=每页数量必须在1-100之间 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: