feat(tenant-balance): 新增后台给租户充值余额接口

This commit is contained in:
2025-11-19 22:10:39 +08:00
parent f00e250be9
commit ebf071b225
10 changed files with 160 additions and 18 deletions

View File

@@ -101,4 +101,12 @@ public class TenantBalanceController {
BeanUtils.toBean(list, TenantBalanceRespVO.class));
}
@PostMapping("/addAmount")
@Operation(summary = "添加租户余额")
@PreAuthorize("@ss.hasPermission('system:tenant-balance:add')")
public CommonResult<Boolean> addTenantBalance(@Valid @RequestBody TenantBalanceAddReqVO addReqVO) {
tenantBalanceService.addTenantBalance(addReqVO);
return success(true);
}
}

View File

@@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
/*
* @author: ziin
* @date: 2025/11/19 21:05
*/
@Schema(description = "管理后台 - 租户余额添加VO")
@Data
public class TenantBalanceAddReqVO {
@Schema(description = "租户 Id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19954")
@NotNull(message = "租户 Id 不能为空")
private Long id;
@Schema(description = "增加的余额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000000")
@NotNull(message = "增加的余额不能为空")
private Integer amount;
}

View File

@@ -14,12 +14,11 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
@TableName("system_tenant_balance")
@KeySequence("system_tenant_balance_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TenantBalanceDO extends BaseDO {
public class TenantBalanceDO{
private Long id;
/**

View File

@@ -14,17 +14,16 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
@TableName("system_tenant_points")
@KeySequence("system_tenant_points_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TenantPointsDO extends BaseDO {
public class TenantPointsDO {
/**
* 主键
*/
@TableId
@TableId(type = IdType.AUTO)
private Long id;
/**
* 本次变动点数,正加负减
@@ -63,5 +62,6 @@ public class TenantPointsDO extends BaseDO {
*/
private LocalDateTime createdAt;
private Long tenantId;
}

View File

@@ -25,4 +25,9 @@ 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()));
}
}

View File

@@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.system.enums.balance;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
/*
* @author: ziin
* @date: 2025/11/19 21:30
*/
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum BalanceEnum {
RECHARGE("充值"),
TRANSFER("转账"),
CONSUMPTION("消费");
private String desc;
}

View File

@@ -59,4 +59,5 @@ public interface TenantBalanceService {
*/
PageResult<TenantBalanceDO> getTenantBalancePage(TenantBalancePageReqVO pageReqVO);
void addTenantBalance(@Valid TenantBalanceAddReqVO updateReqVO);
}

View File

@@ -1,24 +1,27 @@
package cn.iocoder.yudao.module.system.service.tenantbalance;
import cn.hutool.core.collection.CollUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance.TenantBalanceDO;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
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;
import cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance.TenantBalanceDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenantpoints.TenantPointsDO;
import cn.iocoder.yudao.module.system.dal.mysql.tenantbalance.TenantBalanceMapper;
import cn.iocoder.yudao.module.system.dal.mysql.tenantpoints.TenantPointsMapper;
import cn.iocoder.yudao.module.system.util.BizNoGenerator;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_BALANCE_NOT_EXISTS;
import static cn.iocoder.yudao.module.system.enums.balance.BalanceEnum.RECHARGE;
/**
* 租户余额 Service 实现类
@@ -32,6 +35,9 @@ public class TenantBalanceServiceImpl implements TenantBalanceService {
@Resource
private TenantBalanceMapper tenantBalanceMapper;
@Resource
private TenantPointsMapper tenantPointsMapper;
@Override
public Long createTenantBalance(TenantBalanceSaveReqVO createReqVO) {
// 插入
@@ -89,4 +95,41 @@ public class TenantBalanceServiceImpl implements TenantBalanceService {
return tenantBalanceMapper.selectPage(pageReqVO);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void addTenantBalance(TenantBalanceAddReqVO addReqVO) {
// 校验存在
if (tenantBalanceMapper.selectById(addReqVO.getId()) == null) {
// 初始化余额为 0
TenantBalanceDO tenantBalance = new TenantBalanceDO();
tenantBalance.setId(addReqVO.getId());
tenantBalance.setBalance(0);
tenantBalance.setVersion(0);
tenantBalanceMapper.insert(tenantBalance);
}
String recharge = BizNoGenerator.generate("RECHARGE");
// 获取初始化查询结果
TenantBalanceDO tenantBalance = tenantBalanceMapper.selectById(addReqVO.getId());
Integer newBalance = tenantBalance.getBalance()+addReqVO.getAmount();
Integer oldVersion = tenantBalance.getVersion();
TenantBalanceDO updateObj = BeanUtils.toBean(addReqVO, TenantBalanceDO.class);
updateObj.setVersion(oldVersion);
updateObj.setBalance(newBalance);
Integer updateCount = tenantBalanceMapper.updateBalanceWithVersion(updateObj);
if (updateCount == 0) {
throw exception(TENANT_BALANCE_NOT_EXISTS);
}
TenantPointsDO tenantPointsDO = new TenantPointsDO();
tenantPointsDO.setTenantId(addReqVO.getId());
tenantPointsDO.setPoints(addReqVO.getAmount());
tenantPointsDO.setBalance(newBalance);
tenantPointsDO.setType(RECHARGE.getDesc()); // RECHARGE / BONUS / ...
tenantPointsDO.setDescription("后台加积分");
tenantPointsDO.setBizNo(recharge);
tenantPointsMapper.insert(tenantPointsDO);
}
}

View File

@@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.system.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
public class BizNoGenerator {
private static final AtomicInteger SEQUENCE = new AtomicInteger(0);
private static final int MAX_SEQUENCE = 999999;
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");
/**
* 生成通用业务流水号
* 格式PREFIX-yyyyMMdd-000001
*/
public static String generate(String prefix) {
String date = DATE_FORMAT.format(new Date());
// 自增序列(每天重置)
int seq = SEQUENCE.incrementAndGet();
if (seq > MAX_SEQUENCE) {
synchronized (BizNoGenerator.class) {
if (SEQUENCE.get() > MAX_SEQUENCE) {
SEQUENCE.set(1);
seq = 1;
}
}
}
return prefix + "-" + date + "-" + String.format("%06d", seq);
}
}

View File

@@ -193,6 +193,8 @@ yudao:
- server_country_info
- ai_comment
- ai_language
- system_tenant_balance
- system_tenant_points
ignore-caches:
- user_role_ids
- permission_menu_ids