feat(system): 新增租户余额版本号校验与充值错误码
补充乐观锁场景下的版本号、余额异常及充值失败专用错误码,为后续余额并发更新提供精确异常定位。
This commit is contained in:
@@ -12,6 +12,10 @@ import com.alibaba.excel.annotation.*;
|
|||||||
@ExcelIgnoreUnannotated
|
@ExcelIgnoreUnannotated
|
||||||
public class TenantBalanceRespVO {
|
public class TenantBalanceRespVO {
|
||||||
|
|
||||||
|
@Schema(description = "租户 Id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@ExcelProperty("租户 Id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
@Schema(description = "当前积分余额", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "当前积分余额", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@ExcelProperty("当前积分余额")
|
@ExcelProperty("当前积分余额")
|
||||||
private Integer balance;
|
private Integer balance;
|
||||||
|
|||||||
@@ -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.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance.TenantBalanceDO;
|
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 org.apache.ibatis.annotations.Mapper;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.*;
|
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.*;
|
||||||
|
|
||||||
@@ -25,9 +26,18 @@ public interface TenantBalanceMapper extends BaseMapperX<TenantBalanceDO> {
|
|||||||
.orderByDesc(TenantBalanceDO::getId));
|
.orderByDesc(TenantBalanceDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
default Integer updateBalanceWithVersion(TenantBalanceDO updateObj){
|
default Integer updateBalanceWithVersion(Long id, int amount, Integer oldVersion) {
|
||||||
return update(updateObj, new LambdaQueryWrapperX<TenantBalanceDO>()
|
LambdaUpdateWrapper<TenantBalanceDO> wrapper = new LambdaUpdateWrapper<>();
|
||||||
.eq(TenantBalanceDO::getId, updateObj.getId())
|
|
||||||
.eq(TenantBalanceDO::getVersion, updateObj.getVersion()));
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,6 +121,10 @@ public interface ErrorCodeConstants {
|
|||||||
|
|
||||||
// ========== 租户余额 1-003-017-000 ==========
|
// ========== 租户余额 1-003-017-000 ==========
|
||||||
ErrorCode TENANT_BALANCE_NOT_EXISTS = new ErrorCode(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 ==========
|
// ========== 社交用户 1-002-018-000 ==========
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import cn.hutool.core.collection.CollUtil;
|
|||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
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.TenantBalanceAddReqVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.TenantBalancePageReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.TenantBalancePageReqVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.TenantBalanceSaveReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.TenantBalanceSaveReqVO;
|
||||||
@@ -20,7 +23,7 @@ import javax.annotation.Resource;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
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;
|
import static cn.iocoder.yudao.module.system.enums.balance.BalanceEnum.RECHARGE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,6 +101,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService {
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void addTenantBalance(TenantBalanceAddReqVO addReqVO) {
|
public void addTenantBalance(TenantBalanceAddReqVO addReqVO) {
|
||||||
|
|
||||||
// 校验存在
|
// 校验存在
|
||||||
if (tenantBalanceMapper.selectById(addReqVO.getId()) == null) {
|
if (tenantBalanceMapper.selectById(addReqVO.getId()) == null) {
|
||||||
// 初始化余额为 0
|
// 初始化余额为 0
|
||||||
@@ -118,16 +122,22 @@ public class TenantBalanceServiceImpl implements TenantBalanceService {
|
|||||||
|
|
||||||
updateObj.setVersion(oldVersion);
|
updateObj.setVersion(oldVersion);
|
||||||
updateObj.setBalance(newBalance);
|
updateObj.setBalance(newBalance);
|
||||||
Integer updateCount = tenantBalanceMapper.updateBalanceWithVersion(updateObj);
|
Integer updateCount = tenantBalanceMapper.updateBalanceWithVersion(addReqVO.getId(), addReqVO.getAmount(), oldVersion);
|
||||||
if (updateCount == 0) {
|
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 tenantPointsDO = new TenantPointsDO();
|
||||||
tenantPointsDO.setTenantId(addReqVO.getId());
|
tenantPointsDO.setTenantId(addReqVO.getId());
|
||||||
tenantPointsDO.setPoints(addReqVO.getAmount());
|
tenantPointsDO.setPoints(addReqVO.getAmount());
|
||||||
tenantPointsDO.setBalance(newBalance);
|
tenantPointsDO.setBalance(newBalance);
|
||||||
|
tenantPointsDO.setOperatorId(loginUser.getId());
|
||||||
tenantPointsDO.setType(RECHARGE.getDesc()); // RECHARGE / BONUS / ...
|
tenantPointsDO.setType(RECHARGE.getDesc()); // RECHARGE / BONUS / ...
|
||||||
tenantPointsDO.setDescription("后台加积分");
|
tenantPointsDO.setDescription("后台变动积分");
|
||||||
tenantPointsDO.setBizNo(recharge);
|
tenantPointsDO.setBizNo(recharge);
|
||||||
tenantPointsMapper.insert(tenantPointsDO);
|
tenantPointsMapper.insert(tenantPointsDO);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user