From 0d57c0a5f8ea8c5fc464af9ce9d66d24ce371921 Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 24 Nov 2025 16:46:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E=E5=A5=97?= =?UTF-8?q?=E9=A4=90=E6=B6=88=E8=B4=B9=E4=B8=8E=E4=BD=99=E9=A2=9D=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为 TenantAgencyPackage 增加 validTenantPackage 校验方法 - 在 TenantBalanceService 中实现基于套餐的消费接口 - 新增租户余额消费失败错误码 TENANT_BALANCE_CONSUMPTION_OPERATION_ERROR - 将积分记录 orderId 类型由 Long 改为 String 以兼容业务流水号 - 消费时自动生成 CONSUMPTION/ORDER 业务编号并记录积分变动 --- .../vo/TenantPointsPageRespVO.java | 2 +- .../tenantpoints/vo/TenantPointsRespVO.java | 2 +- .../vo/TenantPointsSaveReqVO.java | 2 +- .../TenantAgencyPackageDO.java | 4 +- .../tenantpoints/TenantPointsDO.java | 2 +- .../system/enums/ErrorCodeConstants.java | 2 +- .../TenantAgencyPackageService.java | 3 + .../TenantAgencyPackageServiceImpl.java | 15 +++++ .../tenantbalance/TenantBalanceService.java | 2 +- .../TenantBalanceServiceImpl.java | 65 +++++++++++++++---- 10 files changed, 80 insertions(+), 19 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageRespVO.java index 65c1e4c..237e609 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageRespVO.java @@ -34,7 +34,7 @@ public class TenantPointsPageRespVO { @Schema(description = "订单 Id/业务单号", example = "84") @ExcelProperty("订单 Id/业务单号") - private Long orderId; + private String orderId; @Schema(description = "业务流水号(转账、订单等唯一标识)") @ExcelProperty("业务流水号(转账、订单等唯一标识)") diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsRespVO.java index 79b123b..a4ba572 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsRespVO.java @@ -34,7 +34,7 @@ public class TenantPointsRespVO { @Schema(description = "订单 Id/业务单号", example = "84") @ExcelProperty("订单 Id/业务单号") - private Long orderId; + private String orderId; @Schema(description = "业务流水号(转账、订单等唯一标识)") @ExcelProperty("业务流水号(转账、订单等唯一标识)") diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsSaveReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsSaveReqVO.java index d77520c..2afa813 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsSaveReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsSaveReqVO.java @@ -28,7 +28,7 @@ public class TenantPointsSaveReqVO { private String description; @Schema(description = "订单 Id/业务单号", example = "84") - private Long orderId; + private String orderId; @Schema(description = "业务流水号(转账、订单等唯一标识)") private String bizNo; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantagencypackage/TenantAgencyPackageDO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantagencypackage/TenantAgencyPackageDO.java index 6257d1a..668da28 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantagencypackage/TenantAgencyPackageDO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantagencypackage/TenantAgencyPackageDO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.*; import java.util.*; import java.time.LocalDateTime; @@ -42,7 +43,8 @@ public class TenantAgencyPackageDO extends BaseDO { /** * 关联的菜单编号 */ - private String menuIds; + @TableField(typeHandler = JacksonTypeHandler.class) + private Set menuIds; /** * 套餐天数 */ diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantpoints/TenantPointsDO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantpoints/TenantPointsDO.java index 04b6551..6383cdd 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantpoints/TenantPointsDO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantpoints/TenantPointsDO.java @@ -44,7 +44,7 @@ public class TenantPointsDO { /** * 订单 Id/业务单号 */ - private Long orderId; + private String orderId; /** * 业务流水号(转账、订单等唯一标识) */ diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index 645ef0f..6ec2d1a 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -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_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_CONSUMPTION_OPERATION_ERROR = new ErrorCode(1_003_017_013, "租户余额消费操作失败"); // ================= 租户套餐 1-003-018-000 ================== ErrorCode TENANT_AGENCY_PACKAGE_NOT_EXISTS = new ErrorCode(1_003_018_000, "代理租户套餐不存在"); diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageService.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageService.java index 99e782c..e44356c 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageService.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageService.java @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.system.service.tenantagencypackage; import java.util.*; import javax.validation.*; +import javax.validation.constraints.NotNull; + import cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO; @@ -58,4 +60,5 @@ public interface TenantAgencyPackageService { */ PageResult getTenantAgencyPackagePage(TenantAgencyPackagePageReqVO pageReqVO); + TenantAgencyPackageDO validTenantPackage(@NotNull(message = "租户套餐编号不能为空") Long packageId); } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageServiceImpl.java index 0174ca4..c179c63 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageServiceImpl.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.system.service.tenantagencypackage; 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 org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -85,4 +87,17 @@ public class TenantAgencyPackageServiceImpl implements TenantAgencyPackageServic 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; + } + } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceService.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceService.java index 6ee5372..2f9a376 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceService.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceService.java @@ -67,5 +67,5 @@ public interface TenantBalanceService { PageResult getSelfSubordinateTenantBalancePage(@Valid TenantBalancePageReqVO pageReqVO); - Boolean consumption(@Valid TenantBalanceConsumptionReqVO consumptionReqVO); + Boolean consumption(Long PackageId, Long targetTenantId,String remark); } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceServiceImpl.java index 0a01902..f687842 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceServiceImpl.java @@ -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.module.system.controller.admin.tenantbalance.vo.*; 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.tenantpoints.TenantPointsDO; 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.tenantagencypackage.TenantAgencyPackageMapper; 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.enums.logger.LoginResultEnum; @@ -54,6 +56,9 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { @Resource private TenantMapper tenantMapper; + @Resource + private TenantAgencyPackageMapper tenantAgencyPackageMapper; + @Override public Long createTenantBalance(TenantBalanceSaveReqVO createReqVO) { // 插入 @@ -295,20 +300,56 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { } @Override - public Boolean consumption(TenantBalanceConsumptionReqVO consumptionReqVO) { + public Boolean consumption(Long PackageId, Long targetTenantId,String remark) { Long tenantId = TenantContextHolder.getTenantId(); -// TenantBalanceDO tenantBalance = tenantBalanceMapper.selectById(tenantId); -// if (tenantBalance == null) { -// throw exception(TENANT_WALLET_NOT_EXISTS); -// } -// if (tenantBalance.getBalance() < consumptionReqVO.getAmount()) { -// throw exception(TENANT_WALLET_NOT_ENOUGH); -// } -// Integer updateCount = tenantBalanceMapper.updateBalanceWithVersion(tenantId, -consumptionReqVO.getAmount(), tenantBalance.getVersion()); -// if (updateCount == 0) { -// throw exception(TENANT_BALANCE_CONSUMPTION_OPERATION_ERROR); -// } + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + + String consumption = BizNoGenerator.generate("CONSUMPTION"); + String order = BizNoGenerator.generate("ORDER"); + + // 从数据库中查询租户余额 + TenantBalanceDO tenantBalance = tenantBalanceMapper.selectById(tenantId); + if (tenantBalance == null) { + throw exception(TENANT_WALLET_NOT_EXISTS); + } + // 从数据库中查询套餐信息 + 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;