feat(system): 新增套餐消费与余额校验逻辑
- 为 TenantAgencyPackage 增加 validTenantPackage 校验方法 - 在 TenantBalanceService 中实现基于套餐的消费接口 - 新增租户余额消费失败错误码 TENANT_BALANCE_CONSUMPTION_OPERATION_ERROR - 将积分记录 orderId 类型由 Long 改为 String 以兼容业务流水号 - 消费时自动生成 CONSUMPTION/ORDER 业务编号并记录积分变动
This commit is contained in:
@@ -34,7 +34,7 @@ public class TenantPointsPageRespVO {
|
|||||||
|
|
||||||
@Schema(description = "订单 Id/业务单号", example = "84")
|
@Schema(description = "订单 Id/业务单号", example = "84")
|
||||||
@ExcelProperty("订单 Id/业务单号")
|
@ExcelProperty("订单 Id/业务单号")
|
||||||
private Long orderId;
|
private String orderId;
|
||||||
|
|
||||||
@Schema(description = "业务流水号(转账、订单等唯一标识)")
|
@Schema(description = "业务流水号(转账、订单等唯一标识)")
|
||||||
@ExcelProperty("业务流水号(转账、订单等唯一标识)")
|
@ExcelProperty("业务流水号(转账、订单等唯一标识)")
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class TenantPointsRespVO {
|
|||||||
|
|
||||||
@Schema(description = "订单 Id/业务单号", example = "84")
|
@Schema(description = "订单 Id/业务单号", example = "84")
|
||||||
@ExcelProperty("订单 Id/业务单号")
|
@ExcelProperty("订单 Id/业务单号")
|
||||||
private Long orderId;
|
private String orderId;
|
||||||
|
|
||||||
@Schema(description = "业务流水号(转账、订单等唯一标识)")
|
@Schema(description = "业务流水号(转账、订单等唯一标识)")
|
||||||
@ExcelProperty("业务流水号(转账、订单等唯一标识)")
|
@ExcelProperty("业务流水号(转账、订单等唯一标识)")
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class TenantPointsSaveReqVO {
|
|||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@Schema(description = "订单 Id/业务单号", example = "84")
|
@Schema(description = "订单 Id/业务单号", example = "84")
|
||||||
private Long orderId;
|
private String orderId;
|
||||||
|
|
||||||
@Schema(description = "业务流水号(转账、订单等唯一标识)")
|
@Schema(description = "业务流水号(转账、订单等唯一标识)")
|
||||||
private String bizNo;
|
private String bizNo;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage;
|
package cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -42,7 +43,8 @@ public class TenantAgencyPackageDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 关联的菜单编号
|
* 关联的菜单编号
|
||||||
*/
|
*/
|
||||||
private String menuIds;
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private Set<Long> menuIds;
|
||||||
/**
|
/**
|
||||||
* 套餐天数
|
* 套餐天数
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class TenantPointsDO {
|
|||||||
/**
|
/**
|
||||||
* 订单 Id/业务单号
|
* 订单 Id/业务单号
|
||||||
*/
|
*/
|
||||||
private Long orderId;
|
private String orderId;
|
||||||
/**
|
/**
|
||||||
* 业务流水号(转账、订单等唯一标识)
|
* 业务流水号(转账、订单等唯一标识)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode TENANT_BALANCE_TRANSFER_PASSWORD_ERROR = new ErrorCode(1_003_017_010, "转账密码错误");
|
ErrorCode TENANT_BALANCE_TRANSFER_PASSWORD_ERROR = new ErrorCode(1_003_017_010, "转账密码错误");
|
||||||
ErrorCode TENANT_BALANCE_TRANSFER_PASSWORD_ERROR_IS_NULL = new ErrorCode(1_003_017_011, "转账密码不能为空");
|
ErrorCode TENANT_BALANCE_TRANSFER_PASSWORD_ERROR_IS_NULL = new ErrorCode(1_003_017_011, "转账密码不能为空");
|
||||||
ErrorCode TENANT_BALANCE_TRANSFER_ERROR_TARGET_NOT_SUBORDINATE = new ErrorCode(1_003_017_012, "转账目标租户不是当前租户的下级");
|
ErrorCode TENANT_BALANCE_TRANSFER_ERROR_TARGET_NOT_SUBORDINATE = new ErrorCode(1_003_017_012, "转账目标租户不是当前租户的下级");
|
||||||
|
ErrorCode TENANT_BALANCE_CONSUMPTION_OPERATION_ERROR = new ErrorCode(1_003_017_013, "租户余额消费操作失败");
|
||||||
|
|
||||||
// ================= 租户套餐 1-003-018-000 ==================
|
// ================= 租户套餐 1-003-018-000 ==================
|
||||||
ErrorCode TENANT_AGENCY_PACKAGE_NOT_EXISTS = new ErrorCode(1_003_018_000, "代理租户套餐不存在");
|
ErrorCode TENANT_AGENCY_PACKAGE_NOT_EXISTS = new ErrorCode(1_003_018_000, "代理租户套餐不存在");
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.system.service.tenantagencypackage;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import javax.validation.*;
|
import javax.validation.*;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo.*;
|
import cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo.*;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO;
|
||||||
@@ -58,4 +60,5 @@ public interface TenantAgencyPackageService {
|
|||||||
*/
|
*/
|
||||||
PageResult<TenantAgencyPackageDO> getTenantAgencyPackagePage(TenantAgencyPackagePageReqVO pageReqVO);
|
PageResult<TenantAgencyPackageDO> getTenantAgencyPackagePage(TenantAgencyPackagePageReqVO pageReqVO);
|
||||||
|
|
||||||
|
TenantAgencyPackageDO validTenantPackage(@NotNull(message = "租户套餐编号不能为空") Long packageId);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package cn.iocoder.yudao.module.system.service.tenantagencypackage;
|
package cn.iocoder.yudao.module.system.service.tenantagencypackage;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -85,4 +87,17 @@ public class TenantAgencyPackageServiceImpl implements TenantAgencyPackageServic
|
|||||||
return tenantAgencyPackageMapper.selectPage(pageReqVO);
|
return tenantAgencyPackageMapper.selectPage(pageReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TenantAgencyPackageDO validTenantPackage(Long packageId) {
|
||||||
|
|
||||||
|
TenantAgencyPackageDO tenantPackage = tenantAgencyPackageMapper.selectById(packageId);
|
||||||
|
if (tenantPackage == null) {
|
||||||
|
throw exception(TENANT_PACKAGE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
if (tenantPackage.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) {
|
||||||
|
throw exception(TENANT_PACKAGE_DISABLE, tenantPackage.getName());
|
||||||
|
}
|
||||||
|
return tenantPackage;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -67,5 +67,5 @@ public interface TenantBalanceService {
|
|||||||
|
|
||||||
PageResult<TenantBalanceRespVO> getSelfSubordinateTenantBalancePage(@Valid TenantBalancePageReqVO pageReqVO);
|
PageResult<TenantBalanceRespVO> getSelfSubordinateTenantBalancePage(@Valid TenantBalancePageReqVO pageReqVO);
|
||||||
|
|
||||||
Boolean consumption(@Valid TenantBalanceConsumptionReqVO consumptionReqVO);
|
Boolean consumption(Long PackageId, Long targetTenantId,String remark);
|
||||||
}
|
}
|
||||||
@@ -8,10 +8,12 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
|||||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.*;
|
import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.*;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance.TenantBalanceDO;
|
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.dataobject.tenantpoints.TenantPointsDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
|
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.mysql.tenantagencypackage.TenantAgencyPackageMapper;
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.tenantbalance.TenantBalanceMapper;
|
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.dal.mysql.tenantpoints.TenantPointsMapper;
|
||||||
import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
|
import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
|
||||||
@@ -54,6 +56,9 @@ public class TenantBalanceServiceImpl implements TenantBalanceService {
|
|||||||
@Resource
|
@Resource
|
||||||
private TenantMapper tenantMapper;
|
private TenantMapper tenantMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TenantAgencyPackageMapper tenantAgencyPackageMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createTenantBalance(TenantBalanceSaveReqVO createReqVO) {
|
public Long createTenantBalance(TenantBalanceSaveReqVO createReqVO) {
|
||||||
// 插入
|
// 插入
|
||||||
@@ -295,20 +300,56 @@ public class TenantBalanceServiceImpl implements TenantBalanceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean consumption(TenantBalanceConsumptionReqVO consumptionReqVO) {
|
public Boolean consumption(Long PackageId, Long targetTenantId,String remark) {
|
||||||
|
|
||||||
Long tenantId = TenantContextHolder.getTenantId();
|
Long tenantId = TenantContextHolder.getTenantId();
|
||||||
// TenantBalanceDO tenantBalance = tenantBalanceMapper.selectById(tenantId);
|
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
|
||||||
// if (tenantBalance == null) {
|
|
||||||
// throw exception(TENANT_WALLET_NOT_EXISTS);
|
String consumption = BizNoGenerator.generate("CONSUMPTION");
|
||||||
// }
|
String order = BizNoGenerator.generate("ORDER");
|
||||||
// if (tenantBalance.getBalance() < consumptionReqVO.getAmount()) {
|
|
||||||
// throw exception(TENANT_WALLET_NOT_ENOUGH);
|
// 从数据库中查询租户余额
|
||||||
// }
|
TenantBalanceDO tenantBalance = tenantBalanceMapper.selectById(tenantId);
|
||||||
// Integer updateCount = tenantBalanceMapper.updateBalanceWithVersion(tenantId, -consumptionReqVO.getAmount(), tenantBalance.getVersion());
|
if (tenantBalance == null) {
|
||||||
// if (updateCount == 0) {
|
throw exception(TENANT_WALLET_NOT_EXISTS);
|
||||||
// throw exception(TENANT_BALANCE_CONSUMPTION_OPERATION_ERROR);
|
}
|
||||||
// }
|
// 从数据库中查询套餐信息
|
||||||
|
TenantAgencyPackageDO tenantAgencyPackageDO = tenantAgencyPackageMapper.selectById(PackageId);
|
||||||
|
if (tenantAgencyPackageDO == null) {
|
||||||
|
throw exception(TENANT_AGENCY_PACKAGE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
// 检查租户余额是否足够
|
||||||
|
if (tenantBalance.getBalance() < tenantAgencyPackageDO.getPrice()) {
|
||||||
|
throw exception(TENANT_BALANCE_BALANCE_NOT_ENOUGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer tenantBalanceDOVersion = tenantBalance.getVersion();
|
||||||
|
|
||||||
|
Integer oldBalance = tenantBalance.getBalance();
|
||||||
|
// 更新租户余额
|
||||||
|
Integer updateCount = tenantBalanceMapper.updateBalanceWithVersion(tenantId, -tenantAgencyPackageDO.getPrice(), tenantBalanceDOVersion);
|
||||||
|
|
||||||
|
if (updateCount == 0) {
|
||||||
|
throw exception(TENANT_BALANCE_CONSUMPTION_OPERATION_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 消费积分变动记录
|
||||||
|
TenantPointsDO tenantPointsDO = new TenantPointsDO();
|
||||||
|
tenantPointsDO.setTenantId(tenantId); // 设置租户ID
|
||||||
|
tenantPointsDO.setPoints(-tenantAgencyPackageDO.getPrice()); // 设置变动积分(负数表示减少)
|
||||||
|
tenantPointsDO.setBalance(oldBalance - tenantAgencyPackageDO.getPrice()); // 设置变动后的余额
|
||||||
|
tenantPointsDO.setOperatorId(loginUserId); // 设置操作人ID
|
||||||
|
tenantPointsDO.setType(CONSUMPTION.getDesc()); // 设置交易类型为转账
|
||||||
|
tenantPointsDO.setDescription("给租户" + targetTenantId + "开通套餐" + tenantAgencyPackageDO.getName() + ",金额:" + tenantAgencyPackageDO.getPrice()); // 设置交易描述
|
||||||
|
tenantPointsDO.setTargetTenantId(targetTenantId); // 设置目标租户ID
|
||||||
|
tenantPointsDO.setBizNo(consumption); // 设置业务流水号
|
||||||
|
tenantPointsDO.setRemark(remark);
|
||||||
|
tenantPointsDO.setOrderId(order);
|
||||||
|
int tenantInsert = tenantPointsMapper.insert(tenantPointsDO); // 插入记录
|
||||||
|
if (tenantInsert == 0) {
|
||||||
|
throw exception(TENANT_BALANCE_CONSUMPTION_OPERATION_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user