TASK:1、教育版添加新用户、修改用户、移除用户需求更改;2、修改登入校验条件
BUGFIX:当用户积分为空时报错
This commit is contained in:
@@ -43,8 +43,8 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
private SecurityProperties properties;
|
||||
|
||||
private static final List<String> FILTER_URL =
|
||||
Arrays.asList("/favicon.ico", "/doc.html", "api/account/login", "api/account/preLogin", "api/account/sendEmail","api/account/noLoginRequired",
|
||||
"/webjars/", "/swagger-resources", "/v2/api-docs", "api/account/resetPwd",
|
||||
Arrays.asList("/favicon.ico", "/doc.html", "/api/account/login", "/api/account/preLogin", "api/account/sendEmail","api/account/noLoginRequired",
|
||||
"/webjars/", "/swagger-resources", "/v2/api-docs", "/api/account/resetPwd",
|
||||
"/api/python/saveGeneratePicture", "/api/python/getLibraryByUserId",
|
||||
"/api/third/party/addUser","/api/third/party/addTrialUser", "/api/third/party/editUser", "/api/element/initDefaultSysFile",
|
||||
"/api/third/party/addNoLoginRequiredNew","/api/third/party/deleteNoLoginRequiredNew","/api/third/party/updateNoLoginRequiredNew",
|
||||
@@ -53,7 +53,7 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
"/api/portfolio/page", "/api/portfolio/detail", "/api/portfolio/commentPage", "/api/portfolio/viewsIncrease",
|
||||
"/api/account/designWorksRegister","/api/account/questionnaire","/api/stripe/trade/notify",
|
||||
"/notification","/api/account/activateNewEmail","/api/third/party/auth/google_callback","/api/third/party/parseGoogleCredential","/api/third/party/receiveDesignResults","/api/third/party/parseWeChatCode","/api/third/party/receiveDesignParams"
|
||||
, "api/account/schoolLogin", "api/account/enterpriseLogin", "api/account/organizationNameSearch",
|
||||
, "/api/account/schoolLogin", "/api/account/enterpriseLogin", "/api/account/organizationNameSearch",
|
||||
"/api/llm/stream"
|
||||
);
|
||||
|
||||
@@ -61,7 +61,7 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
protected void doFilterInternal(HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, @NonNull FilterChain filterChain) throws ServletException, IOException {
|
||||
String requestURI = httpServletRequest.getRequestURI();
|
||||
|
||||
if (calculateUrl(requestURI) || hasAuthorizationToken(httpServletRequest)) {
|
||||
if (calculateUrl(requestURI)/* || hasAuthorizationToken(httpServletRequest)*/) {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
HttpServletRequest wrappedRequest = httpServletRequest;
|
||||
HttpServletResponse wrappedResponse = httpServletResponse;
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.ai.da.common.context.UserContext;
|
||||
import com.ai.da.common.enums.AuthenticationOperationTypeEnum;
|
||||
import com.ai.da.common.enums.CreditsEventsEnum;
|
||||
import com.ai.da.common.enums.LoginTypeEnum;
|
||||
import com.ai.da.common.enums.ProductEnum;
|
||||
import com.ai.da.common.response.PageBaseResponse;
|
||||
import com.ai.da.common.response.ResultEnum;
|
||||
import com.ai.da.common.security.jwt.JWTTokenHelper;
|
||||
@@ -94,6 +95,9 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
@Resource
|
||||
private LibraryService libraryService;
|
||||
|
||||
@Resource
|
||||
private OrderInfoService orderInfoService;
|
||||
|
||||
@Resource
|
||||
private TrialOrderMapper trialOrderMapper;
|
||||
|
||||
@@ -2142,54 +2146,295 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
|
||||
@Override
|
||||
public Boolean addSubAccount(AddSubAccountDTO addSubAccountDTO) {
|
||||
if (null == addSubAccountDTO.getId()) {
|
||||
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
|
||||
Account account = accountMapper.selectById(authPrincipalVo.getId());
|
||||
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
|
||||
Account account = accountMapper.selectById(authPrincipalVo.getId());
|
||||
int subUserRole = getSubUserRole(account.getSystemUser());
|
||||
|
||||
QueryWrapper<Account> qw = new QueryWrapper<>();
|
||||
qw.lambda().eq(Account::getOrganizationName, account.getOrganizationName());
|
||||
List<Account> accounts = accountMapper.selectList(qw);
|
||||
if (accounts.size() >= account.getSubAccountNum()) {
|
||||
throw new BusinessException("The maximum number of sub accounts that can be created has been reached.");
|
||||
}
|
||||
if (addSubAccountDTO.getId() == null) {
|
||||
return createSubAccount(addSubAccountDTO, account, subUserRole, null, null);
|
||||
} else {
|
||||
return updateSubAccount(addSubAccountDTO, account, subUserRole);
|
||||
}
|
||||
}
|
||||
|
||||
qw.lambda().eq(Account::getUserName, addSubAccountDTO.getUserName());
|
||||
accounts = accountMapper.selectList(qw);
|
||||
if (CollectionUtil.isNotEmpty(accounts)) {
|
||||
throw new BusinessException("The enterprise already has an account with the same username.");
|
||||
}
|
||||
private int getSubUserRole(int systemUser) {
|
||||
switch (systemUser) {
|
||||
case 5:
|
||||
return 6;
|
||||
case 7:
|
||||
return 8;
|
||||
default:
|
||||
throw new BusinessException("Access denied. Insufficient permissions.");
|
||||
}
|
||||
}
|
||||
|
||||
Account subAccount = CopyUtil.copyObject(addSubAccountDTO, Account.class);
|
||||
if (account.getSystemUser() == 5) {
|
||||
subAccount.setSystemUser(6);
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean createSubAccount(AddSubAccountDTO addSubAccountDTO, Account account, int subUserRole,
|
||||
BigDecimal creditsLimit, BigDecimal creditsUsage) {
|
||||
QueryWrapper<Account> qw = new QueryWrapper<>();
|
||||
qw.lambda().eq(Account::getOrganizationName, account.getOrganizationName());
|
||||
List<Account> accounts = accountMapper.selectList(qw);
|
||||
|
||||
// 校验子账号总数是否达上限
|
||||
if (account.getSubAccountNum() == null || account.getSubAccountNum() <= 0){
|
||||
throw new BusinessException("Error: Sub-account quota reached (Max: 0). Upgrade to create more.");
|
||||
}
|
||||
if (accounts.size() >= account.getSubAccountNum()) {
|
||||
throw new BusinessException("Error: Sub-account quota reached (Max: " + account.getSubAccountNum() + "). Upgrade to create more.");
|
||||
}
|
||||
|
||||
// 校验邮箱是否已加入组织
|
||||
if (isUserEmailExists(account.getOrganizationName(), addSubAccountDTO.getUserEmail())) {
|
||||
throw new BusinessException("This organization already has an account with the same email.", ResultEnum.PROMPT.getCode());
|
||||
}
|
||||
|
||||
// 校验用户名是否同名
|
||||
if (isUsernameExists(account.getOrganizationName(), addSubAccountDTO.getUserName())) {
|
||||
throw new BusinessException("This organization already has an account with the same username.");
|
||||
}
|
||||
|
||||
// 校验当前账号邮箱是否有个人账号
|
||||
Account subAccount = accountMapper.selectOne(new QueryWrapper<Account>().eq("user_email", addSubAccountDTO.getUserEmail()));
|
||||
List<Integer> personAccRole = Arrays.asList(0, 1, 2, 3);
|
||||
List<Integer> orgAccRole = Arrays.asList(5, 6, 7, 8);
|
||||
|
||||
if (Objects.nonNull(subAccount) && personAccRole.contains(subAccount.getSystemUser())) {
|
||||
log.info("将用户{} 加入组织{}", addSubAccountDTO.getUserEmail(), account.getOrganizationName());
|
||||
subAccount.setUserName(addSubAccountDTO.getUserName());
|
||||
subAccount.setUserPassword(addSubAccountDTO.getUserPassword());
|
||||
subAccount.setSystemUser(subUserRole);
|
||||
subAccount.setOrganizationName(account.getOrganizationName());
|
||||
subAccount.setParentId(account.getId());
|
||||
if (Objects.nonNull(creditsLimit)){
|
||||
subAccount.setCreditsUsageLimit(creditsLimit);
|
||||
subAccount.setCreditsUsage(creditsUsage);
|
||||
if (Objects.nonNull(subAccount.getCredits())) {
|
||||
subAccount.setCredits(subAccount.getCreditsUsageLimit().add(subAccount.getCredits()));
|
||||
}
|
||||
}else {
|
||||
handleSubAccCredits(subAccount, account);
|
||||
}
|
||||
if (account.getSystemUser() == 7) {
|
||||
subAccount.setSystemUser(8);
|
||||
subAccount.setUpdateDate(new Date());
|
||||
updateById(subAccount);
|
||||
updateById(account);
|
||||
} else if (Objects.nonNull(subAccount) && orgAccRole.contains(subAccount.getSystemUser())) {
|
||||
throw new BusinessException("邮箱 " + addSubAccountDTO.getUserEmail() + " 已加入其他组织", ResultEnum.PROMPT.getCode());
|
||||
} else {
|
||||
subAccount = new Account();
|
||||
subAccount.setUserName(addSubAccountDTO.getUserName());
|
||||
subAccount.setUserEmail(addSubAccountDTO.getUserEmail());
|
||||
subAccount.setUserPassword(addSubAccountDTO.getUserPassword());
|
||||
if (Objects.nonNull(creditsLimit)){
|
||||
subAccount.setCreditsUsageLimit(creditsLimit);
|
||||
subAccount.setCreditsUsage(creditsUsage);
|
||||
if (Objects.nonNull(subAccount.getCredits())) {
|
||||
subAccount.setCredits(subAccount.getCreditsUsageLimit().add(subAccount.getCredits()));
|
||||
}else {
|
||||
subAccount.setCredits(subAccount.getCreditsUsageLimit());
|
||||
}
|
||||
} else {
|
||||
handleSubAccCredits(subAccount, account);
|
||||
updateById(account);
|
||||
}
|
||||
subAccount.setValidStartTime(account.getValidStartTime());
|
||||
subAccount.setValidEndTime(account.getValidEndTime());
|
||||
subAccount.setSystemUser(subUserRole);
|
||||
subAccount.setLanguage(Language.ENGLISH.name());
|
||||
subAccount.setCreateDate(new Date());
|
||||
subAccount.setIsTrial(0);
|
||||
subAccount.setIsBeginner(1);
|
||||
subAccount.setParentId(account.getParentId());
|
||||
subAccount.setParentId(account.getId());
|
||||
subAccount.setOrganizationName(account.getOrganizationName());
|
||||
accountMapper.insert(subAccount);
|
||||
}else {
|
||||
Account subAccount = CopyUtil.copyObject(addSubAccountDTO, Account.class);
|
||||
accountMapper.updateById(subAccount);
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
private Boolean updateSubAccount(AddSubAccountDTO addSubAccountDTO, Account account, int subUserRole) {
|
||||
Account exAccountInfo = baseMapper.selectById(addSubAccountDTO.getId());
|
||||
|
||||
// 校验用户名是否同名
|
||||
if (!exAccountInfo.getUserName().equals(addSubAccountDTO.getUserName()) && isUsernameExists(account.getOrganizationName(), addSubAccountDTO.getUserName())) {
|
||||
throw new BusinessException("This organization already has an account with the same username.");
|
||||
}else if (!exAccountInfo.getUserName().equals(addSubAccountDTO.getUserName())){
|
||||
exAccountInfo.setUserName(addSubAccountDTO.getUserName());
|
||||
}
|
||||
|
||||
// 判断积分变更是增加还是减少还是没变化
|
||||
if (Objects.nonNull(addSubAccountDTO.getCreditsUsageLimit()) && exAccountInfo.getCreditsUsageLimit().compareTo(addSubAccountDTO.getCreditsUsageLimit()) < 0) {
|
||||
BigDecimal remainingCredits = adminRemainingCredits(account);
|
||||
// 新增加的积分
|
||||
BigDecimal addedCredits = addSubAccountDTO.getCreditsUsageLimit().subtract(exAccountInfo.getCreditsUsageLimit());
|
||||
if (remainingCredits.compareTo(addedCredits) >= 0) {
|
||||
// 更新管理员已分配的积分
|
||||
account.setCreditsUsage(account.getCreditsUsage().add(addedCredits));
|
||||
// 更新子账号的积分上限
|
||||
exAccountInfo.setCreditsUsageLimit(addSubAccountDTO.getCreditsUsageLimit());
|
||||
} else {
|
||||
throw new BusinessException("Insufficient credits (Balance: " + remainingCredits + ").", ResultEnum.PROMPT.getCode());
|
||||
}
|
||||
} else if (Objects.nonNull(addSubAccountDTO.getCreditsUsageLimit()) && exAccountInfo.getCreditsUsageLimit().compareTo(addSubAccountDTO.getCreditsUsageLimit()) > 0) {
|
||||
if (exAccountInfo.getCreditsUsage().compareTo(addSubAccountDTO.getCreditsUsageLimit()) > 0) {
|
||||
throw new BusinessException("Usage alert: " + exAccountInfo.getCreditsUsage() + " credits consumed this month. New limit must be ≥ " + exAccountInfo.getCreditsUsage() + " .");
|
||||
} else {
|
||||
// 减少的积分
|
||||
BigDecimal subtractedCredits = exAccountInfo.getCreditsUsageLimit().subtract(addSubAccountDTO.getCreditsUsageLimit());
|
||||
// 更新管理员已分配的积分(积分回流)
|
||||
account.setCreditsUsage(account.getCreditsUsage().subtract(subtractedCredits));
|
||||
// 更新子账号的积分上限
|
||||
exAccountInfo.setCreditsUsageLimit(addSubAccountDTO.getCreditsUsageLimit());
|
||||
}
|
||||
}
|
||||
|
||||
// 校验邮箱是否变更
|
||||
if (!exAccountInfo.getUserEmail().equals(addSubAccountDTO.getUserEmail())) {
|
||||
// 原账号的积分使用上限
|
||||
BigDecimal creditsLimit = exAccountInfo.getCreditsUsageLimit();
|
||||
// 原账号已使用的积分
|
||||
BigDecimal creditsUsage = exAccountInfo.getCreditsUsage();
|
||||
// 这里移除原账号,但是积分不回流,机构分配的积分会由下一个账号继续持有(包括积分上限和已使用的积分都保持不变)
|
||||
removeSubAccount(new AddSubAccountDTO(Collections.singletonList(addSubAccountDTO.getId())), false);
|
||||
// 移入新子账号(可能是移入,也可能是新增)
|
||||
createSubAccount(addSubAccountDTO, account, subUserRole, creditsLimit, creditsUsage);
|
||||
} else {
|
||||
baseMapper.updateById(exAccountInfo);
|
||||
baseMapper.updateById(account);
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
private boolean isUserEmailExists(String organizationName, String email) {
|
||||
QueryWrapper<Account> qw = new QueryWrapper<>();
|
||||
qw.lambda().eq(Account::getOrganizationName, organizationName).eq(Account::getUserEmail, email);
|
||||
return accountMapper.selectCount(qw) > 0;
|
||||
}
|
||||
|
||||
private boolean isUsernameExists(String organizationName, String userName) {
|
||||
QueryWrapper<Account> qw = new QueryWrapper<>();
|
||||
qw.lambda().eq(Account::getOrganizationName, organizationName).eq(Account::getUserName, userName);
|
||||
return accountMapper.selectCount(qw) > 0;
|
||||
}
|
||||
|
||||
public BigDecimal adminRemainingCredits(Account adminAccount) {
|
||||
if (adminAccount == null) {
|
||||
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
|
||||
adminAccount = accountMapper.selectById(authPrincipalVo.getId());
|
||||
if (adminAccount == null) {
|
||||
throw new BusinessException("管理员账户不存在");
|
||||
}
|
||||
}
|
||||
|
||||
if (Objects.nonNull(adminAccount.getCreditsUsageLimit()) && Objects.nonNull(adminAccount.getCreditsUsage())){
|
||||
return adminAccount.getCreditsUsageLimit().subtract(adminAccount.getCreditsUsage());
|
||||
}else if (Objects.nonNull(adminAccount.getCreditsUsageLimit())){
|
||||
return adminAccount.getCreditsUsageLimit();
|
||||
} else {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
// 仅适用于新建用户
|
||||
private void handleSubAccCredits(Account subAcc, Account adminAcc) {
|
||||
BigDecimal remainingCredits = adminRemainingCredits(adminAcc);
|
||||
if (remainingCredits.compareTo(BigDecimal.ZERO) < 0) {
|
||||
remainingCredits = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
if (Objects.nonNull(adminAcc.getCreditsUsageLimit()) && (Objects.isNull(subAcc.getCreditsUsageLimit()) || subAcc.getCreditsUsageLimit().compareTo(BigDecimal.ZERO) == 0)) {
|
||||
// todo 需要先判断管理员的订阅类型 年付 -> 4200 月付 -> 3500
|
||||
BigDecimal defaultCredits = BigDecimal.valueOf(3500L);
|
||||
|
||||
if (remainingCredits.compareTo(defaultCredits) >= 0) {
|
||||
subAcc.setCreditsUsageLimit(defaultCredits);
|
||||
} else if (remainingCredits.compareTo(BigDecimal.ZERO) > 0) {
|
||||
subAcc.setCreditsUsageLimit(remainingCredits);
|
||||
} else {
|
||||
subAcc.setCreditsUsageLimit(BigDecimal.ZERO);
|
||||
}
|
||||
adminAcc.setCreditsUsage(adminAcc.getCreditsUsage().add(subAcc.getCreditsUsageLimit()));
|
||||
adminAcc.setUpdateDate(new Date());
|
||||
log.debug("分配积分: subAccId={}, defaultCredits={}, remainingCredits={}", subAcc.getId(), defaultCredits, remainingCredits);
|
||||
|
||||
if (Objects.nonNull(subAcc.getCredits())) {
|
||||
subAcc.setCredits(subAcc.getCreditsUsageLimit().add(subAcc.getCredits()));
|
||||
}else {
|
||||
subAcc.setCredits(subAcc.getCreditsUsageLimit());
|
||||
}
|
||||
}
|
||||
// 创建账号时指定积分
|
||||
else if (Objects.nonNull(adminAcc.getCreditsUsageLimit())) {
|
||||
if (remainingCredits.compareTo(subAcc.getCreditsUsageLimit()) < 0) {
|
||||
throw new BusinessException("Insufficient credits (Balance: " + remainingCredits + ").", ResultEnum.PROMPT.getCode());
|
||||
} else {
|
||||
subAcc.setCredits(subAcc.getCreditsUsageLimit());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteSubAccount(AddSubAccountDTO addSubAccountDTO) {
|
||||
accountMapper.deleteBatchIds(addSubAccountDTO.getDeleteIdList());
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
public void removeSubAccount(AddSubAccountDTO addSubAccountDTO, boolean returnCredits) {
|
||||
Long adminAccId = UserContext.getUserHolder().getId();
|
||||
Account adminAcc = baseMapper.selectById(adminAccId);
|
||||
if (Objects.isNull(adminAcc) || (adminAcc.getSystemUser() != 5 && adminAcc.getSystemUser() != 7)) {
|
||||
throw new BusinessException("have.no.permission");
|
||||
}
|
||||
|
||||
BigDecimal unusedCreditsTotal = BigDecimal.ZERO;
|
||||
for (Long id : addSubAccountDTO.getDeleteIdList()) {
|
||||
Account account = baseMapper.selectById(id);
|
||||
if (Objects.nonNull(account.getParentId()) && account.getParentId().equals(adminAccId)) {
|
||||
BigDecimal unusedCredits = account.getCreditsUsageLimit().subtract(account.getCreditsUsage());
|
||||
BigDecimal finalCredits = calculateFinalCredits(account, unusedCredits);
|
||||
|
||||
int userRole = determineUserRole(account.getId());
|
||||
|
||||
UpdateWrapper<Account> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.lambda().eq(Account::getId, account.getId())
|
||||
.set(Account::getOrganizationName, null)
|
||||
.set(Account::getOrganizationId, null)
|
||||
.set(Account::getParentId, null)
|
||||
.set(Account::getSystemUser, userRole)
|
||||
.set(Account::getCredits, finalCredits)
|
||||
.set(Account::getCreditsUsage, null)
|
||||
.set(Account::getCreditsUsageLimit, null)
|
||||
.set(Account::getUpdateDate, new Date());
|
||||
baseMapper.update(null, updateWrapper);
|
||||
|
||||
if (unusedCredits.compareTo(BigDecimal.ZERO) > 0) {
|
||||
unusedCreditsTotal = unusedCreditsTotal.add(unusedCredits);
|
||||
}
|
||||
} else {
|
||||
log.warn("需要移除账号 {}: {} 不属于当前管理员 {}: {}", id, account.getUserEmail(), adminAccId, adminAcc.getUserEmail());
|
||||
}
|
||||
}
|
||||
// 是否需要将积分回流
|
||||
if (returnCredits && unusedCreditsTotal.compareTo(BigDecimal.ZERO) != 0){
|
||||
adminAcc.setCreditsUsage(adminAcc.getCreditsUsage().subtract(unusedCreditsTotal));
|
||||
adminAcc.setUpdateDate(new Date());
|
||||
baseMapper.updateById(adminAcc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private BigDecimal calculateFinalCredits(Account account, BigDecimal unusedCredits) {
|
||||
return unusedCredits.compareTo(BigDecimal.ZERO) > 0 ? account.getCredits().subtract(unusedCredits) :
|
||||
account.getCredits();
|
||||
}
|
||||
|
||||
private int determineUserRole(Long accountId) {
|
||||
List<String> subscriptionType = Arrays.asList(ProductEnum.MonthlySubscription.getName(), ProductEnum.AnnualSubscription.getName());
|
||||
List<OrderInfo> list = orderInfoService.list(new QueryWrapper<OrderInfo>().lambda().eq(OrderInfo::getAccountId, accountId)
|
||||
.in(OrderInfo::getTitle, subscriptionType).orderByDesc(OrderInfo::getId));
|
||||
if (!list.isEmpty()) {
|
||||
return list.get(0).getTitle().equals(ProductEnum.MonthlySubscription.getName()) ? 2 :
|
||||
list.get(0).getTitle().equals(ProductEnum.AnnualSubscription.getName()) ? 1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageBaseResponse<Account> subAccountList(SubAccountPageDTO subAccountPageDTO) {
|
||||
AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder();
|
||||
|
||||
@@ -96,7 +96,7 @@ public class CreditsServiceImpl extends ServiceImpl<CreditsDetailMapper, Credits
|
||||
@Override
|
||||
public String getCredits(Long accountId) {
|
||||
Account account = accountMapper.selectById(accountId);
|
||||
return account.getCredits().toString();
|
||||
return Objects.isNull(account.getCredits()) ? "0" : account.getCredits().toString();
|
||||
}
|
||||
|
||||
public void creditsRefund(Long accountId, Integer quantity, String orderNo) {
|
||||
|
||||
Reference in New Issue
Block a user