feat(tenant-balance): 新增余额充值及自查询接口
This commit is contained in:
@@ -101,4 +101,28 @@ public class TenantBalanceController {
|
|||||||
BeanUtils.toBean(list, TenantBalanceRespVO.class));
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get-self-amount")
|
||||||
|
@Operation(summary = "获得自己的余额")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:tenant-balance:self-amount')")
|
||||||
|
public CommonResult<TenantBalanceRespVO> getTenantBalance() {
|
||||||
|
TenantBalanceDO tenantBalance = tenantBalanceService.getSelfBalance();
|
||||||
|
return success(BeanUtils.toBean(tenantBalance, TenantBalanceRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get-self-subordinate-amount-page")
|
||||||
|
@Operation(summary = "获得自己下级余额的分页")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:tenant-balance:self-subordinate')")
|
||||||
|
public CommonResult<PageResult<TenantBalanceRespVO>> getSelfSubordinate(@Valid TenantBalancePageReqVO pageReqVO) {
|
||||||
|
PageResult<TenantBalanceRespVO> tenantBalancePage = tenantBalanceService.getSelfSubordinateTenantBalancePage(pageReqVO);
|
||||||
|
return success(BeanUtils.toBean(tenantBalancePage, TenantBalanceRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.yolo.keyboard.controller.admin.tenantbalance.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @author: ziin
|
||||||
|
* @date: 2025/11/19 21:05
|
||||||
|
*/
|
||||||
|
@Schema(description = "管理后台 - 租户余额添加VO")
|
||||||
|
@Data
|
||||||
|
public class TenantBalanceAddReqVO {
|
||||||
|
@Schema(description = "租户 Id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19954")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "增加的余额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000000")
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
@Schema(description = "备注", example = "备注")
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package com.yolo.keyboard.dal.dataobject.tenantbalance;
|
|||||||
|
|
||||||
import com.yolo.keyboard.framework.tenant.core.aop.TenantIgnore;
|
import com.yolo.keyboard.framework.tenant.core.aop.TenantIgnore;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
@@ -31,10 +33,11 @@ public class TenantBalanceDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 当前积分余额
|
* 当前积分余额
|
||||||
*/
|
*/
|
||||||
private Integer balance;
|
private BigDecimal balance;
|
||||||
/**
|
/**
|
||||||
* 乐观锁版本号
|
* 乐观锁版本号
|
||||||
*/
|
*/
|
||||||
|
@Version
|
||||||
private Integer version;
|
private Integer version;
|
||||||
/**
|
/**
|
||||||
* 更新时间
|
* 更新时间
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.yolo.keyboard.dal.dataobject.tenantbalancetransaction;
|
||||||
|
|
||||||
|
import com.yolo.keyboard.framework.tenant.core.aop.TenantIgnore;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.*;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.yolo.keyboard.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户积分记录 DO
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@TableName("system_tenant_balance_transaction")
|
||||||
|
@KeySequence("system_tenant_balance_transaction_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
|
@Data
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@TenantIgnore
|
||||||
|
public class TenantBalanceTransactionDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 本次变动点数,正加负减
|
||||||
|
*/
|
||||||
|
private BigDecimal points;
|
||||||
|
/**
|
||||||
|
* 变动后余额快照(冗余)
|
||||||
|
*/
|
||||||
|
private BigDecimal balance;
|
||||||
|
/**
|
||||||
|
* 变动类型,如 TRANSFER_IN, WITHDRAW,REFUND_COMMISSION ,RECHARGE_COMMISSION
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
/**
|
||||||
|
* 变动描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
/**
|
||||||
|
* 订单 Id/业务单号
|
||||||
|
*/
|
||||||
|
private String orderId;
|
||||||
|
/**
|
||||||
|
* 业务流水号(转账、订单等唯一标识)
|
||||||
|
*/
|
||||||
|
private String bizNo;
|
||||||
|
/**
|
||||||
|
* 操作人 Id
|
||||||
|
*/
|
||||||
|
private Long operatorId;
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
private Long tenantId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.yolo.keyboard.dal.mysql.tenantbalancetransaction;
|
||||||
|
|
||||||
|
import com.yolo.keyboard.dal.dataobject.tenantbalancetransaction.TenantBalanceTransactionDO;
|
||||||
|
import com.yolo.keyboard.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户积分记录 Mapper
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface TenantBalanceTransactionMapper extends BaseMapperX<TenantBalanceTransactionDO> {
|
||||||
|
}
|
||||||
@@ -59,4 +59,26 @@ public interface TenantBalanceService {
|
|||||||
*/
|
*/
|
||||||
PageResult<TenantBalanceDO> getTenantBalancePage(TenantBalancePageReqVO pageReqVO);
|
PageResult<TenantBalanceDO> getTenantBalancePage(TenantBalancePageReqVO pageReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加租户余额
|
||||||
|
*
|
||||||
|
* @param addReqVO 添加信息
|
||||||
|
*/
|
||||||
|
void addTenantBalance(@Valid TenantBalanceAddReqVO addReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得自己的余额
|
||||||
|
*
|
||||||
|
* @return 租户余额
|
||||||
|
*/
|
||||||
|
TenantBalanceDO getSelfBalance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得自己下级余额的分页
|
||||||
|
*
|
||||||
|
* @param pageReqVO 分页查询
|
||||||
|
* @return 租户余额分页
|
||||||
|
*/
|
||||||
|
PageResult<TenantBalanceRespVO> getSelfSubordinateTenantBalancePage(TenantBalancePageReqVO pageReqVO);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
package com.yolo.keyboard.service.tenantbalance;
|
package com.yolo.keyboard.service.tenantbalance;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import com.yolo.keyboard.dal.dataobject.tenantbalancetransaction.TenantBalanceTransactionDO;
|
||||||
|
import com.yolo.keyboard.dal.mysql.tenantbalancetransaction.TenantBalanceTransactionMapper;
|
||||||
|
import com.yolo.keyboard.framework.tenant.core.context.TenantContextHolder;
|
||||||
|
import com.yolo.keyboard.utils.BizNoGenerator;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import com.yolo.keyboard.controller.admin.tenantbalance.vo.*;
|
import com.yolo.keyboard.controller.admin.tenantbalance.vo.*;
|
||||||
import com.yolo.keyboard.dal.dataobject.tenantbalance.TenantBalanceDO;
|
import com.yolo.keyboard.dal.dataobject.tenantbalance.TenantBalanceDO;
|
||||||
@@ -32,6 +37,9 @@ public class TenantBalanceServiceImpl implements TenantBalanceService {
|
|||||||
@Resource
|
@Resource
|
||||||
private TenantBalanceMapper tenantBalanceMapper;
|
private TenantBalanceMapper tenantBalanceMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TenantBalanceTransactionMapper tenantBalanceTransactionMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createTenantBalance(TenantBalanceSaveReqVO createReqVO) {
|
public Long createTenantBalance(TenantBalanceSaveReqVO createReqVO) {
|
||||||
// 插入
|
// 插入
|
||||||
@@ -82,4 +90,47 @@ public class TenantBalanceServiceImpl implements TenantBalanceService {
|
|||||||
return tenantBalanceMapper.selectPage(pageReqVO);
|
return tenantBalanceMapper.selectPage(pageReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void addTenantBalance(TenantBalanceAddReqVO addReqVO) {
|
||||||
|
// 1. 根据ID查询租户余额记录,校验是否存在
|
||||||
|
TenantBalanceDO balance = tenantBalanceMapper.selectById(addReqVO.getId());
|
||||||
|
if (balance == null) {
|
||||||
|
throw exception(TENANT_BALANCE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 计算新的余额(当前余额 + 充值金额)
|
||||||
|
BigDecimal newBalance = balance.getBalance().add(new BigDecimal(String.valueOf(addReqVO.getAmount())));
|
||||||
|
// 3. 更新租户余额(使用乐观锁)
|
||||||
|
balance.setBalance(newBalance);
|
||||||
|
int updateCount = tenantBalanceMapper.updateById(balance);
|
||||||
|
if (updateCount == 0) {
|
||||||
|
throw exception(TENANT_BALANCE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 创建余额交易记录
|
||||||
|
TenantBalanceTransactionDO transaction = TenantBalanceTransactionDO.builder()
|
||||||
|
.bizNo(BizNoGenerator.generate("RECHARGE")) // 生成充值业务编号
|
||||||
|
.points(new BigDecimal(String.valueOf(addReqVO.getAmount()))) // 充值金额
|
||||||
|
.balance(newBalance) // 充值后余额
|
||||||
|
.tenantId(addReqVO.getId())
|
||||||
|
.type("RECHARGE") // 交易类型:充值
|
||||||
|
.description("余额充值") // 交易描述
|
||||||
|
.remark(addReqVO.getRemark()) // 备注信息
|
||||||
|
.operatorId(TenantContextHolder.getTenantId()) // 操作人ID(当前租户ID)
|
||||||
|
.build();
|
||||||
|
// 5. 插入交易记录到数据库
|
||||||
|
tenantBalanceTransactionMapper.insert(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TenantBalanceDO getSelfBalance() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<TenantBalanceRespVO> getSelfSubordinateTenantBalancePage(TenantBalancePageReqVO pageReqVO) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.yolo.keyboard.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
|
||||||
|
public class BizNoGenerator {
|
||||||
|
public static String generate(String prefix) {
|
||||||
|
return prefix + "-" + IdUtil.getSnowflakeNextIdStr();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import com.baomidou.mybatisplus.extension.incrementer.*;
|
|||||||
import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
|
import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
|
||||||
import com.baomidou.mybatisplus.extension.parser.cache.JdkSerialCaffeineJsqlParseCache;
|
import com.baomidou.mybatisplus.extension.parser.cache.JdkSerialCaffeineJsqlParseCache;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
@@ -48,6 +49,7 @@ public class YoloMybatisAutoConfiguration {
|
|||||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||||
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
|
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
|
||||||
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件
|
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件
|
||||||
|
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 乐观锁插件
|
||||||
// ↓↓↓ 按需开启,可能会影响到 updateBatch 的地方:例如说文件配置管理 ↓↓↓
|
// ↓↓↓ 按需开启,可能会影响到 updateBatch 的地方:例如说文件配置管理 ↓↓↓
|
||||||
// mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); // 拦截没有指定条件的 update 和 delete 语句
|
// mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); // 拦截没有指定条件的 update 和 delete 语句
|
||||||
return mybatisPlusInterceptor;
|
return mybatisPlusInterceptor;
|
||||||
|
|||||||
Reference in New Issue
Block a user