feat(system): 新增租户余额版本号校验与充值错误码

补充乐观锁场景下的版本号、余额异常及充值失败专用错误码,为后续余额并发更新提供精确异常定位。
This commit is contained in:
2025-11-20 18:26:35 +08:00
parent ebf071b225
commit 3466996f07
4 changed files with 36 additions and 8 deletions

View File

@@ -12,6 +12,10 @@ import com.alibaba.excel.annotation.*;
@ExcelIgnoreUnannotated
public class TenantBalanceRespVO {
@Schema(description = "租户 Id", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("租户 Id")
private Long id;
@Schema(description = "当前积分余额", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("当前积分余额")
private Integer balance;

View File

@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance.TenantBalanceDO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.*;
@@ -25,9 +26,18 @@ public interface TenantBalanceMapper extends BaseMapperX<TenantBalanceDO> {
.orderByDesc(TenantBalanceDO::getId));
}
default Integer updateBalanceWithVersion(TenantBalanceDO updateObj){
return update(updateObj, new LambdaQueryWrapperX<TenantBalanceDO>()
.eq(TenantBalanceDO::getId, updateObj.getId())
.eq(TenantBalanceDO::getVersion, updateObj.getVersion()));
default Integer updateBalanceWithVersion(Long id, int amount, Integer oldVersion) {
LambdaUpdateWrapper<TenantBalanceDO> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(TenantBalanceDO::getId, id);
wrapper.eq(TenantBalanceDO::getVersion, oldVersion);
// balance = balance + amount
wrapper.setSql("balance = balance + " + amount);
// version = version + 1
wrapper.setSql("version = version + 1");
return this.update(null, wrapper);
}
}

View File

@@ -121,6 +121,10 @@ public interface ErrorCodeConstants {
// ========== 租户余额 1-003-017-000 ==========
ErrorCode TENANT_BALANCE_NOT_EXISTS = new ErrorCode(1_003_017_000, "租户余额不存在");
ErrorCode TENANT_BALANCE_VERSION_ERROR = new ErrorCode(1_003_017_001, "租户余额版本号错误");
ErrorCode TENANT_BALANCE_BALANCE_ERROR = new ErrorCode(1_003_017_002, "租户余额余额错误");
ErrorCode TENANT_BALANCE_BALANCE_NOT_ENOUGH = new ErrorCode(1_003_017_003, "租户余额余额不足");
ErrorCode TENANT_BALANCE_RECHARGE_ERROR = new ErrorCode(1_003_017_004, "租户余额充值错误");
// ========== 社交用户 1-002-018-000 ==========

View File

@@ -4,6 +4,9 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.TenantBalanceAddReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.TenantBalancePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.TenantBalanceSaveReqVO;
@@ -20,7 +23,7 @@ import javax.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_BALANCE_NOT_EXISTS;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.system.enums.balance.BalanceEnum.RECHARGE;
/**
@@ -98,6 +101,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService {
@Override
@Transactional(rollbackFor = Exception.class)
public void addTenantBalance(TenantBalanceAddReqVO addReqVO) {
// 校验存在
if (tenantBalanceMapper.selectById(addReqVO.getId()) == null) {
// 初始化余额为 0
@@ -118,16 +122,22 @@ public class TenantBalanceServiceImpl implements TenantBalanceService {
updateObj.setVersion(oldVersion);
updateObj.setBalance(newBalance);
Integer updateCount = tenantBalanceMapper.updateBalanceWithVersion(updateObj);
Integer updateCount = tenantBalanceMapper.updateBalanceWithVersion(addReqVO.getId(), addReqVO.getAmount(), oldVersion);
if (updateCount == 0) {
throw exception(TENANT_BALANCE_NOT_EXISTS);
throw exception(TENANT_BALANCE_RECHARGE_ERROR);
}
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
if (loginUser == null) {
throw exception(USER_NOT_EXISTS);
}
TenantPointsDO tenantPointsDO = new TenantPointsDO();
tenantPointsDO.setTenantId(addReqVO.getId());
tenantPointsDO.setPoints(addReqVO.getAmount());
tenantPointsDO.setBalance(newBalance);
tenantPointsDO.setOperatorId(loginUser.getId());
tenantPointsDO.setType(RECHARGE.getDesc()); // RECHARGE / BONUS / ...
tenantPointsDO.setDescription("后台积分");
tenantPointsDO.setDescription("后台变动积分");
tenantPointsDO.setBizNo(recharge);
tenantPointsMapper.insert(tenantPointsDO);
}