From 6e0f41e661125159522a334f9fdfd38862b4621e Mon Sep 17 00:00:00 2001 From: ziin Date: Tue, 18 Nov 2025 19:21:44 +0800 Subject: [PATCH 01/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E7=A7=9F=E6=88=B7=E6=9F=A5=E8=AF=A2=E4=B8=8B?= =?UTF-8?q?=E5=B1=9E=E7=A7=9F=E6=88=B7=E5=88=86=E9=A1=B5=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/tenant/TenantController.java | 12 ++++++++++++ .../admin/tenant/vo/tenant/TenantPageReqVO.java | 3 +++ .../admin/tenant/vo/tenant/TenantRespVO.java | 2 ++ .../system/dal/dataobject/tenant/TenantDO.java | 10 ++++++++++ .../system/dal/mysql/tenant/TenantMapper.java | 14 ++++++++++++++ .../system/service/tenant/TenantService.java | 1 + .../system/service/tenant/TenantServiceImpl.java | 9 +++++++++ 7 files changed, 51 insertions(+) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java index 76c3b52..edde75d 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java @@ -124,4 +124,16 @@ public class TenantController { BeanUtils.toBean(list, TenantRespVO.class)); } + +// 以下是控制代理租户的租户查询 +// ---------------------------------------------------------------------------------- + + @GetMapping("/page_self") + @Operation(summary = "代理获得自己下属租户分页") + @PreAuthorize("@ss.hasPermission('system:tenant:query-self')") + public CommonResult> getSelfTenantPage(@Valid TenantPageReqVO pageVO) { + PageResult pageResult = tenantService.getSelfTenantPage(pageVO); + return success(BeanUtils.toBean(pageResult, TenantRespVO.class)); + } + } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java index 73a177c..5fcca5b 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java @@ -47,4 +47,7 @@ public class TenantPageReqVO extends PageParam { @Schema private String remark; + + @Schema(description = "父租户Id") + private Long parentId; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java index 44b4c0b..72d28d8 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java @@ -64,4 +64,6 @@ public class TenantRespVO { @Schema(description = "备注", example = "备注") private String remark; + @Schema(description = "上级租户 Id", example = "1024") + private Long parentId; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java index 15085f1..d998f96 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java @@ -87,7 +87,17 @@ public class TenantDO extends BaseDO { /** * 账号数量 */ + private Integer accountCount; + /** + * 上级租户 Id + */ + private Long parentId; + + /** + * 备注 + */ + private String remark; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java index 6cf149d..9d54788 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java @@ -63,4 +63,18 @@ public interface TenantMapper extends BaseMapperX { } + default PageResult selectSelfPage(TenantPageReqVO reqVO){ + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(TenantDO::getParentId, reqVO.getParentId()) + .likeIfPresent(TenantDO::getName, reqVO.getName()) + .likeIfPresent(TenantDO::getContactName, reqVO.getContactName()) + .likeIfPresent(TenantDO::getContactMobile, reqVO.getContactMobile()) + .eqIfPresent(TenantDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(TenantDO::getCreateTime, reqVO.getCreateTime()) + .betweenIfPresent(TenantDO::getAiExpireTime, reqVO.getAiExpireTime()) + .betweenIfPresent(TenantDO::getExpireTime, reqVO.getExpireTime()) + .betweenIfPresent(TenantDO::getBrotherExpireTime, reqVO.getBrotherExpireTime()) + .likeIfPresent(TenantDO::getRemark, reqVO.getRemark()) + .orderByDesc(TenantDO::getId)); + } } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java index 96af6bc..e77b15e 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java @@ -135,4 +135,5 @@ public interface TenantService { */ void validTenant(Long id); + PageResult getSelfTenantPage(@Valid TenantPageReqVO pageVO); } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index 956b957..2f1fffa 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -95,6 +95,13 @@ public class TenantServiceImpl implements TenantService { } } + @Override + public PageResult getSelfTenantPage(TenantPageReqVO pageVO) { + Long tenantId = TenantContextHolder.getTenantId(); + pageVO.setParentId(tenantId); + return tenantMapper.selectSelfPage(pageVO); + } + @Override @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换 @DataPermission(enable = false) // 参见 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1154 说明 @@ -108,6 +115,8 @@ public class TenantServiceImpl implements TenantService { // 创建租户 TenantDO tenant = BeanUtils.toBean(createReqVO, TenantDO.class); + Long tenantId = TenantContextHolder.getTenantId(); + tenant.setParentId(tenantId); tenantMapper.insert(tenant); // 创建租户的管理员 TenantUtils.execute(tenant.getId(), () -> { From c75df4743d6a5f3f3841994677c19559bf6088c8 Mon Sep 17 00:00:00 2001 From: ziin Date: Wed, 19 Nov 2025 20:39:29 +0800 Subject: [PATCH 02/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E7=A7=AF=E5=88=86=E7=AE=A1=E7=90=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增租户积分实体、Mapper、Service及Controller全套代码,并补充对应错误码TENANT_POINTS_NOT_EXISTS。 --- .../tenantpoints/TenantPointsController.java | 104 ++++++++++++++++++ .../vo/TenantPointsPageReqVO.java | 43 ++++++++ .../tenantpoints/vo/TenantPointsRespVO.java | 55 +++++++++ .../vo/TenantPointsSaveReqVO.java | 46 ++++++++ .../tenantpoints/TenantPointsDO.java | 67 +++++++++++ .../tenantpoints/TenantPointsMapper.java | 34 ++++++ .../system/enums/ErrorCodeConstants.java | 3 + .../tenantpoints/TenantPointsService.java | 62 +++++++++++ .../tenantpoints/TenantPointsServiceImpl.java | 92 ++++++++++++++++ .../resources/mapper/TenantPointsMapper.xml | 12 ++ 10 files changed, 518 insertions(+) create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsRespVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsSaveReqVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantpoints/TenantPointsDO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java create mode 100644 yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java new file mode 100644 index 0000000..a01cb76 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantpoints; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.system.controller.admin.tenantpoints.vo.*; +import cn.iocoder.yudao.module.system.dal.dataobject.tenantpoints.TenantPointsDO; +import cn.iocoder.yudao.module.system.service.tenantpoints.TenantPointsService; + +@Tag(name = "管理后台 - 租户积分记录") +@RestController +@RequestMapping("/system/tenant-points") +@Validated +public class TenantPointsController { + + @Resource + private TenantPointsService tenantPointsService; + + @PostMapping("/create") + @Operation(summary = "创建租户积分记录") + @PreAuthorize("@ss.hasPermission('system:tenant-points:create')") + public CommonResult createTenantPoints(@Valid @RequestBody TenantPointsSaveReqVO createReqVO) { + return success(tenantPointsService.createTenantPoints(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新租户积分记录") + @PreAuthorize("@ss.hasPermission('system:tenant-points:update')") + public CommonResult updateTenantPoints(@Valid @RequestBody TenantPointsSaveReqVO updateReqVO) { + tenantPointsService.updateTenantPoints(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除租户积分记录") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('system:tenant-points:delete')") + public CommonResult deleteTenantPoints(@RequestParam("id") Long id) { + tenantPointsService.deleteTenantPoints(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Parameter(name = "ids", description = "编号", required = true) + @Operation(summary = "批量删除租户积分记录") + @PreAuthorize("@ss.hasPermission('system:tenant-points:delete')") + public CommonResult deleteTenantPointsList(@RequestParam("ids") List ids) { + tenantPointsService.deleteTenantPointsListByIds(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得租户积分记录") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('system:tenant-points:query')") + public CommonResult getTenantPoints(@RequestParam("id") Long id) { + TenantPointsDO tenantPoints = tenantPointsService.getTenantPoints(id); + return success(BeanUtils.toBean(tenantPoints, TenantPointsRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得租户积分记录分页") + @PreAuthorize("@ss.hasPermission('system:tenant-points:query')") + public CommonResult> getTenantPointsPage(@Valid TenantPointsPageReqVO pageReqVO) { + PageResult pageResult = tenantPointsService.getTenantPointsPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, TenantPointsRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出租户积分记录 Excel") + @PreAuthorize("@ss.hasPermission('system:tenant-points:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTenantPointsExcel(@Valid TenantPointsPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = tenantPointsService.getTenantPointsPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "租户积分记录.xls", "数据", TenantPointsRespVO.class, + BeanUtils.toBean(list, TenantPointsRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java new file mode 100644 index 0000000..9162fde --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantpoints.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 租户积分记录分页 Request VO") +@Data +public class TenantPointsPageReqVO extends PageParam { + + @Schema(description = "本次变动点数,正加负减") + private Integer points; + + @Schema(description = "变动后余额快照(冗余)") + private Integer balance; + + @Schema(description = "变动类型,如 RECHARGE, CONSUME, TRANSFER_OUT, TRANSFER_IN", example = "1") + private String type; + + @Schema(description = "变动描述", example = "随便") + private String description; + + @Schema(description = "订单 Id/业务单号", example = "84") + private Long orderId; + + @Schema(description = "业务流水号(转账、订单等唯一标识)") + private String bizNo; + + @Schema(description = "操作人 Id", example = "8171") + private Long operatorId; + + @Schema(description = "目标租户 Id(转账使用)", example = "18731") + private Long targetTenantId; + + @Schema(description = "创建时间") + private LocalDateTime createdAt; + +} \ No newline at end of file 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 new file mode 100644 index 0000000..79b123b --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsRespVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantpoints.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 租户积分记录 Response VO") +@Data +@ExcelIgnoreUnannotated +public class TenantPointsRespVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "16587") + @ExcelProperty("主键") + private Long id; + + @Schema(description = "本次变动点数,正加负减", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("本次变动点数,正加负减") + private Integer points; + + @Schema(description = "变动后余额快照(冗余)") + @ExcelProperty("变动后余额快照(冗余)") + private Integer balance; + + @Schema(description = "变动类型,如 RECHARGE, CONSUME, TRANSFER_OUT, TRANSFER_IN", example = "1") + @ExcelProperty("变动类型,如 RECHARGE, CONSUME, TRANSFER_OUT, TRANSFER_IN") + private String type; + + @Schema(description = "变动描述", example = "随便") + @ExcelProperty("变动描述") + private String description; + + @Schema(description = "订单 Id/业务单号", example = "84") + @ExcelProperty("订单 Id/业务单号") + private Long orderId; + + @Schema(description = "业务流水号(转账、订单等唯一标识)") + @ExcelProperty("业务流水号(转账、订单等唯一标识)") + private String bizNo; + + @Schema(description = "操作人 Id", example = "8171") + @ExcelProperty("操作人 Id") + private Long operatorId; + + @Schema(description = "目标租户 Id(转账使用)", example = "18731") + @ExcelProperty("目标租户 Id(转账使用)") + private Long targetTenantId; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createdAt; + +} \ No newline at end of file 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 new file mode 100644 index 0000000..d77520c --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsSaveReqVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantpoints.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 租户积分记录新增/修改 Request VO") +@Data +public class TenantPointsSaveReqVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "16587") + private Long id; + + @Schema(description = "本次变动点数,正加负减", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "本次变动点数,正加负减不能为空") + private Integer points; + + @Schema(description = "变动后余额快照(冗余)") + private Integer balance; + + @Schema(description = "变动类型,如 RECHARGE, CONSUME, TRANSFER_OUT, TRANSFER_IN", example = "1") + private String type; + + @Schema(description = "变动描述", example = "随便") + private String description; + + @Schema(description = "订单 Id/业务单号", example = "84") + private Long orderId; + + @Schema(description = "业务流水号(转账、订单等唯一标识)") + private String bizNo; + + @Schema(description = "操作人 Id", example = "8171") + private Long operatorId; + + @Schema(description = "目标租户 Id(转账使用)", example = "18731") + private Long targetTenantId; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "创建时间不能为空") + private LocalDateTime createdAt; + +} \ No newline at end of file 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 new file mode 100644 index 0000000..68e4abd --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantpoints/TenantPointsDO.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.system.dal.dataobject.tenantpoints; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 租户积分记录 DO + * + * @author 总后台 + */ +@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 { + + /** + * 主键 + */ + @TableId + private Long id; + /** + * 本次变动点数,正加负减 + */ + private Integer points; + /** + * 变动后余额快照(冗余) + */ + private Integer balance; + /** + * 变动类型,如 RECHARGE, CONSUME, TRANSFER_OUT, TRANSFER_IN + */ + private String type; + /** + * 变动描述 + */ + private String description; + /** + * 订单 Id/业务单号 + */ + private Long orderId; + /** + * 业务流水号(转账、订单等唯一标识) + */ + private String bizNo; + /** + * 操作人 Id + */ + private Long operatorId; + /** + * 目标租户 Id(转账使用) + */ + private Long targetTenantId; + /** + * 创建时间 + */ + private LocalDateTime createdAt; + + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java new file mode 100644 index 0000000..a04eb84 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.system.dal.mysql.tenantpoints; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.system.dal.dataobject.tenantpoints.TenantPointsDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.system.controller.admin.tenantpoints.vo.*; + +/** + * 租户积分记录 Mapper + * + * @author 总后台 + */ +@Mapper +public interface TenantPointsMapper extends BaseMapperX { + + default PageResult selectPage(TenantPointsPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(TenantPointsDO::getPoints, reqVO.getPoints()) + .eqIfPresent(TenantPointsDO::getBalance, reqVO.getBalance()) + .eqIfPresent(TenantPointsDO::getType, reqVO.getType()) + .eqIfPresent(TenantPointsDO::getDescription, reqVO.getDescription()) + .eqIfPresent(TenantPointsDO::getOrderId, reqVO.getOrderId()) + .eqIfPresent(TenantPointsDO::getBizNo, reqVO.getBizNo()) + .eqIfPresent(TenantPointsDO::getOperatorId, reqVO.getOperatorId()) + .eqIfPresent(TenantPointsDO::getTargetTenantId, reqVO.getTargetTenantId()) + .eqIfPresent(TenantPointsDO::getCreatedAt, reqVO.getCreatedAt()) + .orderByDesc(TenantPointsDO::getId)); + } + +} \ No newline at end of file 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 c89a5dc..cc9bb84 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 @@ -116,6 +116,9 @@ public interface ErrorCodeConstants { ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1_002_016_002, "名字为【{}】的租户套餐已被禁用"); ErrorCode TENANT_PACKAGE_NAME_DUPLICATE = new ErrorCode(1_002_016_003, "已经存在该名字的租户套餐"); +// ========== 租户套餐 1-002-017-000 ========== + ErrorCode TENANT_POINTS_NOT_EXISTS = new ErrorCode(1_002_017_000, "租户积分不存在"); + // ========== 社交用户 1-002-018-000 ========== ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1_002_018_000, "社交授权失败,原因是:{}"); ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1_002_018_001, "社交授权失败,找不到对应的用户"); diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java new file mode 100644 index 0000000..626fb3c --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.system.service.tenantpoints; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.system.controller.admin.tenantpoints.vo.*; +import cn.iocoder.yudao.module.system.dal.dataobject.tenantpoints.TenantPointsDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 租户积分记录 Service 接口 + * + * @author 总后台 + */ +public interface TenantPointsService { + + /** + * 创建租户积分记录 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTenantPoints(@Valid TenantPointsSaveReqVO createReqVO); + + /** + * 更新租户积分记录 + * + * @param updateReqVO 更新信息 + */ + void updateTenantPoints(@Valid TenantPointsSaveReqVO updateReqVO); + + /** + * 删除租户积分记录 + * + * @param id 编号 + */ + void deleteTenantPoints(Long id); + + /** + * 批量删除租户积分记录 + * + * @param ids 编号 + */ + void deleteTenantPointsListByIds(List ids); + + /** + * 获得租户积分记录 + * + * @param id 编号 + * @return 租户积分记录 + */ + TenantPointsDO getTenantPoints(Long id); + + /** + * 获得租户积分记录分页 + * + * @param pageReqVO 分页查询 + * @return 租户积分记录分页 + */ + PageResult getTenantPointsPage(TenantPointsPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java new file mode 100644 index 0000000..6a5b3aa --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.system.service.tenantpoints; + +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.tenantpoints.vo.*; +import cn.iocoder.yudao.module.system.dal.dataobject.tenantpoints.TenantPointsDO; +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.dal.mysql.tenantpoints.TenantPointsMapper; + +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.*; + +/** + * 租户积分记录 Service 实现类 + * + * @author 总后台 + */ +@Service +@Validated +public class TenantPointsServiceImpl implements TenantPointsService { + + @Resource + private TenantPointsMapper tenantPointsMapper; + + @Override + public Long createTenantPoints(TenantPointsSaveReqVO createReqVO) { + // 插入 + TenantPointsDO tenantPoints = BeanUtils.toBean(createReqVO, TenantPointsDO.class); + tenantPointsMapper.insert(tenantPoints); + // 返回 + return tenantPoints.getId(); + } + + @Override + public void updateTenantPoints(TenantPointsSaveReqVO updateReqVO) { + // 校验存在 + validateTenantPointsExists(updateReqVO.getId()); + // 更新 + TenantPointsDO updateObj = BeanUtils.toBean(updateReqVO, TenantPointsDO.class); + tenantPointsMapper.updateById(updateObj); + } + + @Override + public void deleteTenantPoints(Long id) { + // 校验存在 + validateTenantPointsExists(id); + // 删除 + tenantPointsMapper.deleteById(id); + } + + @Override + public void deleteTenantPointsListByIds(List ids) { + // 校验存在 + validateTenantPointsExists(ids); + // 删除 + tenantPointsMapper.deleteByIds(ids); + } + + private void validateTenantPointsExists(List ids) { + List list = tenantPointsMapper.selectByIds(ids); + if (CollUtil.isEmpty(list) || list.size() != ids.size()) { + throw exception(TENANT_POINTS_NOT_EXISTS); + } + } + + private void validateTenantPointsExists(Long id) { + if (tenantPointsMapper.selectById(id) == null) { + throw exception(TENANT_POINTS_NOT_EXISTS); + } + } + + @Override + public TenantPointsDO getTenantPoints(Long id) { + return tenantPointsMapper.selectById(id); + } + + @Override + public PageResult getTenantPointsPage(TenantPointsPageReqVO pageReqVO) { + return tenantPointsMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml b/yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml new file mode 100644 index 0000000..94a3d7d --- /dev/null +++ b/yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file From f00e250be93e3f9180327bce7cdf97fb56416852 Mon Sep 17 00:00:00 2001 From: ziin Date: Wed, 19 Nov 2025 21:04:06 +0800 Subject: [PATCH 03/37] =?UTF-8?q?feat(tenant-balance):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E7=A7=9F=E6=88=B7=E4=BD=99=E9=A2=9D=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增租户余额实体、Mapper、Service、Controller 及对应 VO,支持余额分页查询、保存与错误码定义。 --- .../TenantBalanceController.java | 104 ++++++++++++++++++ .../vo/TenantBalancePageReqVO.java | 25 +++++ .../tenantbalance/vo/TenantBalanceRespVO.java | 27 +++++ .../vo/TenantBalanceSaveReqVO.java | 29 +++++ .../tenantbalance/TenantBalanceDO.java | 39 +++++++ .../tenantbalance/TenantBalanceMapper.java | 28 +++++ .../system/enums/ErrorCodeConstants.java | 4 + .../tenantbalance/TenantBalanceService.java | 62 +++++++++++ .../TenantBalanceServiceImpl.java | 92 ++++++++++++++++ .../resources/mapper/TenantBalanceMapper.xml | 12 ++ 10 files changed, 422 insertions(+) create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceSaveReqVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceService.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceServiceImpl.java create mode 100644 yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java new file mode 100644 index 0000000..a4d8c8a --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantbalance; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.*; +import cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance.TenantBalanceDO; +import cn.iocoder.yudao.module.system.service.tenantbalance.TenantBalanceService; + +@Tag(name = "管理后台 - 租户余额") +@RestController +@RequestMapping("/system/tenant-balance") +@Validated +public class TenantBalanceController { + + @Resource + private TenantBalanceService tenantBalanceService; + + @PostMapping("/create") + @Operation(summary = "创建租户余额") + @PreAuthorize("@ss.hasPermission('system:tenant-balance:create')") + public CommonResult createTenantBalance(@Valid @RequestBody TenantBalanceSaveReqVO createReqVO) { + return success(tenantBalanceService.createTenantBalance(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新租户余额") + @PreAuthorize("@ss.hasPermission('system:tenant-balance:update')") + public CommonResult updateTenantBalance(@Valid @RequestBody TenantBalanceSaveReqVO updateReqVO) { + tenantBalanceService.updateTenantBalance(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除租户余额") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('system:tenant-balance:delete')") + public CommonResult deleteTenantBalance(@RequestParam("id") Long id) { + tenantBalanceService.deleteTenantBalance(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Parameter(name = "ids", description = "编号", required = true) + @Operation(summary = "批量删除租户余额") + @PreAuthorize("@ss.hasPermission('system:tenant-balance:delete')") + public CommonResult deleteTenantBalanceList(@RequestParam("ids") List ids) { + tenantBalanceService.deleteTenantBalanceListByIds(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得租户余额") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('system:tenant-balance:query')") + public CommonResult getTenantBalance(@RequestParam("id") Long id) { + TenantBalanceDO tenantBalance = tenantBalanceService.getTenantBalance(id); + return success(BeanUtils.toBean(tenantBalance, TenantBalanceRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得租户余额分页") + @PreAuthorize("@ss.hasPermission('system:tenant-balance:query')") + public CommonResult> getTenantBalancePage(@Valid TenantBalancePageReqVO pageReqVO) { + PageResult pageResult = tenantBalanceService.getTenantBalancePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, TenantBalanceRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出租户余额 Excel") + @PreAuthorize("@ss.hasPermission('system:tenant-balance:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTenantBalanceExcel(@Valid TenantBalancePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = tenantBalanceService.getTenantBalancePage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "租户余额.xls", "数据", TenantBalanceRespVO.class, + BeanUtils.toBean(list, TenantBalanceRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java new file mode 100644 index 0000000..4dff99d --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 租户余额分页 Request VO") +@Data +public class TenantBalancePageReqVO extends PageParam { + + @Schema(description = "当前积分余额") + private Integer balance; + + @Schema(description = "乐观锁版本号") + private Integer version; + + @Schema(description = "更新时间") + private LocalDateTime updatedAt; + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java new file mode 100644 index 0000000..6458986 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 租户余额 Response VO") +@Data +@ExcelIgnoreUnannotated +public class TenantBalanceRespVO { + + @Schema(description = "当前积分余额", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("当前积分余额") + private Integer balance; + + @Schema(description = "乐观锁版本号", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("乐观锁版本号") + private Integer version; + + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("更新时间") + private LocalDateTime updatedAt; + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceSaveReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceSaveReqVO.java new file mode 100644 index 0000000..29ba2f5 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceSaveReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 租户余额新增/修改 Request VO") +@Data +public class TenantBalanceSaveReqVO { + + @Schema(description = "租户 Id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19954") + private Long id; + + @Schema(description = "当前积分余额", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "当前积分余额不能为空") + private Integer balance; + + @Schema(description = "乐观锁版本号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "乐观锁版本号不能为空") + private Integer version; + + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "更新时间不能为空") + private LocalDateTime updatedAt; + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java new file mode 100644 index 0000000..5f85cff --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 租户余额 DO + * + * @author 总后台 + */ +@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 { + + private Long id; + /** + * 当前积分余额 + */ + private Integer balance; + /** + * 乐观锁版本号 + */ + private Integer version; + /** + * 更新时间 + */ + private LocalDateTime updatedAt; + + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java new file mode 100644 index 0000000..8cfcfa2 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.dal.mysql.tenantbalance; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance.TenantBalanceDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.*; + +/** + * 租户余额 Mapper + * + * @author 总后台 + */ +@Mapper +public interface TenantBalanceMapper extends BaseMapperX { + + default PageResult selectPage(TenantBalancePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(TenantBalanceDO::getBalance, reqVO.getBalance()) + .eqIfPresent(TenantBalanceDO::getVersion, reqVO.getVersion()) + .eqIfPresent(TenantBalanceDO::getUpdatedAt, reqVO.getUpdatedAt()) + .orderByDesc(TenantBalanceDO::getId)); + } + +} \ No newline at end of file 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 cc9bb84..e430946 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 @@ -119,6 +119,10 @@ public interface ErrorCodeConstants { // ========== 租户套餐 1-002-017-000 ========== ErrorCode TENANT_POINTS_NOT_EXISTS = new ErrorCode(1_002_017_000, "租户积分不存在"); +// ========== 租户余额 1-003-017-000 ========== + ErrorCode TENANT_BALANCE_NOT_EXISTS = new ErrorCode(1_003_017_000, "租户余额不存在"); + + // ========== 社交用户 1-002-018-000 ========== ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1_002_018_000, "社交授权失败,原因是:{}"); ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1_002_018_001, "社交授权失败,找不到对应的用户"); 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 new file mode 100644 index 0000000..581682a --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceService.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.system.service.tenantbalance; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.*; +import cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance.TenantBalanceDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 租户余额 Service 接口 + * + * @author 总后台 + */ +public interface TenantBalanceService { + + /** + * 创建租户余额 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTenantBalance(@Valid TenantBalanceSaveReqVO createReqVO); + + /** + * 更新租户余额 + * + * @param updateReqVO 更新信息 + */ + void updateTenantBalance(@Valid TenantBalanceSaveReqVO updateReqVO); + + /** + * 删除租户余额 + * + * @param id 编号 + */ + void deleteTenantBalance(Long id); + + /** + * 批量删除租户余额 + * + * @param ids 编号 + */ + void deleteTenantBalanceListByIds(List ids); + + /** + * 获得租户余额 + * + * @param id 编号 + * @return 租户余额 + */ + TenantBalanceDO getTenantBalance(Long id); + + /** + * 获得租户余额分页 + * + * @param pageReqVO 分页查询 + * @return 租户余额分页 + */ + PageResult getTenantBalancePage(TenantBalancePageReqVO pageReqVO); + +} \ 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 new file mode 100644 index 0000000..7f4958b --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantbalance/TenantBalanceServiceImpl.java @@ -0,0 +1,92 @@ +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.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.dal.mysql.tenantbalance.TenantBalanceMapper; + +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.*; + +/** + * 租户余额 Service 实现类 + * + * @author 总后台 + */ +@Service +@Validated +public class TenantBalanceServiceImpl implements TenantBalanceService { + + @Resource + private TenantBalanceMapper tenantBalanceMapper; + + @Override + public Long createTenantBalance(TenantBalanceSaveReqVO createReqVO) { + // 插入 + TenantBalanceDO tenantBalance = BeanUtils.toBean(createReqVO, TenantBalanceDO.class); + tenantBalanceMapper.insert(tenantBalance); + // 返回 + return tenantBalance.getId(); + } + + @Override + public void updateTenantBalance(TenantBalanceSaveReqVO updateReqVO) { + // 校验存在 + validateTenantBalanceExists(updateReqVO.getId()); + // 更新 + TenantBalanceDO updateObj = BeanUtils.toBean(updateReqVO, TenantBalanceDO.class); + tenantBalanceMapper.updateById(updateObj); + } + + @Override + public void deleteTenantBalance(Long id) { + // 校验存在 + validateTenantBalanceExists(id); + // 删除 + tenantBalanceMapper.deleteById(id); + } + + @Override + public void deleteTenantBalanceListByIds(List ids) { + // 校验存在 + validateTenantBalanceExists(ids); + // 删除 + tenantBalanceMapper.deleteByIds(ids); + } + + private void validateTenantBalanceExists(List ids) { + List list = tenantBalanceMapper.selectByIds(ids); + if (CollUtil.isEmpty(list) || list.size() != ids.size()) { + throw exception(TENANT_BALANCE_NOT_EXISTS); + } + } + + private void validateTenantBalanceExists(Long id) { + if (tenantBalanceMapper.selectById(id) == null) { + throw exception(TENANT_BALANCE_NOT_EXISTS); + } + } + + @Override + public TenantBalanceDO getTenantBalance(Long id) { + return tenantBalanceMapper.selectById(id); + } + + @Override + public PageResult getTenantBalancePage(TenantBalancePageReqVO pageReqVO) { + return tenantBalanceMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml b/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml new file mode 100644 index 0000000..fca190a --- /dev/null +++ b/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file From ebf071b225f2357bd118791c12cc49484c4c66ee Mon Sep 17 00:00:00 2001 From: ziin Date: Wed, 19 Nov 2025 22:10:39 +0800 Subject: [PATCH 04/37] =?UTF-8?q?feat(tenant-balance):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=90=8E=E5=8F=B0=E7=BB=99=E7=A7=9F=E6=88=B7=E5=85=85?= =?UTF-8?q?=E5=80=BC=E4=BD=99=E9=A2=9D=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TenantBalanceController.java | 8 +++ .../vo/TenantBalanceAddReqVO.java | 23 +++++++ .../tenantbalance/TenantBalanceDO.java | 3 +- .../tenantpoints/TenantPointsDO.java | 6 +- .../tenantbalance/TenantBalanceMapper.java | 5 ++ .../system/enums/balance/BalanceEnum.java | 27 ++++++++ .../tenantbalance/TenantBalanceService.java | 1 + .../TenantBalanceServiceImpl.java | 69 +++++++++++++++---- .../module/system/util/BizNoGenerator.java | 34 +++++++++ .../src/main/resources/application.yaml | 2 + 10 files changed, 160 insertions(+), 18 deletions(-) create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/util/BizNoGenerator.java diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java index a4d8c8a..f92b5e5 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java @@ -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 addTenantBalance(@Valid @RequestBody TenantBalanceAddReqVO addReqVO) { + tenantBalanceService.addTenantBalance(addReqVO); + return success(true); + } } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java new file mode 100644 index 0000000..1a99a4f --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java @@ -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; +} diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java index 5f85cff..3c6a707 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java @@ -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; /** 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 68e4abd..25f7d66 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 @@ -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; } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java index 8cfcfa2..e0feea7 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java @@ -25,4 +25,9 @@ public interface TenantBalanceMapper extends BaseMapperX { .orderByDesc(TenantBalanceDO::getId)); } + default Integer updateBalanceWithVersion(TenantBalanceDO updateObj){ + return update(updateObj, new LambdaQueryWrapperX() + .eq(TenantBalanceDO::getId, updateObj.getId()) + .eq(TenantBalanceDO::getVersion, updateObj.getVersion())); + } } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java new file mode 100644 index 0000000..6d11b12 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java @@ -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; + + + + +} 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 581682a..7582a02 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 @@ -59,4 +59,5 @@ public interface TenantBalanceService { */ PageResult getTenantBalancePage(TenantBalancePageReqVO pageReqVO); + void addTenantBalance(@Valid TenantBalanceAddReqVO updateReqVO); } \ 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 7f4958b..2cbc6a9 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 @@ -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); + } + } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/util/BizNoGenerator.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/util/BizNoGenerator.java new file mode 100644 index 0000000..3e79919 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/util/BizNoGenerator.java @@ -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); + } +} diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 2a97a81..842c034 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -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 From 3466996f07d5a1aa620561e2dade35b0bf2e1e02 Mon Sep 17 00:00:00 2001 From: ziin Date: Thu, 20 Nov 2025 18:26:35 +0800 Subject: [PATCH 05/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E4=BD=99=E9=A2=9D=E7=89=88=E6=9C=AC=E5=8F=B7?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E4=B8=8E=E5=85=85=E5=80=BC=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 补充乐观锁场景下的版本号、余额异常及充值失败专用错误码,为后续余额并发更新提供精确异常定位。 --- .../tenantbalance/vo/TenantBalanceRespVO.java | 4 ++++ .../tenantbalance/TenantBalanceMapper.java | 18 ++++++++++++++---- .../system/enums/ErrorCodeConstants.java | 4 ++++ .../TenantBalanceServiceImpl.java | 18 ++++++++++++++---- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java index 6458986..6cbc852 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java @@ -12,6 +12,10 @@ import com.alibaba.excel.annotation.*; @ExcelIgnoreUnannotated public class TenantBalanceRespVO { + @Schema(description = "租户 Id", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("租户 Id") + private Long id; + @Schema(description = "当前积分余额", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("当前积分余额") private Integer balance; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java index e0feea7..9b0a202 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java @@ -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.mapper.BaseMapperX; 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 cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.*; @@ -25,9 +26,18 @@ public interface TenantBalanceMapper extends BaseMapperX { .orderByDesc(TenantBalanceDO::getId)); } - default Integer updateBalanceWithVersion(TenantBalanceDO updateObj){ - return update(updateObj, new LambdaQueryWrapperX() - .eq(TenantBalanceDO::getId, updateObj.getId()) - .eq(TenantBalanceDO::getVersion, updateObj.getVersion())); + default Integer updateBalanceWithVersion(Long id, int amount, Integer oldVersion) { + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + + 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); } } \ No newline at end of file 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 e430946..337627e 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 @@ -121,6 +121,10 @@ public interface ErrorCodeConstants { // ========== 租户余额 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 ========== 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 2cbc6a9..a7e7ea5 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 @@ -4,6 +4,9 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.RandomUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.TenantBalancePageReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.TenantBalanceSaveReqVO; @@ -20,7 +23,7 @@ import javax.annotation.Resource; import java.util.List; 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; /** @@ -98,6 +101,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { @Override @Transactional(rollbackFor = Exception.class) public void addTenantBalance(TenantBalanceAddReqVO addReqVO) { + // 校验存在 if (tenantBalanceMapper.selectById(addReqVO.getId()) == null) { // 初始化余额为 0 @@ -118,16 +122,22 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { updateObj.setVersion(oldVersion); updateObj.setBalance(newBalance); - Integer updateCount = tenantBalanceMapper.updateBalanceWithVersion(updateObj); + Integer updateCount = tenantBalanceMapper.updateBalanceWithVersion(addReqVO.getId(), addReqVO.getAmount(), oldVersion); 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.setTenantId(addReqVO.getId()); tenantPointsDO.setPoints(addReqVO.getAmount()); tenantPointsDO.setBalance(newBalance); + tenantPointsDO.setOperatorId(loginUser.getId()); tenantPointsDO.setType(RECHARGE.getDesc()); // RECHARGE / BONUS / ... - tenantPointsDO.setDescription("后台加积分"); + tenantPointsDO.setDescription("后台变动积分"); tenantPointsDO.setBizNo(recharge); tenantPointsMapper.insert(tenantPointsDO); } From 78b6f5624be07ec4e235b63f7d7f30f08e9b0942 Mon Sep 17 00:00:00 2001 From: ziin Date: Thu, 20 Nov 2025 19:15:31 +0800 Subject: [PATCH 06/37] =?UTF-8?q?feat(system):=20=E7=A7=9F=E6=88=B7?= =?UTF-8?q?=E4=BD=99=E9=A2=9D=E5=88=97=E8=A1=A8=E6=96=B0=E5=A2=9E=E7=A7=9F?= =?UTF-8?q?=E6=88=B7=E5=90=8D=E7=A7=B0=E5=AD=97=E6=AE=B5=E5=B9=B6=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=8F=98=E5=8A=A8=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在分页查询中联表返回租户名称,提升列表可读性 - 新增变动描述字段,支持充值等操作记录具体原因 - 优化 Mapper 与 Service 返回类型,统一使用 TenantBalanceRespVO --- .../tenantbalance/TenantBalanceController.java | 6 +++--- .../tenantbalance/vo/TenantBalanceAddReqVO.java | 4 ++++ .../tenantbalance/vo/TenantBalancePageReqVO.java | 3 +++ .../admin/tenantbalance/vo/TenantBalanceRespVO.java | 4 ++++ .../mysql/tenantbalance/TenantBalanceMapper.java | 5 +++++ .../service/tenantbalance/TenantBalanceService.java | 2 +- .../tenantbalance/TenantBalanceServiceImpl.java | 13 ++++++++----- .../main/resources/mapper/TenantBalanceMapper.xml | 12 ++++++++++++ 8 files changed, 40 insertions(+), 9 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java index f92b5e5..eb46482 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java @@ -84,8 +84,8 @@ public class TenantBalanceController { @Operation(summary = "获得租户余额分页") @PreAuthorize("@ss.hasPermission('system:tenant-balance:query')") public CommonResult> getTenantBalancePage(@Valid TenantBalancePageReqVO pageReqVO) { - PageResult pageResult = tenantBalanceService.getTenantBalancePage(pageReqVO); - return success(BeanUtils.toBean(pageResult, TenantBalanceRespVO.class)); + PageResult tenantBalancePage = tenantBalanceService.getTenantBalancePage(pageReqVO); + return success(BeanUtils.toBean(tenantBalancePage, TenantBalanceRespVO.class)); } @GetMapping("/export-excel") @@ -95,7 +95,7 @@ public class TenantBalanceController { public void exportTenantBalanceExcel(@Valid TenantBalancePageReqVO pageReqVO, HttpServletResponse response) throws IOException { pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = tenantBalanceService.getTenantBalancePage(pageReqVO).getList(); + List list = tenantBalanceService.getTenantBalancePage(pageReqVO).getList(); // 导出 Excel ExcelUtils.write(response, "租户余额.xls", "数据", TenantBalanceRespVO.class, BeanUtils.toBean(list, TenantBalanceRespVO.class)); diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java index 1a99a4f..31ee213 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java @@ -20,4 +20,8 @@ public class TenantBalanceAddReqVO { @Schema(description = "增加的余额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000000") @NotNull(message = "增加的余额不能为空") private Integer amount; + + @Schema(description = "变动描述", example = "充值") + @NotNull(message = "变动描述不能为空") + private String description; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java index 4dff99d..d399b15 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java @@ -13,6 +13,9 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @Data public class TenantBalancePageReqVO extends PageParam { + @Schema(description = "租户编号", example = "1024") + private Long id; + @Schema(description = "当前积分余额") private Integer balance; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java index 6cbc852..0dabf15 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java @@ -28,4 +28,8 @@ public class TenantBalanceRespVO { @ExcelProperty("更新时间") private LocalDateTime updatedAt; + @Schema(description = "代理名称") + @ExcelProperty("代理名称") + private String tenantName; + } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java index 9b0a202..59715cb 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java @@ -7,8 +7,10 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance.TenantBalanceDO; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import org.apache.ibatis.annotations.Mapper; import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.*; +import org.apache.ibatis.annotations.Param; /** * 租户余额 Mapper @@ -40,4 +42,7 @@ public interface TenantBalanceMapper extends BaseMapperX { return this.update(null, wrapper); } + + + IPage selectPageWithTenantName(IPage iPage,@Param("req") TenantBalancePageReqVO pageReqVO); } \ 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 7582a02..6ccd51c 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 @@ -57,7 +57,7 @@ public interface TenantBalanceService { * @param pageReqVO 分页查询 * @return 租户余额分页 */ - PageResult getTenantBalancePage(TenantBalancePageReqVO pageReqVO); + PageResult getTenantBalancePage(TenantBalancePageReqVO pageReqVO); void addTenantBalance(@Valid TenantBalanceAddReqVO updateReqVO); } \ 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 a7e7ea5..7f6f715 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 @@ -1,20 +1,21 @@ package cn.iocoder.yudao.module.system.service.tenantbalance; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.RandomUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.TenantBalancePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.TenantBalanceRespVO; 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 com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -94,8 +95,10 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { } @Override - public PageResult getTenantBalancePage(TenantBalancePageReqVO pageReqVO) { - return tenantBalanceMapper.selectPage(pageReqVO); + public PageResult getTenantBalancePage(TenantBalancePageReqVO pageReqVO) { + IPage iPage = new Page<>(pageReqVO.getPageNo(),pageReqVO.getPageSize()); + IPage tenantBalanceRespVOIPage = tenantBalanceMapper.selectPageWithTenantName(iPage, pageReqVO); + return new PageResult<>(tenantBalanceRespVOIPage.getRecords(),tenantBalanceRespVOIPage.getTotal()); } @Override @@ -137,7 +140,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { tenantPointsDO.setBalance(newBalance); tenantPointsDO.setOperatorId(loginUser.getId()); tenantPointsDO.setType(RECHARGE.getDesc()); // RECHARGE / BONUS / ... - tenantPointsDO.setDescription("后台变动积分"); + tenantPointsDO.setDescription(addReqVO.getDescription()); tenantPointsDO.setBizNo(recharge); tenantPointsMapper.insert(tenantPointsDO); } diff --git a/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml b/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml index fca190a..b7cb654 100644 --- a/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml +++ b/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml @@ -9,4 +9,16 @@ 文档可见:https://www.iocoder.cn/MyBatis/x-plugins/ --> + + \ No newline at end of file From 36a5b3bd0d19171e971393055a69c487e9d49f62 Mon Sep 17 00:00:00 2001 From: ziin Date: Thu, 20 Nov 2025 20:30:52 +0800 Subject: [PATCH 07/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E7=B1=BB=E5=9E=8B=E5=AD=97=E6=AE=B5=E5=B9=B6?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BB=A3=E7=90=86=E9=92=B1=E5=8C=85=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/tenant/vo/tenant/TenantPageReqVO.java | 3 +++ .../admin/tenant/vo/tenant/TenantRespVO.java | 3 +++ .../admin/tenant/vo/tenant/TenantSaveReqVO.java | 4 ++++ .../system/dal/dataobject/tenant/TenantDO.java | 6 ++++++ .../system/dal/mysql/tenant/TenantMapper.java | 1 + .../system/service/tenant/TenantServiceImpl.java | 14 ++++++++++++++ 6 files changed, 31 insertions(+) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java index 5fcca5b..dbd8875 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java @@ -50,4 +50,7 @@ public class TenantPageReqVO extends PageParam { @Schema(description = "父租户Id") private Long parentId; + + @Schema(description = "租户类型", example = "代理/客户") + private String tenantType; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java index 72d28d8..b53cbcc 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java @@ -66,4 +66,7 @@ public class TenantRespVO { @Schema(description = "上级租户 Id", example = "1024") private Long parentId; + + @Schema(description = "租户类型", example = "代理/客户") + private String tenantType; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java index 9df617a..a1bce11 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java @@ -86,4 +86,8 @@ public class TenantSaveReqVO { @Schema(description = "备注", example = "备注") private String remark; + @Schema(description = "租户类型", example = "代理/客户") + @NotNull(message = "租户类型不能为空") + private String tenantType; + } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java index d998f96..9f1be24 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java @@ -100,4 +100,10 @@ public class TenantDO extends BaseDO { */ private String remark; + + + /** + * 租户类型 + */ + private String tenantType; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java index 9d54788..dbd10fe 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java @@ -28,6 +28,7 @@ public interface TenantMapper extends BaseMapperX { .likeIfPresent(TenantDO::getContactName, reqVO.getContactName()) .likeIfPresent(TenantDO::getContactMobile, reqVO.getContactMobile()) .eqIfPresent(TenantDO::getStatus, reqVO.getStatus()) + .eqIfPresent(TenantDO::getTenantType, reqVO.getTenantType()) .betweenIfPresent(TenantDO::getCreateTime, reqVO.getCreateTime()) .betweenIfPresent(TenantDO::getAiExpireTime, reqVO.getAiExpireTime()) .betweenIfPresent(TenantDO::getExpireTime, reqVO.getExpireTime()) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index 2f1fffa..e196d7f 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -21,7 +21,9 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; +import cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance.TenantBalanceDO; import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper; +import cn.iocoder.yudao.module.system.dal.mysql.tenantbalance.TenantBalanceMapper; import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; import cn.iocoder.yudao.module.system.service.permission.MenuService; @@ -74,6 +76,8 @@ public class TenantServiceImpl implements TenantService { private MenuService menuService; @Resource private PermissionService permissionService; + @Resource + private TenantBalanceMapper tenantBalanceMapper; @Override public List getTenantIdList() { @@ -127,6 +131,16 @@ public class TenantServiceImpl implements TenantService { // 修改租户的管理员 tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId)); }); + // 初始化代理钱包 + if (tenant.getTenantType().equals("代理")) { + // 创建租户的钱包 + TenantBalanceDO tenantBalance = new TenantBalanceDO(); + tenantBalance.setId(tenant.getId()); + tenantBalance.setBalance(0); + tenantBalance.setVersion(0); + tenantBalanceMapper.insert(tenantBalance); + } + return tenant.getId(); } From 1c40343c6d10135f9dfb0122676bc5ea510b04fb Mon Sep 17 00:00:00 2001 From: ziin Date: Thu, 20 Nov 2025 22:08:54 +0800 Subject: [PATCH 08/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E4=BD=99=E9=A2=9D=E8=BD=AC=E8=B4=A6=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TenantBalanceController.java | 8 ++ .../vo/TenantBalanceTransferReqVO.java | 31 +++++ .../system/enums/ErrorCodeConstants.java | 8 ++ .../tenantbalance/TenantBalanceService.java | 2 + .../TenantBalanceServiceImpl.java | 130 ++++++++++++++++-- 5 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceTransferReqVO.java diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java index eb46482..a109ce1 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java @@ -109,4 +109,12 @@ public class TenantBalanceController { tenantBalanceService.addTenantBalance(addReqVO); return success(true); } + + @PostMapping("/transfer") + @Operation(summary = "租户余额转账") + @PreAuthorize("@ss.hasPermission('system:tenant-balance:transfer')") + public CommonResult transferToTenant(@Valid @RequestBody TenantBalanceTransferReqVO transferReqVO) { + tenantBalanceService.transferToTenant(transferReqVO); + return success(true); + } } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceTransferReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceTransferReqVO.java new file mode 100644 index 0000000..dae2424 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceTransferReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/* + * @author: ziin + * @date: 2025/11/19 21:05 + */ +@Schema(description = "管理后台 - 租户余额添加VO") +@Data +public class TenantBalanceTransferReqVO { + @Schema(description = "租户 Id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "租户 Id 不能为空") + private Long targetTenantId; + + + @Schema(description = "转账的金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") + @NotNull(message = "增加的余额不能为空") + private Integer transferAmount; + + @Schema(description = "变动描述", example = "充值") + @NotNull(message = "变动描述不能为空") + private String description; + + @Schema(description = "登录密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") + @NotNull(message = "登录密码不能为空") + private String password; +} 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 337627e..be2f4b8 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 @@ -125,6 +125,14 @@ public interface ErrorCodeConstants { 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, "租户余额充值错误"); + ErrorCode TENANT_WALLET_NOT_EXISTS = new ErrorCode(1_003_017_005, "租户钱包不存在"); + ErrorCode TENANT_BALANCE_NOT_ENOUGH = new ErrorCode(1_003_017_006, "当前余额余额不足"); + ErrorCode TENANT_BALANCE_TRANSFER_ERROR = new ErrorCode(1_003_017_007, "转账余额不能小于等与 0"); + ErrorCode TENANT_BALANCE_TRANSFER_TARGET_NOT_EXISTS = new ErrorCode(1_003_017_008, "转账目标租户钱包不存在"); + ErrorCode TENANT_BALANCE_TRANSFER_OPERATION_ERROR = new ErrorCode(1_003_017_009, "转账操作失败"); + 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, "转账密码不能为空"); + // ========== 社交用户 1-002-018-000 ========== 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 6ccd51c..4522248 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 @@ -60,4 +60,6 @@ public interface TenantBalanceService { PageResult getTenantBalancePage(TenantBalancePageReqVO pageReqVO); void addTenantBalance(@Valid TenantBalanceAddReqVO updateReqVO); + + void transferToTenant(@Valid TenantBalanceTransferReqVO transferReqVO); } \ 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 7f6f715..b286ef1 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 @@ -5,14 +5,15 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.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.TenantBalanceRespVO; -import cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo.TenantBalanceSaveReqVO; +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.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.tenantbalance.TenantBalanceMapper; 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.service.user.AdminUserService; import cn.iocoder.yudao.module.system.util.BizNoGenerator; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -26,6 +27,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 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.TRANSFER; /** * 租户余额 Service 实现类 @@ -42,6 +44,9 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { @Resource private TenantPointsMapper tenantPointsMapper; + @Resource + private AdminUserService userService; + @Override public Long createTenantBalance(TenantBalanceSaveReqVO createReqVO) { // 插入 @@ -121,10 +126,6 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { 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(addReqVO.getId(), addReqVO.getAmount(), oldVersion); if (updateCount == 0) { throw exception(TENANT_BALANCE_RECHARGE_ERROR); @@ -145,4 +146,117 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { tenantPointsMapper.insert(tenantPointsDO); } + @Override + @Transactional(rollbackFor = Exception.class) + public void transferToTenant(TenantBalanceTransferReqVO transferReqVO) { + + /** + * 执行租户余额转账操作 + * 注:这部分代码应该位于某个转账相关的方法中 + */ + // 获取当前登录用户ID,用于操作记录和权限验证 + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + + // 生成转账业务流水号,用于唯一标识这笔转账交易 + String transfer = BizNoGenerator.generate("TRANSFER"); + + // 验证转账密码是否为空 + if (transferReqVO.getPassword().isEmpty()) { + throw exception(TENANT_BALANCE_TRANSFER_PASSWORD_ERROR_IS_NULL); + } + + // 获取当前登录用户信息 + AdminUserDO user = userService.getUser(loginUserId); + + // 验证转账密码是否正确 + if (!userService.isPasswordMatch(transferReqVO.getPassword(), user.getPassword())) { + throw exception(TENANT_BALANCE_TRANSFER_PASSWORD_ERROR); + } + + // 获取当前租户ID(转出方) + Long tenantId = TenantContextHolder.getTenantId(); + + // 校验当前租户钱包是否存在 + TenantBalanceDO tenantBalanceDO = tenantBalanceMapper.selectById(tenantId); + if (tenantBalanceDO == null) { + throw exception(TENANT_WALLET_NOT_EXISTS); + } + + // 获取目标租户(转入方)的余额信息 + TenantBalanceDO targetTenantBalance = tenantBalanceMapper.selectById(transferReqVO.getTargetTenantId()); + + // 校验目标租户钱包是否存在 + if (targetTenantBalance == null) { + throw exception(TENANT_BALANCE_TRANSFER_TARGET_NOT_EXISTS); + } + + // 校验当前租户余额是否足够支付转账金额 + if (tenantBalanceDO.getBalance() < transferReqVO.getTransferAmount()) { + throw exception(TENANT_BALANCE_NOT_ENOUGH); + } + + // 校验转账金额是否有效(必须大于0) + if (transferReqVO.getTransferAmount() <= 0) { + throw exception(TENANT_BALANCE_TRANSFER_ERROR); + } + + // 计算转账后转出方的新余额 + Integer tenantNewBalance = tenantBalanceDO.getBalance() - transferReqVO.getTransferAmount(); + + // 计算转账后转入方的新余额 + Integer targetTenantNewBalance = targetTenantBalance.getBalance() + transferReqVO.getTransferAmount(); + + // 获取转出方当前的版本号(用于乐观锁控制) + Integer tenantBalanceDOVersion = tenantBalanceDO.getVersion(); + + // 获取转入方当前的版本号(用于乐观锁控制) + Integer targetTenantBalanceVersion = targetTenantBalance.getVersion(); + + // 先更新转入方的余额(使用乐观锁) + Integer updateTargetBalanceCount = tenantBalanceMapper + .updateBalanceWithVersion(transferReqVO.getTargetTenantId(), transferReqVO.getTransferAmount(), targetTenantBalanceVersion); + + // 如果更新转入方失败,抛出异常 + if (updateTargetBalanceCount == 0) { + throw exception(TENANT_BALANCE_TRANSFER_OPERATION_ERROR); + } + + // 再更新转出方的余额(使用乐观锁,金额为负数表示减少) + Integer updateCount = tenantBalanceMapper + .updateBalanceWithVersion(tenantId, -transferReqVO.getTransferAmount(), tenantBalanceDOVersion); + + // 如果更新转出方失败,抛出异常 + if (updateCount == 0) { + throw exception(TENANT_BALANCE_TRANSFER_OPERATION_ERROR); + } + + // 创建转出方的积分变动记录 + TenantPointsDO tenantPointsDO = new TenantPointsDO(); + tenantPointsDO.setTenantId(tenantId); // 设置租户ID + tenantPointsDO.setPoints(-transferReqVO.getTransferAmount()); // 设置变动积分(负数表示减少) + tenantPointsDO.setBalance(tenantNewBalance); // 设置变动后的余额 + tenantPointsDO.setOperatorId(loginUserId); // 设置操作人ID + tenantPointsDO.setType(TRANSFER.getDesc()); // 设置交易类型为转账 + tenantPointsDO.setDescription(transferReqVO.getDescription()); // 设置交易描述 + tenantPointsDO.setBizNo(transfer); // 设置业务流水号 + int tenantInsert = tenantPointsMapper.insert(tenantPointsDO); // 插入记录 + + // 创建转入方的积分变动记录 + TenantPointsDO targetPointsDO = new TenantPointsDO(); + targetPointsDO.setTenantId(transferReqVO.getTargetTenantId()); // 设置目标租户ID + targetPointsDO.setPoints(transferReqVO.getTransferAmount()); // 设置变动积分(正数表示增加) + targetPointsDO.setBalance(targetTenantNewBalance); // 设置变动后的余额 + targetPointsDO.setOperatorId(loginUserId); // 设置操作人ID + targetPointsDO.setType(TRANSFER.getDesc()); // 设置交易类型为转账 + targetPointsDO.setDescription(transferReqVO.getDescription()); // 设置交易描述 + targetPointsDO.setBizNo(transfer); // 设置业务流水号(与转出方使用同一个流水号) + int targetInsert = tenantPointsMapper.insert(targetPointsDO); // 插入记录 + + // 验证交易记录是否都插入成功 + if (tenantInsert == 0 || targetInsert == 0) { + throw exception(TENANT_BALANCE_TRANSFER_OPERATION_ERROR); + } + + } + } \ No newline at end of file From dfdedbb92dedc69d006d75847f13b5e434cc3995 Mon Sep 17 00:00:00 2001 From: ziin Date: Fri, 21 Nov 2025 15:51:17 +0800 Subject: [PATCH 09/37] =?UTF-8?q?feat(tenant-balance):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=9F=A5=E8=AF=A2=E8=87=AA=E8=BA=AB=E5=8F=8A=E4=B8=8B?= =?UTF-8?q?=E7=BA=A7=E4=BD=99=E9=A2=9D=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Controller 增加 /get-self-amount 与 /get-self-subordinate-amount-page 端点 - Service 与 Mapper 实现当前租户余额查询及下级分页查询 - RespVO 移除乐观锁字段,改用 updatedAt 并补充 tenantName 展示 --- .../tenantbalance/TenantBalanceController.java | 16 ++++++++++++++++ .../tenantbalance/vo/TenantBalanceRespVO.java | 4 ---- .../tenantbalance/TenantBalanceMapper.java | 2 ++ .../tenantbalance/TenantBalanceService.java | 4 ++++ .../TenantBalanceServiceImpl.java | 18 ++++++++++++++++++ .../resources/mapper/TenantBalanceMapper.xml | 13 +++++++++++++ 6 files changed, 53 insertions(+), 4 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java index a109ce1..a3fb0ec 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java @@ -117,4 +117,20 @@ public class TenantBalanceController { tenantBalanceService.transferToTenant(transferReqVO); return success(true); } + + @GetMapping("/get-self-amount") + @Operation(summary = "获得自己的余额") + @PreAuthorize("@ss.hasPermission('system:tenant-balance:self-amount')") + public CommonResult 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> getSelfSubordinate(@Valid TenantBalancePageReqVO pageReqVO) { + PageResult tenantBalancePage = tenantBalanceService.getSelfSubordinateTenantBalancePage(pageReqVO); + return success(BeanUtils.toBean(tenantBalancePage, TenantBalanceRespVO.class)); + } } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java index 0dabf15..6bd4922 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java @@ -20,10 +20,6 @@ public class TenantBalanceRespVO { @ExcelProperty("当前积分余额") private Integer balance; - @Schema(description = "乐观锁版本号", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("乐观锁版本号") - private Integer version; - @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("更新时间") private LocalDateTime updatedAt; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java index 59715cb..5cd453d 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java @@ -45,4 +45,6 @@ public interface TenantBalanceMapper extends BaseMapperX { IPage selectPageWithTenantName(IPage iPage,@Param("req") TenantBalancePageReqVO pageReqVO); + + IPage selectPageWithSelfSubordinateTenant(@Param("iPage") IPage iPage, @Param("pageReqVO") TenantBalancePageReqVO pageReqVO, @Param("tenantId") Long tenantId); } \ 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 4522248..9e2b19d 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 @@ -62,4 +62,8 @@ public interface TenantBalanceService { void addTenantBalance(@Valid TenantBalanceAddReqVO updateReqVO); void transferToTenant(@Valid TenantBalanceTransferReqVO transferReqVO); + + TenantBalanceDO getSelfBalance(); + + PageResult getSelfSubordinateTenantBalancePage(@Valid TenantBalancePageReqVO pageReqVO); } \ 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 b286ef1..7000ede 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 @@ -259,4 +259,22 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { } + @Override + public TenantBalanceDO getSelfBalance() { + Long tenantId = TenantContextHolder.getTenantId(); + TenantBalanceDO tenantBalance = tenantBalanceMapper.selectById(tenantId); + if (tenantBalance == null) { + throw exception(TENANT_WALLET_NOT_EXISTS); + } + return tenantBalance; + } + + @Override + public PageResult getSelfSubordinateTenantBalancePage(TenantBalancePageReqVO pageReqVO) { + Long tenantId = TenantContextHolder.getTenantId(); + IPage iPage = new Page<>(pageReqVO.getPageNo(),pageReqVO.getPageSize()); + IPage tenantBalanceRespVOIPage = tenantBalanceMapper.selectPageWithSelfSubordinateTenant(iPage, pageReqVO,tenantId); + return new PageResult<>(tenantBalanceRespVOIPage.getRecords(),tenantBalanceRespVOIPage.getTotal()); + } + } \ No newline at end of file diff --git a/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml b/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml index b7cb654..ffcfe10 100644 --- a/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml +++ b/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml @@ -21,4 +21,17 @@ order by stb.id desc + + \ No newline at end of file From fdbd90c6de38360b2d4a1ee5964512cdfa925756 Mon Sep 17 00:00:00 2001 From: ziin Date: Fri, 21 Nov 2025 16:10:41 +0800 Subject: [PATCH 10/37] =?UTF-8?q?refactor(system):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E4=B8=9A=E5=8A=A1=E6=B5=81=E6=B0=B4=E5=8F=B7=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=99=A8=E5=B9=B6=E4=BC=98=E5=8C=96=E7=A7=9F=E6=88=B7=E8=BD=AC?= =?UTF-8?q?=E8=B4=A6=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 BizNoGenerator 改为基于 Hutool Snowflake 的全局唯一 ID,移除每日自增序列逻辑 - TenantBalanceTransferReqVO 用 password/remark 替换原 description 字段 - TenantPointsDO 新增 remark 字段 - 转账记录自动生成“转账给租户 X,金额:Y”与“转账来自租户 X,金额:Y”描述,并写入 remark --- .../vo/TenantBalanceTransferReqVO.java | 6 ++-- .../tenantpoints/TenantPointsDO.java | 1 + .../TenantBalanceServiceImpl.java | 5 ++-- .../module/system/util/BizNoGenerator.java | 29 ++----------------- 4 files changed, 9 insertions(+), 32 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceTransferReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceTransferReqVO.java index dae2424..5f0e939 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceTransferReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceTransferReqVO.java @@ -21,11 +21,11 @@ public class TenantBalanceTransferReqVO { @NotNull(message = "增加的余额不能为空") private Integer transferAmount; - @Schema(description = "变动描述", example = "充值") - @NotNull(message = "变动描述不能为空") - private String description; @Schema(description = "登录密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") @NotNull(message = "登录密码不能为空") private String password; + + @Schema(description = "备注", example = "转账") + private String remark; } 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 25f7d66..04b6551 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 @@ -64,4 +64,5 @@ public class TenantPointsDO { private Long tenantId; + private 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 7000ede..2e9cae2 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 @@ -237,8 +237,9 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { tenantPointsDO.setBalance(tenantNewBalance); // 设置变动后的余额 tenantPointsDO.setOperatorId(loginUserId); // 设置操作人ID tenantPointsDO.setType(TRANSFER.getDesc()); // 设置交易类型为转账 - tenantPointsDO.setDescription(transferReqVO.getDescription()); // 设置交易描述 + tenantPointsDO.setDescription("转账给租户" + transferReqVO.getTargetTenantId() + ",金额:" + transferReqVO.getTransferAmount()); // 设置交易描述 tenantPointsDO.setBizNo(transfer); // 设置业务流水号 + tenantPointsDO.setRemark(transferReqVO.getRemark()); int tenantInsert = tenantPointsMapper.insert(tenantPointsDO); // 插入记录 // 创建转入方的积分变动记录 @@ -248,7 +249,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { targetPointsDO.setBalance(targetTenantNewBalance); // 设置变动后的余额 targetPointsDO.setOperatorId(loginUserId); // 设置操作人ID targetPointsDO.setType(TRANSFER.getDesc()); // 设置交易类型为转账 - targetPointsDO.setDescription(transferReqVO.getDescription()); // 设置交易描述 + targetPointsDO.setDescription("转账来自租户" + tenantId + ",金额:" + transferReqVO.getTransferAmount()); // 设置交易描述 targetPointsDO.setBizNo(transfer); // 设置业务流水号(与转出方使用同一个流水号) int targetInsert = tenantPointsMapper.insert(targetPointsDO); // 插入记录 diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/util/BizNoGenerator.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/util/BizNoGenerator.java index 3e79919..32dd235 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/util/BizNoGenerator.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/util/BizNoGenerator.java @@ -1,34 +1,9 @@ package cn.iocoder.yudao.module.system.util; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.concurrent.atomic.AtomicInteger; +import cn.hutool.core.util.IdUtil; 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); + return prefix + "-" + IdUtil.getSnowflakeNextIdStr(); } } From 5a15f2208b45327e3b400ba9664cd9cb5af42c00 Mon Sep 17 00:00:00 2001 From: ziin Date: Fri, 21 Nov 2025 18:04:24 +0800 Subject: [PATCH 11/37] =?UTF-8?q?fix(system):=20=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E8=BD=AC=E8=B4=A6=E8=AE=B0=E5=BD=95=E4=B8=AD?= =?UTF-8?q?=E7=9B=AE=E6=A0=87=E7=A7=9F=E6=88=B7ID=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/service/tenantbalance/TenantBalanceServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) 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 2e9cae2..3ee1644 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 @@ -238,6 +238,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { tenantPointsDO.setOperatorId(loginUserId); // 设置操作人ID tenantPointsDO.setType(TRANSFER.getDesc()); // 设置交易类型为转账 tenantPointsDO.setDescription("转账给租户" + transferReqVO.getTargetTenantId() + ",金额:" + transferReqVO.getTransferAmount()); // 设置交易描述 + tenantPointsDO.setTargetTenantId(transferReqVO.getTargetTenantId()); // 设置目标租户ID tenantPointsDO.setBizNo(transfer); // 设置业务流水号 tenantPointsDO.setRemark(transferReqVO.getRemark()); int tenantInsert = tenantPointsMapper.insert(tenantPointsDO); // 插入记录 @@ -249,6 +250,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { targetPointsDO.setBalance(targetTenantNewBalance); // 设置变动后的余额 targetPointsDO.setOperatorId(loginUserId); // 设置操作人ID targetPointsDO.setType(TRANSFER.getDesc()); // 设置交易类型为转账 + targetPointsDO.setTargetTenantId(tenantId);// 设置目标租户ID targetPointsDO.setDescription("转账来自租户" + tenantId + ",金额:" + transferReqVO.getTransferAmount()); // 设置交易描述 targetPointsDO.setBizNo(transfer); // 设置业务流水号(与转出方使用同一个流水号) int targetInsert = tenantPointsMapper.insert(targetPointsDO); // 插入记录 From 431c943019fbaa6372f114745586c40b9f85e162 Mon Sep 17 00:00:00 2001 From: ziin Date: Fri, 21 Nov 2025 19:50:04 +0800 Subject: [PATCH 12/37] =?UTF-8?q?feat(system):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E4=BB=A3=E7=90=86=E5=B1=82=E7=BA=A7=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E4=B8=8E=E7=BA=A7=E5=88=AB=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/tenant/TenantController.java | 11 +++ .../tenant/vo/tenant/TenantLevelRespVO.java | 15 ++++ .../admin/tenant/vo/tenant/TenantRespVO.java | 7 +- .../dal/dataobject/tenant/TenantDO.java | 5 ++ .../system/enums/ErrorCodeConstants.java | 1 + .../system/enums/tenant/TenantEnum.java | 23 ++++++ .../service/tenant/TenantServiceImpl.java | 82 ++++++++++++------- 7 files changed, 114 insertions(+), 30 deletions(-) create mode 100755 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantLevelRespVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/tenant/TenantEnum.java diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java index edde75d..9d57581 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java @@ -8,6 +8,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantLevelRespVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantRespVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; @@ -136,4 +138,13 @@ public class TenantController { return success(BeanUtils.toBean(pageResult, TenantRespVO.class)); } + @GetMapping("/getSelfTenantLevel") + @Operation(summary = "获取自身代理级别") + @PreAuthorize("@ss.hasPermission('system:tenant:query-self-Level')") + public CommonResult getSelfTenantPage() { + Long tenantId = TenantContextHolder.getTenantId(); + TenantDO tenant = tenantService.getTenant(tenantId); + return success(BeanUtils.toBean(tenant, TenantLevelRespVO.class)); + } + } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantLevelRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantLevelRespVO.java new file mode 100755 index 0000000..af12227 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantLevelRespVO.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + + +@Schema(description = "管理后台 - 租户 Response VO") +@Data +@ExcelIgnoreUnannotated +public class TenantLevelRespVO { + + @Schema(description = "租户等级",example = "1") + private String tenantLevel; +} diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java index b53cbcc..3564a24 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java @@ -67,6 +67,9 @@ public class TenantRespVO { @Schema(description = "上级租户 Id", example = "1024") private Long parentId; - @Schema(description = "租户类型", example = "代理/客户") - private String tenantType; + @Schema(description = "租户类型", example = "代理/客户") + private String tenantType; + + @Schema(description = "租户等级",example = "1") + private String tenantLevel; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java index 9f1be24..486af7b 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java @@ -106,4 +106,9 @@ public class TenantDO extends BaseDO { * 租户类型 */ private String tenantType; + + /** + * 代理级别 + */ + private Integer tenantLevel; } 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 be2f4b8..3e33b79 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 @@ -109,6 +109,7 @@ public interface ErrorCodeConstants { ErrorCode TENANT_CAN_NOT_UPDATE_SYSTEM = new ErrorCode(1_002_015_003, "系统租户不能进行修改、删除等操作!"); ErrorCode TENANT_NAME_DUPLICATE = new ErrorCode(1_002_015_004, "名字为【{}】的租户已存在"); ErrorCode TENANT_WEBSITE_DUPLICATE = new ErrorCode(1_002_015_005, "域名为【{}】的租户已存在"); + ErrorCode TENANT_LEVEL_CANT_CREATE_AGENCY = new ErrorCode(1_002_015_006, "租户级别不能创建代理租户"); // ========== 租户套餐 1-002-016-000 ========== ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1_002_016_000, "租户套餐不存在"); diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/tenant/TenantEnum.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/tenant/TenantEnum.java new file mode 100644 index 0000000..5432ea0 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/tenant/TenantEnum.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.system.enums.tenant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/* + * @author: ziin + * @date: 2025/11/21 18:55 + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +public enum TenantEnum { + + + AGENCY("代理"), + USER("用户"); + + + private String tenantType; + +} diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index e196d7f..48d9720 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -26,6 +26,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper; import cn.iocoder.yudao.module.system.dal.mysql.tenantbalance.TenantBalanceMapper; import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; +import cn.iocoder.yudao.module.system.enums.tenant.TenantEnum; import cn.iocoder.yudao.module.system.service.permission.MenuService; import cn.iocoder.yudao.module.system.service.permission.PermissionService; import cn.iocoder.yudao.module.system.service.permission.RoleService; @@ -110,37 +111,62 @@ public class TenantServiceImpl implements TenantService { @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换 @DataPermission(enable = false) // 参见 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1154 说明 public Long createTenant(TenantSaveReqVO createReqVO) { - // 校验租户名称是否重复 + // 校验租户名称是否重复(null表示新增场景,无需排除当前ID) validTenantNameDuplicate(createReqVO.getName(), null); - // 校验租户域名是否重复 + + // 校验租户域名是否重复(null表示新增场景,无需排除当前ID) validTenantWebsiteDuplicate(createReqVO.getWebsite(), null); - // 校验套餐被禁用 + + // 校验并获取租户套餐信息(确保套餐存在且未被禁用) TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(createReqVO.getPackageId()); - - // 创建租户 - TenantDO tenant = BeanUtils.toBean(createReqVO, TenantDO.class); - Long tenantId = TenantContextHolder.getTenantId(); - tenant.setParentId(tenantId); - tenantMapper.insert(tenant); - // 创建租户的管理员 - TenantUtils.execute(tenant.getId(), () -> { - // 创建角色 - Long roleId = createRole(tenantPackage); - // 创建用户,并分配角色 - Long userId = createUser(roleId, createReqVO); - // 修改租户的管理员 - tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId)); - }); - // 初始化代理钱包 - if (tenant.getTenantType().equals("代理")) { - // 创建租户的钱包 - TenantBalanceDO tenantBalance = new TenantBalanceDO(); - tenantBalance.setId(tenant.getId()); - tenantBalance.setBalance(0); - tenantBalance.setVersion(0); - tenantBalanceMapper.insert(tenantBalance); + + // 获取当前操作租户的ID(即创建者的租户ID) + Long currentTenantId = TenantContextHolder.getTenantId(); + + // 查询当前租户的详细信息 + TenantDO currentTenant = tenantMapper.selectById(currentTenantId); + + // 校验租户类型和层级权限:不允许创建代理类型租户,或当前租户级别为2的租户不允许创建 + if (createReqVO.getTenantType().equals(TenantEnum.AGENCY.getTenantType()) && currentTenant.getTenantLevel() == 2) { + throw exception(TENANT_LEVEL_CANT_CREATE_AGENCY); } - + + // 将请求参数转换为租户数据对象 + TenantDO tenant = BeanUtils.toBean(createReqVO, TenantDO.class); + + // 设置新租户的级别为当前租户级别+1(层级关系) + if (createReqVO.getTenantType().equals(TenantEnum.AGENCY.getTenantType())){ + tenant.setTenantLevel(currentTenant.getTenantLevel() + 1); + } + // 设置新租户的父租户ID为当前租户ID(建立层级关系) + tenant.setParentId(currentTenantId); + + // 将新租户信息插入数据库 + tenantMapper.insert(tenant); + + // 在新创建的租户上下文中执行管理员初始化操作 + TenantUtils.execute(tenant.getId(), () -> { + // 创建租户的默认角色 + Long roleId = createRole(tenantPackage); + + // 创建租户的管理员用户,并分配角色 + Long userId = createUser(roleId, createReqVO); + + // 将创建的用户设置为租户的联系人(管理员) + tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId)); + }); + + // 如果创建的是代理类型租户,则初始化其钱包 + if (tenant.getTenantType().equals("代理")) { + // 创建租户钱包对象 + TenantBalanceDO tenantBalance = new TenantBalanceDO(); + tenantBalance.setId(tenant.getId()); // 钱包ID与租户ID一致 + tenantBalance.setBalance(0); // 初始余额设为0 + tenantBalance.setVersion(0); // 初始版本号设为0 + tenantBalanceMapper.insert(tenantBalance); // 插入钱包记录 + } + + // 返回新创建的租户ID return tenant.getId(); } @@ -333,4 +359,4 @@ public class TenantServiceImpl implements TenantService { return tenantProperties == null || Boolean.FALSE.equals(tenantProperties.getEnable()); } -} +} \ No newline at end of file From 90039ad7ae300dba28b1b1a76dd00af1b067ee23 Mon Sep 17 00:00:00 2001 From: ziin Date: Fri, 21 Nov 2025 21:20:25 +0800 Subject: [PATCH 13/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E7=A7=AF=E5=88=86=E4=BA=A4=E6=98=93=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E5=88=86=E9=A1=B5=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/tenantpoints/TenantPointsController.java | 9 +++++++++ .../dal/mysql/tenantpoints/TenantPointsMapper.java | 6 ++++++ .../system/service/tenantpoints/TenantPointsService.java | 1 + .../service/tenantpoints/TenantPointsServiceImpl.java | 5 +++++ 4 files changed, 21 insertions(+) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java index a01cb76..68123e7 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java @@ -101,4 +101,13 @@ public class TenantPointsController { BeanUtils.toBean(list, TenantPointsRespVO.class)); } + @GetMapping("/transaction-history/page") + @Operation(summary = "获得租户积分记录分页") + @Parameter(name = "tenantId", description = "租户 Id") + @PreAuthorize("@ss.hasPermission('system:tenant-balance:query')") + public CommonResult> getTenantTransactionHistoryPointsPage(PageParam pageReqVO, + @RequestParam("tenantId") Long tenantId) { + return success(tenantPointsService.getTenantTransactionHistoryPointsPage(pageReqVO, tenantId)); + } + } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java index a04eb84..440fdcb 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.mysql.tenantpoints; import java.util.*; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -31,4 +32,9 @@ public interface TenantPointsMapper extends BaseMapperX { .orderByDesc(TenantPointsDO::getId)); } + default PageResult TenantTransactionHistoryPointsPage(PageParam pageReqVO, Long tenantId){ + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eq(TenantPointsDO::getTenantId, tenantId) + .orderByDesc(TenantPointsDO::getCreatedAt)); + } } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java index 626fb3c..b40b71c 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java @@ -59,4 +59,5 @@ public interface TenantPointsService { */ PageResult getTenantPointsPage(TenantPointsPageReqVO pageReqVO); + PageResult getTenantTransactionHistoryPointsPage(PageParam pageReqVO, Long tenantId); } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java index 6a5b3aa..941e414 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java @@ -89,4 +89,9 @@ public class TenantPointsServiceImpl implements TenantPointsService { return tenantPointsMapper.selectPage(pageReqVO); } + @Override + public PageResult getTenantTransactionHistoryPointsPage(PageParam pageReqVO, Long tenantId) { + return tenantPointsMapper.TenantTransactionHistoryPointsPage(pageReqVO,tenantId); + } + } \ No newline at end of file From a65400b3e86c8fa4bc9a069786e0dc513d8b285a Mon Sep 17 00:00:00 2001 From: ziin Date: Fri, 21 Nov 2025 21:23:57 +0800 Subject: [PATCH 14/37] =?UTF-8?q?refactor(tenant-balance):=20=E5=B0=86?= =?UTF-8?q?=E5=8F=98=E5=8A=A8=E6=8F=8F=E8=BF=B0=E5=AD=97=E6=AE=B5=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E5=A4=87=E6=B3=A8=E5=B9=B6=E8=87=AA=E5=8A=A8=E7=94=9F?= =?UTF-8?q?=E6=88=90=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/tenantbalance/vo/TenantBalanceAddReqVO.java | 5 ++--- .../service/tenantbalance/TenantBalanceServiceImpl.java | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java index 31ee213..9b8eb29 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceAddReqVO.java @@ -21,7 +21,6 @@ public class TenantBalanceAddReqVO { @NotNull(message = "增加的余额不能为空") private Integer amount; - @Schema(description = "变动描述", example = "充值") - @NotNull(message = "变动描述不能为空") - private String description; + @Schema(description = "备注", example = "备注") + private String remark; } 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 3ee1644..07b8e98 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 @@ -141,7 +141,8 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { tenantPointsDO.setBalance(newBalance); tenantPointsDO.setOperatorId(loginUser.getId()); tenantPointsDO.setType(RECHARGE.getDesc()); // RECHARGE / BONUS / ... - tenantPointsDO.setDescription(addReqVO.getDescription()); + tenantPointsDO.setDescription("总后台充值,金额:"+addReqVO.getAmount()); + tenantPointsDO.setRemark(addReqVO.getRemark()); tenantPointsDO.setBizNo(recharge); tenantPointsMapper.insert(tenantPointsDO); } From cf6290d3b4e7a3d85d2c0fc78a3e26a8dbe883c7 Mon Sep 17 00:00:00 2001 From: ziin Date: Fri, 21 Nov 2025 21:23:57 +0800 Subject: [PATCH 15/37] =?UTF-8?q?refactor(system):=20=E6=8B=86=E5=88=86?= =?UTF-8?q?=E8=BD=AC=E8=B4=A6=E6=9E=9A=E4=B8=BE=E4=B8=BA=E8=BD=AC=E5=85=A5?= =?UTF-8?q?=E4=B8=8E=E8=BD=AC=E5=87=BA=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/system/enums/balance/BalanceEnum.java | 3 ++- .../service/tenantbalance/TenantBalanceServiceImpl.java | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java index 6d11b12..87511b4 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java @@ -15,7 +15,8 @@ public enum BalanceEnum { RECHARGE("充值"), - TRANSFER("转账"), + TRANSFER_OUT("转出"), + TRANSFER_IN("转入"), CONSUMPTION("消费"); 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 07b8e98..400c6b8 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 @@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.system.service.user.AdminUserService; import cn.iocoder.yudao.module.system.util.BizNoGenerator; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.mzt.logapi.starter.annotation.LogRecord; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -26,8 +27,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 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.TRANSFER; +import static cn.iocoder.yudao.module.system.enums.balance.BalanceEnum.*; /** * 租户余额 Service 实现类 @@ -237,7 +237,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { tenantPointsDO.setPoints(-transferReqVO.getTransferAmount()); // 设置变动积分(负数表示减少) tenantPointsDO.setBalance(tenantNewBalance); // 设置变动后的余额 tenantPointsDO.setOperatorId(loginUserId); // 设置操作人ID - tenantPointsDO.setType(TRANSFER.getDesc()); // 设置交易类型为转账 + tenantPointsDO.setType(TRANSFER_OUT.getDesc()); // 设置交易类型为转账 tenantPointsDO.setDescription("转账给租户" + transferReqVO.getTargetTenantId() + ",金额:" + transferReqVO.getTransferAmount()); // 设置交易描述 tenantPointsDO.setTargetTenantId(transferReqVO.getTargetTenantId()); // 设置目标租户ID tenantPointsDO.setBizNo(transfer); // 设置业务流水号 @@ -250,7 +250,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { targetPointsDO.setPoints(transferReqVO.getTransferAmount()); // 设置变动积分(正数表示增加) targetPointsDO.setBalance(targetTenantNewBalance); // 设置变动后的余额 targetPointsDO.setOperatorId(loginUserId); // 设置操作人ID - targetPointsDO.setType(TRANSFER.getDesc()); // 设置交易类型为转账 + targetPointsDO.setType(TRANSFER_IN.getDesc()); // 设置交易类型为转账 targetPointsDO.setTargetTenantId(tenantId);// 设置目标租户ID targetPointsDO.setDescription("转账来自租户" + tenantId + ",金额:" + transferReqVO.getTransferAmount()); // 设置交易描述 targetPointsDO.setBizNo(transfer); // 设置业务流水号(与转出方使用同一个流水号) From 500feb74cb8f5c2cef9c9941532ba8a3f1c8f059 Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 24 Nov 2025 14:08:46 +0800 Subject: [PATCH 16/37] =?UTF-8?q?fix(system):=20=E9=99=90=E5=88=B6?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E5=8F=AA=E8=83=BD=E6=9F=A5=E7=9C=8B=E8=87=AA?= =?UTF-8?q?=E5=B7=B1=E7=9A=84=E7=A7=AF=E5=88=86=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mysql/tenantpoints/TenantPointsMapper.java | 16 ++++++++++++++++ .../tenantpoints/TenantPointsServiceImpl.java | 8 +++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java index 440fdcb..d503940 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java @@ -37,4 +37,20 @@ public interface TenantPointsMapper extends BaseMapperX { .eq(TenantPointsDO::getTenantId, tenantId) .orderByDesc(TenantPointsDO::getCreatedAt)); } + + default PageResult selectPageWithTenantId(TenantPointsPageReqVO reqVO, Long tenantId) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(TenantPointsDO::getTenantId, tenantId) + .eqIfPresent(TenantPointsDO::getPoints, reqVO.getPoints()) + .eqIfPresent(TenantPointsDO::getBalance, reqVO.getBalance()) + .eqIfPresent(TenantPointsDO::getType, reqVO.getType()) + .eqIfPresent(TenantPointsDO::getDescription, reqVO.getDescription()) + .eqIfPresent(TenantPointsDO::getOrderId, reqVO.getOrderId()) + .eqIfPresent(TenantPointsDO::getBizNo, reqVO.getBizNo()) + .eqIfPresent(TenantPointsDO::getOperatorId, reqVO.getOperatorId()) + .eqIfPresent(TenantPointsDO::getTargetTenantId, reqVO.getTargetTenantId()) + .eqIfPresent(TenantPointsDO::getCreatedAt, reqVO.getCreatedAt()) + .orderByDesc(TenantPointsDO::getId)); + } + } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java index 941e414..a7e0c30 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.service.tenantpoints; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import org.springframework.stereotype.Service; import javax.annotation.Resource; import org.springframework.validation.annotation.Validated; @@ -86,7 +87,12 @@ public class TenantPointsServiceImpl implements TenantPointsService { @Override public PageResult getTenantPointsPage(TenantPointsPageReqVO pageReqVO) { - return tenantPointsMapper.selectPage(pageReqVO); + Long tenantId = TenantContextHolder.getTenantId(); + if (tenantId == 1) { + return tenantPointsMapper.selectPage(pageReqVO); + } + return tenantPointsMapper.selectPageWithTenantId(pageReqVO,tenantId); + } @Override From 30bbbfb7298d8a7ed81f565064adea4d704cb127 Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 24 Nov 2025 14:28:23 +0800 Subject: [PATCH 17/37] =?UTF-8?q?fix(system):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E8=BD=AC=E8=B4=A6=E4=B8=8B=E7=BA=A7=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E5=B9=B6=E8=A1=A5=E5=85=85=E9=94=99=E8=AF=AF=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 校验目标租户必须为当前租户下级,新增 TENANT_BALANCE_TRANSFER_ERROR_TARGET_NOT_SUBORDINATE 错误码,防止越权转账。 --- .../tenantpoints/vo/TenantPointsPageReqVO.java | 2 +- .../module/system/enums/ErrorCodeConstants.java | 1 + .../tenantbalance/TenantBalanceServiceImpl.java | 17 +++++++++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java index 9162fde..d0cd4b1 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java @@ -26,7 +26,7 @@ public class TenantPointsPageReqVO extends PageParam { 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/enums/ErrorCodeConstants.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index 3e33b79..458f380 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 @@ -133,6 +133,7 @@ public interface ErrorCodeConstants { ErrorCode TENANT_BALANCE_TRANSFER_OPERATION_ERROR = new ErrorCode(1_003_017_009, "转账操作失败"); 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, "转账目标租户不是当前租户的下级"); 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 400c6b8..35aa5ec 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 @@ -7,9 +7,11 @@ 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.*; +import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; 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.tenantbalance.TenantBalanceMapper; import cn.iocoder.yudao.module.system.dal.mysql.tenantpoints.TenantPointsMapper; import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; @@ -18,12 +20,14 @@ import cn.iocoder.yudao.module.system.util.BizNoGenerator; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.mzt.logapi.starter.annotation.LogRecord; +import org.springframework.beans.factory.annotation.Autowired; 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 java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; @@ -47,6 +51,9 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { @Resource private AdminUserService userService; + @Resource + private TenantMapper tenantMapper; + @Override public Long createTenantBalance(TenantBalanceSaveReqVO createReqVO) { // 插入 @@ -165,7 +172,9 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { if (transferReqVO.getPassword().isEmpty()) { throw exception(TENANT_BALANCE_TRANSFER_PASSWORD_ERROR_IS_NULL); } - + TenantDO targetTenantInfo = tenantMapper.selectById(transferReqVO.getTargetTenantId()); + + // 获取当前登录用户信息 AdminUserDO user = userService.getUser(loginUserId); @@ -176,7 +185,11 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { // 获取当前租户ID(转出方) Long tenantId = TenantContextHolder.getTenantId(); - + + if (!Objects.equals(targetTenantInfo.getParentId(), tenantId)) { + throw exception(TENANT_BALANCE_TRANSFER_ERROR_TARGET_NOT_SUBORDINATE); + } + // 校验当前租户钱包是否存在 TenantBalanceDO tenantBalanceDO = tenantBalanceMapper.selectById(tenantId); if (tenantBalanceDO == null) { From 023a01b7a26cced9dba13e77cbd759b58ae3e5f1 Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 24 Nov 2025 15:10:06 +0800 Subject: [PATCH 18/37] =?UTF-8?q?refactor(system):=20=E7=A7=9F=E6=88=B7?= =?UTF-8?q?=E7=A7=AF=E5=88=86=E5=88=86=E9=A1=B5=E6=9F=A5=E8=AF=A2=E6=94=B9?= =?UTF-8?q?=E4=B8=BAXML=E8=BF=9E=E8=A1=A8=E5=B9=B6=E8=BF=94=E5=9B=9EVO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tenantpoints/TenantPointsController.java | 15 +++-- .../vo/TenantPointsPageReqVO.java | 6 +- .../vo/TenantPointsPageRespVO.java | 58 ++++++++++++++++ .../tenantpoints/TenantPointsMapper.java | 5 ++ .../tenantpoints/TenantPointsService.java | 2 +- .../tenantpoints/TenantPointsServiceImpl.java | 16 +++-- .../resources/mapper/TenantPointsMapper.xml | 66 +++++++++++++++++++ 7 files changed, 154 insertions(+), 14 deletions(-) create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageRespVO.java diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java index 68123e7..8aadcef 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/TenantPointsController.java @@ -8,7 +8,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; -import javax.validation.constraints.*; import javax.validation.*; import javax.servlet.http.*; import java.util.*; @@ -83,9 +82,9 @@ public class TenantPointsController { @GetMapping("/page") @Operation(summary = "获得租户积分记录分页") @PreAuthorize("@ss.hasPermission('system:tenant-points:query')") - public CommonResult> getTenantPointsPage(@Valid TenantPointsPageReqVO pageReqVO) { - PageResult pageResult = tenantPointsService.getTenantPointsPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, TenantPointsRespVO.class)); + public CommonResult> getTenantPointsPage(@Valid TenantPointsPageReqVO pageReqVO) { + PageResult tenantPointsPage = tenantPointsService.getTenantPointsPage(pageReqVO); + return success(tenantPointsPage); } @GetMapping("/export-excel") @@ -95,10 +94,12 @@ public class TenantPointsController { public void exportTenantPointsExcel(@Valid TenantPointsPageReqVO pageReqVO, HttpServletResponse response) throws IOException { pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = tenantPointsService.getTenantPointsPage(pageReqVO).getList(); + + List list = tenantPointsService.getTenantPointsPage(pageReqVO).getList(); + // 导出 Excel - ExcelUtils.write(response, "租户积分记录.xls", "数据", TenantPointsRespVO.class, - BeanUtils.toBean(list, TenantPointsRespVO.class)); + ExcelUtils.write(response, "租户积分记录.xls", "数据", TenantPointsPageRespVO.class, + BeanUtils.toBean(list, TenantPointsPageRespVO.class)); } @GetMapping("/transaction-history/page") diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java index d0cd4b1..094b9b5 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageReqVO.java @@ -38,6 +38,10 @@ public class TenantPointsPageReqVO extends PageParam { private Long targetTenantId; @Schema(description = "创建时间") - private LocalDateTime createdAt; + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createdAt; + + @Schema(description = "备注") + private String remark; } \ No newline at end of file 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 new file mode 100644 index 0000000..65c1e4c --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantpoints/vo/TenantPointsPageRespVO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantpoints.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 租户积分记录 Response VO") +@Data +@ExcelIgnoreUnannotated +public class TenantPointsPageRespVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "16587") + @ExcelProperty("主键") + private Long id; + + @Schema(description = "本次变动点数,正加负减", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("本次变动点数,正加负减") + private Integer points; + + @Schema(description = "变动后余额快照(冗余)") + @ExcelProperty("变动后余额快照(冗余)") + private Integer balance; + + @Schema(description = "变动类型,", example = "转账") + @ExcelProperty("变动类型,") + private String type; + + @Schema(description = "变动描述", example = "转账金额 100") + @ExcelProperty("变动描述") + private String description; + + @Schema(description = "订单 Id/业务单号", example = "84") + @ExcelProperty("订单 Id/业务单号") + private Long orderId; + + @Schema(description = "业务流水号(转账、订单等唯一标识)") + @ExcelProperty("业务流水号(转账、订单等唯一标识)") + private String bizNo; + + @Schema(description = "操作人 Id", example = "8171") + @ExcelProperty("操作人 Id") + private Long operatorId; + + @Schema(description = "目标租户 Id(转账使用)", example = "18731") + @ExcelProperty("目标租户 Id(转账使用)") + private Long targetTenantId; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createdAt; + + @Schema(description = "租户名称", example = "租户 A") + @ExcelProperty("租户名称") + private String tenantName; +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java index d503940..75c0ecf 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantpoints/TenantPointsMapper.java @@ -7,8 +7,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.system.dal.dataobject.tenantpoints.TenantPointsDO; +import com.baomidou.mybatisplus.core.metadata.IPage; import org.apache.ibatis.annotations.Mapper; import cn.iocoder.yudao.module.system.controller.admin.tenantpoints.vo.*; +import org.apache.ibatis.annotations.Param; /** * 租户积分记录 Mapper @@ -53,4 +55,7 @@ public interface TenantPointsMapper extends BaseMapperX { .orderByDesc(TenantPointsDO::getId)); } + IPage selectPageWithXML(@Param("iPage") IPage iPage, @Param("pageReqVO") TenantPointsPageReqVO pageReqVO); + + IPage selectPageWithTenantIdXML(@Param("iPage")IPage iPage,@Param("pageReqVO") TenantPointsPageReqVO pageReqVO,@Param("tenantId") Long tenantId); } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java index b40b71c..a7c548e 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsService.java @@ -57,7 +57,7 @@ public interface TenantPointsService { * @param pageReqVO 分页查询 * @return 租户积分记录分页 */ - PageResult getTenantPointsPage(TenantPointsPageReqVO pageReqVO); + PageResult getTenantPointsPage(TenantPointsPageReqVO pageReqVO); PageResult getTenantTransactionHistoryPointsPage(PageParam pageReqVO, Long tenantId); } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java index a7e0c30..a3623ae 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantpoints/TenantPointsServiceImpl.java @@ -2,10 +2,11 @@ package cn.iocoder.yudao.module.system.service.tenantpoints; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 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.tenantpoints.vo.*; @@ -18,7 +19,6 @@ import cn.iocoder.yudao.module.system.dal.mysql.tenantpoints.TenantPointsMapper; 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.*; /** @@ -86,12 +86,18 @@ public class TenantPointsServiceImpl implements TenantPointsService { } @Override - public PageResult getTenantPointsPage(TenantPointsPageReqVO pageReqVO) { + public PageResult getTenantPointsPage(TenantPointsPageReqVO pageReqVO) { Long tenantId = TenantContextHolder.getTenantId(); + if (tenantId == 1) { - return tenantPointsMapper.selectPage(pageReqVO); + IPage iPage = new Page<>(pageReqVO.getPageNo(),pageReqVO.getPageSize()); + IPage tenantPointsPageRespVOIPage = tenantPointsMapper.selectPageWithXML(iPage, pageReqVO); + return new PageResult<>(tenantPointsPageRespVOIPage.getRecords(),tenantPointsPageRespVOIPage.getTotal()); } - return tenantPointsMapper.selectPageWithTenantId(pageReqVO,tenantId); + + IPage iPage = new Page<>(pageReqVO.getPageNo(),pageReqVO.getPageSize()); + IPage tenantPointsPageRespVOIPage = tenantPointsMapper.selectPageWithTenantIdXML(iPage,pageReqVO,tenantId); + return new PageResult<>(tenantPointsPageRespVOIPage.getRecords(),tenantPointsPageRespVOIPage.getTotal()); } diff --git a/yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml b/yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml index 94a3d7d..bd04d3c 100644 --- a/yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml +++ b/yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml @@ -9,4 +9,70 @@ 文档可见:https://www.iocoder.cn/MyBatis/x-plugins/ --> + + + + \ No newline at end of file From f03877c1d56a01ed2824b7916ea7bba75d905f7b Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 24 Nov 2025 15:15:43 +0800 Subject: [PATCH 19/37] =?UTF-8?q?fix(system):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E7=A7=AF=E5=88=86=E6=9F=A5=E8=AF=A2=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=9D=A1=E4=BB=B6=E5=88=A4=E6=96=AD=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/mapper/TenantPointsMapper.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml b/yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml index bd04d3c..8bc8dc7 100644 --- a/yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml +++ b/yudao-module-system/src/main/resources/mapper/TenantPointsMapper.xml @@ -35,7 +35,7 @@ and stp.type = #{pageReqVO.type} - + and stp.created_at between #{pageReqVO.createdAt[0]} and #{pageReqVO.createdAt[1]} From 016b4df3e8224b0e95aeff116b9ea21aaa8bb87a Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 24 Nov 2025 15:59:04 +0800 Subject: [PATCH 20/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E7=A7=9F=E6=88=B7=E5=A5=97=E9=A4=90=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 TenantAgencyPackage 实体、Mapper、Service 及 Controller 全套后端 - 新增租户余额消费接口及 VO(预留实现) - 移除废弃的社交登录相关错误码,补充代理套餐错误码 TENANT_AGENCY_PACKAGE_NOT_EXISTS - 配置文件增加 system_tenant_agency_package 缓存忽略 共 15 个文件,+578 −7 行,复杂度:非常复杂 --- .../TenantAgencyPackageController.java | 103 ++++++++++++++++++ .../vo/TenantAgencyPackagePageReqVO.java | 50 +++++++++ .../vo/TenantAgencyPackageRespVO.java | 63 +++++++++++ .../vo/TenantAgencyPackageSaveReqVO.java | 50 +++++++++ .../TenantBalanceController.java | 2 + .../vo/TenantBalanceConsumptionReqVO.java | 17 +++ .../TenantAgencyPackageDO.java | 72 ++++++++++++ .../TenantAgencyPackageMapper.java | 36 ++++++ .../system/enums/ErrorCodeConstants.java | 15 +-- .../TenantAgencyPackageService.java | 61 +++++++++++ .../TenantAgencyPackageServiceImpl.java | 88 +++++++++++++++ .../tenantbalance/TenantBalanceService.java | 2 + .../TenantBalanceServiceImpl.java | 21 ++++ .../mapper/TenantAgencyPackageMapper.xml | 12 ++ .../src/main/resources/application.yaml | 1 + 15 files changed, 582 insertions(+), 11 deletions(-) create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceConsumptionReqVO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantagencypackage/TenantAgencyPackageDO.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageService.java create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageServiceImpl.java create mode 100644 yudao-module-system/src/main/resources/mapper/TenantAgencyPackageMapper.xml diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java new file mode 100644 index 0000000..65374a0 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage; + +import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO; +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo.*; +import cn.iocoder.yudao.module.system.service.tenantagencypackage.TenantAgencyPackageService; + +@Tag(name = "管理后台 - 代理租户套餐") +@RestController +@RequestMapping("/system/tenant-agency-package") +@Validated +public class TenantAgencyPackageController { + + @Resource + private TenantAgencyPackageService tenantAgencyPackageService; + + @PostMapping("/create") + @Operation(summary = "创建代理租户套餐") + @PreAuthorize("@ss.hasPermission('system:tenant-agency-package:create')") + public CommonResult createTenantAgencyPackage(@Valid @RequestBody TenantAgencyPackageSaveReqVO createReqVO) { + return success(tenantAgencyPackageService.createTenantAgencyPackage(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新代理租户套餐") + @PreAuthorize("@ss.hasPermission('system:tenant-agency-package:update')") + public CommonResult updateTenantAgencyPackage(@Valid @RequestBody TenantAgencyPackageSaveReqVO updateReqVO) { + tenantAgencyPackageService.updateTenantAgencyPackage(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除代理租户套餐") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('system:tenant-agency-package:delete')") + public CommonResult deleteTenantAgencyPackage(@RequestParam("id") Long id) { + tenantAgencyPackageService.deleteTenantAgencyPackage(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Parameter(name = "ids", description = "编号", required = true) + @Operation(summary = "批量删除代理租户套餐") + @PreAuthorize("@ss.hasPermission('system:tenant-agency-package:delete')") + public CommonResult deleteTenantAgencyPackageList(@RequestParam("ids") List ids) { + tenantAgencyPackageService.deleteTenantAgencyPackageListByIds(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得代理租户套餐") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('system:tenant-agency-package:query')") + public CommonResult getTenantAgencyPackage(@RequestParam("id") Long id) { + TenantAgencyPackageDO tenantAgencyPackage = tenantAgencyPackageService.getTenantAgencyPackage(id); + return success(BeanUtils.toBean(tenantAgencyPackage, TenantAgencyPackageRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得代理租户套餐分页") + @PreAuthorize("@ss.hasPermission('system:tenant-agency-package:query')") + public CommonResult> getTenantAgencyPackagePage(@Valid TenantAgencyPackagePageReqVO pageReqVO) { + PageResult pageResult = tenantAgencyPackageService.getTenantAgencyPackagePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, TenantAgencyPackageRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出代理租户套餐 Excel") + @PreAuthorize("@ss.hasPermission('system:tenant-agency-package:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTenantAgencyPackageExcel(@Valid TenantAgencyPackagePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = tenantAgencyPackageService.getTenantAgencyPackagePage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "代理租户套餐.xls", "数据", TenantAgencyPackageRespVO.class, + BeanUtils.toBean(list, TenantAgencyPackageRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java new file mode 100644 index 0000000..c177571 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 代理租户套餐分页 Request VO") +@Data +public class TenantAgencyPackagePageReqVO extends PageParam { + + @Schema(description = "套餐名", example = "芋艿") + private String name; + + @Schema(description = "租户状态(0正常 1停用)", example = "2") + private Integer status; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "关联的菜单编号") + private String menuIds; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + + @Schema(description = "套餐天数") + private Integer days; + + @Schema(description = "套餐价格", example = "22890") + private Integer price; + + @Schema(description = "爬主播客户端 0 关闭 1 开启") + private Integer hostslClient; + + @Schema(description = "爬大哥客户端 0 关闭 1 开启") + private Integer brotherClient; + + @Schema(description = "AI 客户端 0 关闭 1 开启") + private Integer aiClient; + + @Schema(description = "套餐类型", example = "2") + private Integer packageType; + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java new file mode 100644 index 0000000..7237a88 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 代理租户套餐 Response VO") +@Data +@ExcelIgnoreUnannotated +public class TenantAgencyPackageRespVO { + + @Schema(description = "套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20125") + @ExcelProperty("套餐编号") + private Long id; + + @Schema(description = "套餐名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @ExcelProperty("套餐名") + private String name; + + @Schema(description = "租户状态(0正常 1停用)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("租户状态(0正常 1停用)") + private Integer status; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "关联的菜单编号", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("关联的菜单编号") + private String menuIds; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "套餐天数", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("套餐天数") + private Integer days; + + @Schema(description = "套餐价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "22890") + @ExcelProperty("套餐价格") + private Integer price; + + @Schema(description = "爬主播客户端 0 关闭 1 开启") + @ExcelProperty("爬主播客户端 0 关闭 1 开启") + private Integer hostslClient; + + @Schema(description = "爬大哥客户端 0 关闭 1 开启") + @ExcelProperty("爬大哥客户端 0 关闭 1 开启") + private Integer brotherClient; + + @Schema(description = "AI 客户端 0 关闭 1 开启") + @ExcelProperty("AI 客户端 0 关闭 1 开启") + private Integer aiClient; + + @Schema(description = "套餐类型", example = "2") + @ExcelProperty("套餐类型") + private Integer packageType; + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java new file mode 100644 index 0000000..7594da3 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - 代理租户套餐新增/修改 Request VO") +@Data +public class TenantAgencyPackageSaveReqVO { + + @Schema(description = "套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20125") + private Long id; + + @Schema(description = "套餐名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @NotEmpty(message = "套餐名不能为空") + private String name; + + @Schema(description = "租户状态(0正常 1停用)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "租户状态(0正常 1停用)不能为空") + private Integer status; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "关联的菜单编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "关联的菜单编号不能为空") + private String menuIds; + + @Schema(description = "套餐天数", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "套餐天数不能为空") + private Integer days; + + @Schema(description = "套餐价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "22890") + @NotNull(message = "套餐价格不能为空") + private Integer price; + + @Schema(description = "爬主播客户端 0 关闭 1 开启") + private Integer hostslClient; + + @Schema(description = "爬大哥客户端 0 关闭 1 开启") + private Integer brotherClient; + + @Schema(description = "AI 客户端 0 关闭 1 开启") + private Integer aiClient; + + @Schema(description = "套餐类型", example = "2") + private Integer packageType; + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java index a3fb0ec..856b599 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/TenantBalanceController.java @@ -133,4 +133,6 @@ public class TenantBalanceController { PageResult tenantBalancePage = tenantBalanceService.getSelfSubordinateTenantBalancePage(pageReqVO); return success(BeanUtils.toBean(tenantBalancePage, TenantBalanceRespVO.class)); } + + } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceConsumptionReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceConsumptionReqVO.java new file mode 100644 index 0000000..3f053b5 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceConsumptionReqVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/* + * @author: ziin + * @date: 2025/11/24 15:32 + */ +@Schema(description = "管理后台 - 租户余额消费") +@Data +public class TenantBalanceConsumptionReqVO { + + @Schema( description = "套餐编号") + private Long id; + +} 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 new file mode 100644 index 0000000..6257d1a --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantagencypackage/TenantAgencyPackageDO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 代理租户套餐 DO + * + * @author 总后台 + */ +@TableName("system_tenant_agency_package") +@KeySequence("system_tenant_agency_package_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TenantAgencyPackageDO extends BaseDO { + + /** + * 套餐编号 + */ + @TableId + private Long id; + /** + * 套餐名 + */ + private String name; + /** + * 租户状态(0正常 1停用) + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 关联的菜单编号 + */ + private String menuIds; + /** + * 套餐天数 + */ + private Integer days; + /** + * 套餐价格 + */ + private Integer price; + /** + * 爬主播客户端 0 关闭 1 开启 + */ + private Integer hostslClient; + /** + * 爬大哥客户端 0 关闭 1 开启 + */ + private Integer brotherClient; + /** + * AI 客户端 0 关闭 1 开启 + */ + private Integer aiClient; + /** + * 套餐类型 + */ + private Integer packageType; + + +} \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java new file mode 100644 index 0000000..540538e --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.system.dal.mysql.tenantagencypackage; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo.*; + +/** + * 代理租户套餐 Mapper + * + * @author 总后台 + */ +@Mapper +public interface TenantAgencyPackageMapper extends BaseMapperX { + + default PageResult selectPage(TenantAgencyPackagePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(TenantAgencyPackageDO::getName, reqVO.getName()) + .eqIfPresent(TenantAgencyPackageDO::getStatus, reqVO.getStatus()) + .eqIfPresent(TenantAgencyPackageDO::getRemark, reqVO.getRemark()) + .eqIfPresent(TenantAgencyPackageDO::getMenuIds, reqVO.getMenuIds()) + .betweenIfPresent(TenantAgencyPackageDO::getCreateTime, reqVO.getCreateTime()) + .eqIfPresent(TenantAgencyPackageDO::getDays, reqVO.getDays()) + .eqIfPresent(TenantAgencyPackageDO::getPrice, reqVO.getPrice()) + .eqIfPresent(TenantAgencyPackageDO::getHostslClient, reqVO.getHostslClient()) + .eqIfPresent(TenantAgencyPackageDO::getBrotherClient, reqVO.getBrotherClient()) + .eqIfPresent(TenantAgencyPackageDO::getAiClient, reqVO.getAiClient()) + .eqIfPresent(TenantAgencyPackageDO::getPackageType, reqVO.getPackageType()) + .orderByDesc(TenantAgencyPackageDO::getId)); + } + +} \ No newline at end of file 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 458f380..645ef0f 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 @@ -136,19 +136,12 @@ public interface ErrorCodeConstants { ErrorCode TENANT_BALANCE_TRANSFER_ERROR_TARGET_NOT_SUBORDINATE = new ErrorCode(1_003_017_012, "转账目标租户不是当前租户的下级"); +// ================= 租户套餐 1-003-018-000 ================== + ErrorCode TENANT_AGENCY_PACKAGE_NOT_EXISTS = new ErrorCode(1_003_018_000, "代理租户套餐不存在"); + + - // ========== 社交用户 1-002-018-000 ========== - ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1_002_018_000, "社交授权失败,原因是:{}"); - ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1_002_018_001, "社交授权失败,找不到对应的用户"); - ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1_002_018_200, "获得手机号失败"); - ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_QRCODE_ERROR = new ErrorCode(1_002_018_201, "获得小程序码失败"); - ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_SUBSCRIBE_TEMPLATE_ERROR = new ErrorCode(1_002_018_202, "获得小程序订阅消息模版失败"); - ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_SUBSCRIBE_MESSAGE_ERROR = new ErrorCode(1_002_018_203, "发送小程序订阅消息失败"); - ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_ORDER_UPLOAD_SHIPPING_INFO_ERROR = new ErrorCode(1_002_018_204, "上传微信小程序发货信息失败"); - ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_ORDER_NOTIFY_CONFIRM_RECEIVE_ERROR = new ErrorCode(1_002_018_205, "上传微信小程序订单收货信息失败"); - ErrorCode SOCIAL_CLIENT_NOT_EXISTS = new ErrorCode(1_002_018_210, "社交客户端不存在"); - ErrorCode SOCIAL_CLIENT_UNIQUE = new ErrorCode(1_002_018_211, "社交客户端已存在配置"); // ========== OAuth2 客户端 1-002-020-000 ========= ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1_002_020_000, "OAuth2 客户端不存在"); 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 new file mode 100644 index 0000000..99e782c --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageService.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.system.service.tenantagencypackage; + +import java.util.*; +import javax.validation.*; +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; + +/** + * 代理租户套餐 Service 接口 + * + * @author 总后台 + */ +public interface TenantAgencyPackageService { + + /** + * 创建代理租户套餐 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTenantAgencyPackage(@Valid TenantAgencyPackageSaveReqVO createReqVO); + + /** + * 更新代理租户套餐 + * + * @param updateReqVO 更新信息 + */ + void updateTenantAgencyPackage(@Valid TenantAgencyPackageSaveReqVO updateReqVO); + + /** + * 删除代理租户套餐 + * + * @param id 编号 + */ + void deleteTenantAgencyPackage(Long id); + + /** + * 批量删除代理租户套餐 + * + * @param ids 编号 + */ + void deleteTenantAgencyPackageListByIds(List ids); + + /** + * 获得代理租户套餐 + * + * @param id 编号 + * @return 代理租户套餐 + */ + TenantAgencyPackageDO getTenantAgencyPackage(Long id); + + /** + * 获得代理租户套餐分页 + * + * @param pageReqVO 分页查询 + * @return 代理租户套餐分页 + */ + PageResult getTenantAgencyPackagePage(TenantAgencyPackagePageReqVO pageReqVO); + +} \ 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 new file mode 100644 index 0000000..0174ca4 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenantagencypackage/TenantAgencyPackageServiceImpl.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.system.service.tenantagencypackage; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO; +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; + +import java.util.*; +import cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo.*; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.system.dal.mysql.tenantagencypackage.TenantAgencyPackageMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; + +/** + * 代理租户套餐 Service 实现类 + * + * @author 总后台 + */ +@Service +@Validated +public class TenantAgencyPackageServiceImpl implements TenantAgencyPackageService { + + @Resource + private TenantAgencyPackageMapper tenantAgencyPackageMapper; + + @Override + public Long createTenantAgencyPackage(TenantAgencyPackageSaveReqVO createReqVO) { + // 插入 + TenantAgencyPackageDO tenantAgencyPackage = BeanUtils.toBean(createReqVO, TenantAgencyPackageDO.class); + tenantAgencyPackageMapper.insert(tenantAgencyPackage); + // 返回 + return tenantAgencyPackage.getId(); + } + + @Override + public void updateTenantAgencyPackage(TenantAgencyPackageSaveReqVO updateReqVO) { + // 校验存在 + validateTenantAgencyPackageExists(updateReqVO.getId()); + // 更新 + TenantAgencyPackageDO updateObj = BeanUtils.toBean(updateReqVO, TenantAgencyPackageDO.class); + tenantAgencyPackageMapper.updateById(updateObj); + } + + @Override + public void deleteTenantAgencyPackage(Long id) { + // 校验存在 + validateTenantAgencyPackageExists(id); + // 删除 + tenantAgencyPackageMapper.deleteById(id); + } + + @Override + public void deleteTenantAgencyPackageListByIds(List ids) { + // 校验存在 + validateTenantAgencyPackageExists(ids); + // 删除 + tenantAgencyPackageMapper.deleteByIds(ids); + } + + private void validateTenantAgencyPackageExists(List ids) { + List list = tenantAgencyPackageMapper.selectByIds(ids); + if (CollUtil.isEmpty(list) || list.size() != ids.size()) { + throw exception(TENANT_AGENCY_PACKAGE_NOT_EXISTS); + } + } + + private void validateTenantAgencyPackageExists(Long id) { + if (tenantAgencyPackageMapper.selectById(id) == null) { + throw exception(TENANT_AGENCY_PACKAGE_NOT_EXISTS); + } + } + + @Override + public TenantAgencyPackageDO getTenantAgencyPackage(Long id) { + return tenantAgencyPackageMapper.selectById(id); + } + + @Override + public PageResult getTenantAgencyPackagePage(TenantAgencyPackagePageReqVO pageReqVO) { + return tenantAgencyPackageMapper.selectPage(pageReqVO); + } + +} \ 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 9e2b19d..6ee5372 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 @@ -66,4 +66,6 @@ public interface TenantBalanceService { TenantBalanceDO getSelfBalance(); PageResult getSelfSubordinateTenantBalancePage(@Valid TenantBalancePageReqVO pageReqVO); + + Boolean consumption(@Valid TenantBalanceConsumptionReqVO consumptionReqVO); } \ 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 35aa5ec..0a01902 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 @@ -294,4 +294,25 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { return new PageResult<>(tenantBalanceRespVOIPage.getRecords(),tenantBalanceRespVOIPage.getTotal()); } + @Override + public Boolean consumption(TenantBalanceConsumptionReqVO consumptionReqVO) { + + 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); +// } + return true; + + + + } + } \ No newline at end of file diff --git a/yudao-module-system/src/main/resources/mapper/TenantAgencyPackageMapper.xml b/yudao-module-system/src/main/resources/mapper/TenantAgencyPackageMapper.xml new file mode 100644 index 0000000..e455b72 --- /dev/null +++ b/yudao-module-system/src/main/resources/mapper/TenantAgencyPackageMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 842c034..c4ca279 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -195,6 +195,7 @@ yudao: - ai_language - system_tenant_balance - system_tenant_points + - system_tenant_agency_package ignore-caches: - user_role_ids - permission_menu_ids From 0d57c0a5f8ea8c5fc464af9ce9d66d24ce371921 Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 24 Nov 2025 16:46:15 +0800 Subject: [PATCH 21/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=A5=97=E9=A4=90=E6=B6=88=E8=B4=B9=E4=B8=8E=E4=BD=99=E9=A2=9D?= =?UTF-8?q?=E6=A0=A1=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; From d879ff7dc979a6b3330a9582fdaee6a49a6314c0 Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 24 Nov 2025 19:43:19 +0800 Subject: [PATCH 22/37] =?UTF-8?q?feat(system):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E7=A7=9F=E6=88=B7=E5=88=9B=E5=BB=BA=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E9=94=99=E8=AF=AF=E7=A0=81=E5=B9=B6=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E5=A5=97=E9=A4=90=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TenantAgencyPackageController.java | 1 + .../vo/TenantAgencyPackageSaveReqVO.java | 2 +- .../TenantAgencyPackageMapper.java | 5 + .../system/enums/ErrorCodeConstants.java | 1 + .../tenant/TenantPackageServiceImpl.java | 13 ++ .../service/tenant/TenantServiceImpl.java | 171 ++++++++++++++---- .../TenantBalanceServiceImpl.java | 4 +- 7 files changed, 163 insertions(+), 34 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java index 65374a0..12e1b24 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java @@ -100,4 +100,5 @@ public class TenantAgencyPackageController { BeanUtils.toBean(list, TenantAgencyPackageRespVO.class)); } + } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java index 7594da3..49e0004 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java @@ -25,7 +25,7 @@ public class TenantAgencyPackageSaveReqVO { @Schema(description = "关联的菜单编号", requiredMode = Schema.RequiredMode.REQUIRED) @NotEmpty(message = "关联的菜单编号不能为空") - private String menuIds; + private Set menuIds; @Schema(description = "套餐天数", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "套餐天数不能为空") diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java index 540538e..2f1e644 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java @@ -5,6 +5,7 @@ import java.util.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO; import org.apache.ibatis.annotations.Mapper; import cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo.*; @@ -33,4 +34,8 @@ public interface TenantAgencyPackageMapper extends BaseMapperX selectListByStatus(Integer status) { + return selectList(TenantAgencyPackageDO::getStatus, status); + } + } \ No newline at end of file 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 6ec2d1a..e6af3f6 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 @@ -135,6 +135,7 @@ public interface ErrorCodeConstants { 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, "租户余额消费操作失败"); + ErrorCode TENANT_CREATE_FAIL = new ErrorCode(1_003_017_014, "租户创建失败"); // ================= 租户套餐 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/tenant/TenantPackageServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java index 8fccc64..7b0b3d5 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java @@ -1,15 +1,20 @@ package cn.iocoder.yudao.module.system.service.tenant; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSimpleRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; 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.mysql.tenant.TenantPackageMapper; +import cn.iocoder.yudao.module.system.dal.mysql.tenantagencypackage.TenantAgencyPackageMapper; import com.baomidou.dynamic.datasource.annotation.DSTransactional; import com.google.common.annotations.VisibleForTesting; import org.springframework.context.annotation.Lazy; @@ -38,6 +43,9 @@ public class TenantPackageServiceImpl implements TenantPackageService { @Lazy // 避免循环依赖的报错 private TenantService tenantService; + @Resource + private TenantAgencyPackageMapper tenantAgencyPackageMapper; + @Override public Long createTenantPackage(TenantPackageSaveReqVO createReqVO) { // 校验套餐名是否重复 @@ -114,6 +122,11 @@ public class TenantPackageServiceImpl implements TenantPackageService { @Override public List getTenantPackageListByStatus(Integer status) { + Long tenantId = TenantContextHolder.getTenantId(); + if (tenantId != 1) { + List tenantAgencyPackageDOS = tenantAgencyPackageMapper.selectListByStatus(status); + return BeanUtils.toBean(tenantAgencyPackageDOS, TenantPackageDO.class); + } return tenantPackageMapper.selectListByStatus(status); } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index 48d9720..cad30d1 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -1,6 +1,9 @@ package cn.iocoder.yudao.module.system.service.tenant; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -21,9 +24,13 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; 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.tenantbalance.TenantBalanceDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper; import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper; import cn.iocoder.yudao.module.system.dal.mysql.tenantbalance.TenantBalanceMapper; +import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; import cn.iocoder.yudao.module.system.enums.tenant.TenantEnum; @@ -32,6 +39,8 @@ import cn.iocoder.yudao.module.system.service.permission.PermissionService; import cn.iocoder.yudao.module.system.service.permission.RoleService; import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler; import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler; +import cn.iocoder.yudao.module.system.service.tenantagencypackage.TenantAgencyPackageService; +import cn.iocoder.yudao.module.system.service.tenantbalance.TenantBalanceService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.baomidou.dynamic.datasource.annotation.DSTransactional; import lombok.extern.slf4j.Slf4j; @@ -41,6 +50,8 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Objects; import java.util.Set; @@ -79,7 +90,12 @@ public class TenantServiceImpl implements TenantService { private PermissionService permissionService; @Resource private TenantBalanceMapper tenantBalanceMapper; - + @Resource + private TenantAgencyPackageService tenantAgencyPackageService; + @Resource + private AdminUserMapper userMapper; + @Resource + private TenantBalanceService balanceService; @Override public List getTenantIdList() { List tenants = tenantMapper.selectList(); @@ -111,61 +127,141 @@ public class TenantServiceImpl implements TenantService { @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换 @DataPermission(enable = false) // 参见 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1154 说明 public Long createTenant(TenantSaveReqVO createReqVO) { - // 校验租户名称是否重复(null表示新增场景,无需排除当前ID) - validTenantNameDuplicate(createReqVO.getName(), null); - - // 校验租户域名是否重复(null表示新增场景,无需排除当前ID) - validTenantWebsiteDuplicate(createReqVO.getWebsite(), null); - - // 校验并获取租户套餐信息(确保套餐存在且未被禁用) - TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(createReqVO.getPackageId()); - + // 获取当前操作租户的ID(即创建者的租户ID) Long currentTenantId = TenantContextHolder.getTenantId(); - + if (currentTenantId != 1){ + // 校验租户名称是否重复(null表示新增场景,无需排除当前ID) + validTenantNameDuplicate(createReqVO.getName(), null); + + // 校验租户域名是否重复(null表示新增场景,无需排除当前ID) + validTenantWebsiteDuplicate(createReqVO.getWebsite(), null); + + // 校验并获取租户套餐信息(确保套餐存在且未被禁用) + TenantAgencyPackageDO tenantAgencyPackageDO = tenantAgencyPackageService.validTenantPackage(createReqVO.getPackageId()); + + // 查询当前租户的详细信息 + TenantDO currentTenant = tenantMapper.selectById(currentTenantId); + + // 校验租户类型和层级权限:不允许创建代理类型租户,或当前租户级别为2的租户不允许创建 + if (createReqVO.getTenantType().equals(TenantEnum.AGENCY.getTenantType()) && currentTenant.getTenantLevel() == 2) { + throw exception(TENANT_LEVEL_CANT_CREATE_AGENCY); + } + + // 将请求参数转换为租户数据对象 + TenantDO tenant = BeanUtils.toBean(createReqVO, TenantDO.class); + + String now = DateUtil.now(); + DateTime dt = DateUtil.parse(now); + LocalDateTime localDateTime = LocalDateTimeUtil.of(dt); + LocalDateTime offset = LocalDateTimeUtil.offset(localDateTime, tenantAgencyPackageDO.getDays(), ChronoUnit.DAYS); + tenant.setExpireTime(offset); + if (tenantAgencyPackageDO.getBrotherClient() == 1){ + tenant.setBrotherExpireTime(offset); + } + if (tenantAgencyPackageDO.getAiClient() == 1){ + tenant.setAiExpireTime(offset); + } + // 设置新租户的级别为当前租户级别+1(层级关系) + if (createReqVO.getTenantType().equals(TenantEnum.AGENCY.getTenantType())){ + tenant.setTenantLevel(currentTenant.getTenantLevel() + 1); + } + // 设置新租户的父租户ID为当前租户ID(建立层级关系) + tenant.setParentId(currentTenantId); + + tenantMapper.insert(tenant); + // 扣除开通费用, + if (balanceService.consumption(createReqVO.getPackageId(), tenant.getId(), createReqVO.getRemark())) { + log.info("代理: {} 开通租户:{} 成功,套餐 Id:{}", currentTenantId,tenant.getId(),createReqVO.getPackageId()); + } + // 在新创建的租户上下文中执行管理员初始化操作 + TenantUtils.execute(tenant.getId(), () -> { + // 创建租户的默认角色 + Long roleId = AgencyCreateRole(tenantAgencyPackageDO); + + // 创建租户的管理员用户,并分配角色 + Long userId = createUser(roleId, createReqVO); + AdminUserDO user = userService.getUser(userId); + if (tenantAgencyPackageDO.getHostslClient() == 1){ + user.setCrawl((byte) 1); + } + if (tenantAgencyPackageDO.getHostslClient() == 1){ + user.setBigBrother((byte) 1); + } + if (tenantAgencyPackageDO.getAiClient() == 1){ + user.setAiChat((byte) 1); + user.setAiReplay((byte) 1); + } + userMapper.updateById(user); + // 将创建的用户设置为租户的联系人(管理员) + tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId)); + }); + + // 如果创建的是代理类型租户,则初始化其钱包 + if (tenant.getTenantType().equals("代理")) { + // 创建租户钱包对象 + TenantBalanceDO tenantBalance = new TenantBalanceDO(); + tenantBalance.setId(tenant.getId()); // 钱包ID与租户ID一致 + tenantBalance.setBalance(0); // 初始余额设为0 + tenantBalance.setVersion(0); // 初始版本号设为0 + tenantBalanceMapper.insert(tenantBalance); // 插入钱包记录 + } + + // 返回新创建的租户ID + return tenant.getId(); + } + // 校验租户名称是否重复(null表示新增场景,无需排除当前ID) + validTenantNameDuplicate(createReqVO.getName(), null); + + // 校验租户域名是否重复(null表示新增场景,无需排除当前ID) + validTenantWebsiteDuplicate(createReqVO.getWebsite(), null); + + // 校验并获取租户套餐信息(确保套餐存在且未被禁用) + TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(createReqVO.getPackageId()); + // 查询当前租户的详细信息 TenantDO currentTenant = tenantMapper.selectById(currentTenantId); - + // 校验租户类型和层级权限:不允许创建代理类型租户,或当前租户级别为2的租户不允许创建 if (createReqVO.getTenantType().equals(TenantEnum.AGENCY.getTenantType()) && currentTenant.getTenantLevel() == 2) { throw exception(TENANT_LEVEL_CANT_CREATE_AGENCY); } - + // 将请求参数转换为租户数据对象 TenantDO tenant = BeanUtils.toBean(createReqVO, TenantDO.class); - + // 设置新租户的级别为当前租户级别+1(层级关系) if (createReqVO.getTenantType().equals(TenantEnum.AGENCY.getTenantType())){ tenant.setTenantLevel(currentTenant.getTenantLevel() + 1); } // 设置新租户的父租户ID为当前租户ID(建立层级关系) tenant.setParentId(currentTenantId); - + // 将新租户信息插入数据库 tenantMapper.insert(tenant); - + // 在新创建的租户上下文中执行管理员初始化操作 TenantUtils.execute(tenant.getId(), () -> { - // 创建租户的默认角色 - Long roleId = createRole(tenantPackage); - - // 创建租户的管理员用户,并分配角色 - Long userId = createUser(roleId, createReqVO); - - // 将创建的用户设置为租户的联系人(管理员) - tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId)); + // 创建租户的默认角色 + Long roleId = createRole(tenantPackage); + + // 创建租户的管理员用户,并分配角色 + Long userId = createUser(roleId, createReqVO); + + // 将创建的用户设置为租户的联系人(管理员) + tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId)); }); - + // 如果创建的是代理类型租户,则初始化其钱包 if (tenant.getTenantType().equals("代理")) { - // 创建租户钱包对象 - TenantBalanceDO tenantBalance = new TenantBalanceDO(); - tenantBalance.setId(tenant.getId()); // 钱包ID与租户ID一致 - tenantBalance.setBalance(0); // 初始余额设为0 - tenantBalance.setVersion(0); // 初始版本号设为0 - tenantBalanceMapper.insert(tenantBalance); // 插入钱包记录 + // 创建租户钱包对象 + TenantBalanceDO tenantBalance = new TenantBalanceDO(); + tenantBalance.setId(tenant.getId()); // 钱包ID与租户ID一致 + tenantBalance.setBalance(0); // 初始余额设为0 + tenantBalance.setVersion(0); // 初始版本号设为0 + tenantBalanceMapper.insert(tenantBalance); // 插入钱包记录 } - + // 返回新创建的租户ID return tenant.getId(); } @@ -189,6 +285,17 @@ public class TenantServiceImpl implements TenantService { return roleId; } + private Long AgencyCreateRole(TenantAgencyPackageDO agencyPackageDO) { + // 创建角色 + RoleSaveReqVO reqVO = new RoleSaveReqVO(); + reqVO.setName(RoleCodeEnum.TENANT_ADMIN.getName()).setCode(RoleCodeEnum.TENANT_ADMIN.getCode()) + .setSort(0).setRemark("系统自动生成"); + Long roleId = roleService.createRole(reqVO, RoleTypeEnum.SYSTEM.getType()); + // 分配权限 + permissionService.assignRoleMenu(roleId, agencyPackageDO.getMenuIds()); + return roleId; + } + @Override @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换 public void updateTenant(TenantSaveReqVO updateReqVO) { 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 f687842..a1bf7a2 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 @@ -326,6 +326,8 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { Integer tenantBalanceDOVersion = tenantBalance.getVersion(); Integer oldBalance = tenantBalance.getBalance(); + + Integer newBalance = oldBalance - tenantAgencyPackageDO.getPrice(); // 更新租户余额 Integer updateCount = tenantBalanceMapper.updateBalanceWithVersion(tenantId, -tenantAgencyPackageDO.getPrice(), tenantBalanceDOVersion); @@ -337,7 +339,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { TenantPointsDO tenantPointsDO = new TenantPointsDO(); tenantPointsDO.setTenantId(tenantId); // 设置租户ID tenantPointsDO.setPoints(-tenantAgencyPackageDO.getPrice()); // 设置变动积分(负数表示减少) - tenantPointsDO.setBalance(oldBalance - tenantAgencyPackageDO.getPrice()); // 设置变动后的余额 + tenantPointsDO.setBalance(newBalance); // 设置变动后的余额 tenantPointsDO.setOperatorId(loginUserId); // 设置操作人ID tenantPointsDO.setType(CONSUMPTION.getDesc()); // 设置交易类型为转账 tenantPointsDO.setDescription("给租户" + targetTenantId + "开通套餐" + tenantAgencyPackageDO.getName() + ",金额:" + tenantAgencyPackageDO.getPrice()); // 设置交易描述 From 43dd7cf768ecc210c2d984ef7f96107d4f37976d Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 24 Nov 2025 20:11:56 +0800 Subject: [PATCH 23/37] =?UTF-8?q?fix(config):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E7=A7=9F=E6=88=B7=E7=B1=BB=E5=9E=8B=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/mapper/TenantBalanceMapper.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml b/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml index ffcfe10..7159368 100644 --- a/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml +++ b/yudao-module-system/src/main/resources/mapper/TenantBalanceMapper.xml @@ -28,6 +28,7 @@ left join system_tenant as st on stb.id = st.id and st.parent_Id = #{tenantId,jdbcType=BIGINT} + and st.tenant_type = '代理' and stb.id = #{pageReqVO.id,jdbcType=BIGINT} From d05ce7336c1778f443f67d4d330d14d2771f0b65 Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 24 Nov 2025 21:18:15 +0800 Subject: [PATCH 24/37] =?UTF-8?q?fix(tenant):=20=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E7=A7=9F=E6=88=B7=E5=A5=97=E9=A4=90MyBatis?= =?UTF-8?q?=E6=98=A0=E5=B0=84=E5=8F=8AVO=E7=B1=BB=E5=9E=8B=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/TenantAgencyPackagePageReqVO.java | 2 +- .../vo/TenantAgencyPackageRespVO.java | 2 +- .../tenantagencypackage/TenantAgencyPackageDO.java | 6 +++++- .../TenantAgencyPackageMapper.java | 1 + .../TenantAgencyPackageServiceImpl.java | 12 ++++++------ .../resources/mapper/TenantAgencyPackageMapper.xml | 14 ++++++++++++++ 6 files changed, 28 insertions(+), 9 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java index c177571..1345191 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java @@ -23,7 +23,7 @@ public class TenantAgencyPackagePageReqVO extends PageParam { private String remark; @Schema(description = "关联的菜单编号") - private String menuIds; + private Set menuIds; @Schema(description = "创建时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java index 7237a88..2beb224 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java @@ -30,7 +30,7 @@ public class TenantAgencyPackageRespVO { @Schema(description = "关联的菜单编号", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("关联的菜单编号") - private String menuIds; + private Set menuIds; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("创建时间") 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 668da28..e56ec4f 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 cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.*; import java.util.*; @@ -13,7 +14,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; * * @author 总后台 */ -@TableName("system_tenant_agency_package") +@TableName(value = "system_tenant_agency_package",autoResultMap = true) @KeySequence("system_tenant_agency_package_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @@ -21,6 +22,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; @Builder @NoArgsConstructor @AllArgsConstructor +@TenantIgnore public class TenantAgencyPackageDO extends BaseDO { /** @@ -43,8 +45,10 @@ public class TenantAgencyPackageDO extends BaseDO { /** * 关联的菜单编号 */ + @TableField(typeHandler = JacksonTypeHandler.class) private Set menuIds; + /** * 套餐天数 */ diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java index 2f1e644..6a820b0 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantagencypackage/TenantAgencyPackageMapper.java @@ -38,4 +38,5 @@ public interface TenantAgencyPackageMapper extends BaseMapperX + + + + + + + + + + + \ No newline at end of file From 95f2e882963111ff78945067f884eed31f485270 Mon Sep 17 00:00:00 2001 From: ziin Date: Tue, 25 Nov 2025 14:58:15 +0800 Subject: [PATCH 25/37] =?UTF-8?q?feat(tenant-agency):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E5=A5=97=E9=A4=90=E7=B2=BE=E7=AE=80=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TenantAgencyPackageController.java | 10 ++++++++++ .../vo/AgencyTenantPackageSimpleRespVO.java | 20 +++++++++++++++++++ .../TenantAgencyPackageService.java | 2 ++ .../TenantAgencyPackageServiceImpl.java | 5 +++++ 4 files changed, 37 insertions(+) create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java index 12e1b24..cf99969 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/TenantAgencyPackageController.java @@ -1,5 +1,8 @@ package cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSimpleRespVO; +import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -100,5 +103,12 @@ public class TenantAgencyPackageController { BeanUtils.toBean(list, TenantAgencyPackageRespVO.class)); } + @GetMapping({"/get-simple-list", "代理套餐精简列表"}) + @Operation(summary = "获取代理租户套餐精简信息列表", description = "只包含被开启的租户套餐,主要用于前端的下拉选项") + @PreAuthorize("@ss.hasPermission('system:tenant-agency-package:simple-list')") + public CommonResult> getTenantPackageList() { + List list = tenantAgencyPackageService.getTenantPackageListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(BeanUtils.toBean(list, AgencyTenantPackageSimpleRespVO.class)); + } } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java new file mode 100644 index 0000000..a0003b4 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 租户套餐精简 Response VO") +@Data +public class AgencyTenantPackageSimpleRespVO { + + @Schema(description = "套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "套餐编号不能为空") + private Long id; + + @Schema(description = "套餐名", requiredMode = Schema.RequiredMode.REQUIRED, example = "VIP") + @NotNull(message = "套餐名不能为空") + private String name; + +} 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 e44356c..8eba9f4 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 @@ -61,4 +61,6 @@ public interface TenantAgencyPackageService { PageResult getTenantAgencyPackagePage(TenantAgencyPackagePageReqVO pageReqVO); TenantAgencyPackageDO validTenantPackage(@NotNull(message = "租户套餐编号不能为空") Long packageId); + + List getTenantPackageListByStatus(Integer status); } \ 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 10a020d..ec2b6cb 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 @@ -100,4 +100,9 @@ public class TenantAgencyPackageServiceImpl implements TenantAgencyPackageServic return tenantAgencyPackageDO; } + @Override + public List getTenantPackageListByStatus(Integer status) { + return tenantAgencyPackageMapper.selectListByStatus(status); + } + } \ No newline at end of file From e366af049308373e540a96f995bf49cc6b753aeb Mon Sep 17 00:00:00 2001 From: ziin Date: Tue, 25 Nov 2025 15:18:13 +0800 Subject: [PATCH 26/37] =?UTF-8?q?feat(system):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E8=B4=A6=E5=8F=B7=E6=95=B0=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BB=A3=E7=90=86=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/tenantbalance/vo/TenantBalancePageReqVO.java | 4 ++++ .../admin/tenantbalance/vo/TenantBalanceRespVO.java | 3 +++ .../admin/tenantbalance/vo/TenantBalanceSaveReqVO.java | 4 ++++ .../system/dal/dataobject/tenantbalance/TenantBalanceDO.java | 4 +++- .../yudao/module/system/service/tenant/TenantServiceImpl.java | 4 ++++ 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java index d399b15..9fa3298 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalancePageReqVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo; +import com.alibaba.excel.annotation.ExcelProperty; import lombok.*; import java.util.*; import io.swagger.v3.oas.annotations.media.Schema; @@ -25,4 +26,7 @@ public class TenantBalancePageReqVO extends PageParam { @Schema(description = "更新时间") private LocalDateTime updatedAt; + @Schema(description = "测试账号数") + @ExcelProperty("测试账号数") + private Integer testAccountNum; } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java index 6bd4922..94687fe 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceRespVO.java @@ -28,4 +28,7 @@ public class TenantBalanceRespVO { @ExcelProperty("代理名称") private String tenantName; + @Schema(description = "测试账号数") + @ExcelProperty("测试账号数") + private Integer testAccountNum; } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceSaveReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceSaveReqVO.java index 29ba2f5..f3195eb 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceSaveReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantbalance/vo/TenantBalanceSaveReqVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.controller.admin.tenantbalance.vo; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; @@ -26,4 +27,7 @@ public class TenantBalanceSaveReqVO { @NotNull(message = "更新时间不能为空") private LocalDateTime updatedAt; + @Schema(description = "测试账号数") + @ExcelProperty("测试账号数") + private Integer testAccountNum; } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java index 3c6a707..7c04c4b 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenantbalance/TenantBalanceDO.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.tenantbalance; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; import java.time.LocalDateTime; @@ -34,5 +36,5 @@ public class TenantBalanceDO{ */ private LocalDateTime updatedAt; - + private Integer testAccountNum; } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index cad30d1..6c4fbfa 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -169,6 +169,10 @@ public class TenantServiceImpl implements TenantService { // 设置新租户的父租户ID为当前租户ID(建立层级关系) tenant.setParentId(currentTenantId); + if (tenant.getTenantType().equals(TenantEnum.AGENCY.getTenantType())) { + tenant.setStatus(CommonStatusEnum.DISABLE.getStatus()); + } + tenantMapper.insert(tenant); // 扣除开通费用, if (balanceService.consumption(createReqVO.getPackageId(), tenant.getId(), createReqVO.getRemark())) { From bfc2b218722bc0572b6979b3b7ad7f33dfeaa581 Mon Sep 17 00:00:00 2001 From: ziin Date: Tue, 25 Nov 2025 16:16:28 +0800 Subject: [PATCH 27/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E6=B5=8B=E8=AF=95=E8=B4=A6=E6=88=B7=E5=A2=9E?= =?UTF-8?q?=E5=87=8F=E5=8F=8A=E5=A5=96=E5=8A=B1=E7=B1=BB=E5=9E=8B=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BalanceEnum 增加 BONUS 奖励类型 - ErrorCodeConstants 补充测试账户不足/操作错误码 - TenantBalanceMapper 添加乐观锁更新测试账户数方法 - TenantBalanceService 新增 reduceTestAccountNum/addTestAccountNum - TenantBalanceServiceImpl 实现测试账户扣减与奖励发放逻辑 - TenantPointsDO/VO 增加 testAccountNum 字段 - TenantServiceImpl 创建租户时根据套餐类型自动增减测试账户 - 新增 PackageTypeEnum 枚举区分测试/代理/普通套餐 --- .../vo/TenantPointsPageRespVO.java | 4 ++ .../tenantpoints/vo/TenantPointsRespVO.java | 3 + .../tenantpoints/TenantPointsDO.java | 2 + .../tenantbalance/TenantBalanceMapper.java | 15 +++++ .../system/enums/ErrorCodeConstants.java | 2 + .../agencyTenantPackage/PackageTypeEnum.java | 26 +++++++ .../system/enums/balance/BalanceEnum.java | 3 +- .../service/tenant/TenantServiceImpl.java | 11 +++ .../tenantbalance/TenantBalanceService.java | 4 ++ .../TenantBalanceServiceImpl.java | 67 +++++++++++++++++++ 10 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/agencyTenantPackage/PackageTypeEnum.java 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 237e609..f455491 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 @@ -55,4 +55,8 @@ public class TenantPointsPageRespVO { @Schema(description = "租户名称", example = "租户 A") @ExcelProperty("租户名称") private String tenantName; + + @Schema(description = "测试账号数", example = "1") + @ExcelProperty("测试账号数") + private Integer testAccountNum; } \ No newline at end of file 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 a4ba572..79b50a5 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 @@ -52,4 +52,7 @@ public class TenantPointsRespVO { @ExcelProperty("创建时间") private LocalDateTime createdAt; + @Schema(description = "测试账号数", example = "1") + @ExcelProperty("测试账号数") + private Integer testAccountNum; } \ No newline at end of file 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 6383cdd..73f5ca3 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 @@ -65,4 +65,6 @@ public class TenantPointsDO { private Long tenantId; private String remark; + + private Integer testAccountNum; } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java index 5cd453d..173f773 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenantbalance/TenantBalanceMapper.java @@ -47,4 +47,19 @@ public interface TenantBalanceMapper extends BaseMapperX { IPage selectPageWithTenantName(IPage iPage,@Param("req") TenantBalancePageReqVO pageReqVO); IPage selectPageWithSelfSubordinateTenant(@Param("iPage") IPage iPage, @Param("pageReqVO") TenantBalancePageReqVO pageReqVO, @Param("tenantId") Long tenantId); + + default Integer updateTestAccountNumWithVersion(Long currentTenantId, Integer newTestAccountNum, Integer oldVersion){ + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + + wrapper.eq(TenantBalanceDO::getId, currentTenantId); + wrapper.eq(TenantBalanceDO::getVersion, oldVersion); + + // testAccount = testAccount + -1 + wrapper.setSql("test_account_num = test_account_num + " + newTestAccountNum); + + // version = version + 1 + wrapper.setSql("version = version + 1"); + + return this.update(null, wrapper); + } } \ No newline at end of file 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 e6af3f6..897c9df 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 @@ -136,6 +136,8 @@ public interface ErrorCodeConstants { 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, "租户余额消费操作失败"); ErrorCode TENANT_CREATE_FAIL = new ErrorCode(1_003_017_014, "租户创建失败"); + ErrorCode TENANT_BALANCE_TEST_ACCOUNT_NUM_NOT_ENOUGH = new ErrorCode(1_003_017_015, "当前账户测试账户数量不足"); + ErrorCode TENANT_BALANCE_TEST_ACCOUNT_NUM_OPERATION_ERROR = new ErrorCode(1_003_017_016, "租户测试账户数量操作错误"); // ================= 租户套餐 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/enums/agencyTenantPackage/PackageTypeEnum.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/agencyTenantPackage/PackageTypeEnum.java new file mode 100644 index 0000000..aee0460 --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/agencyTenantPackage/PackageTypeEnum.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.system.enums.agencyTenantPackage; + + +import lombok.Getter; + +/* + * @author: ziin + * @date: 2025/11/25 15:22 + */ +@Getter +public enum PackageTypeEnum { + + AI(0, "AI"), + CRAWL(1, "爬虫"), + BROTHER_CRAWL(2, "兄弟爬虫"), + TEST(99, "测试账户"), + AGENCY(199, "代理"); + + private final Integer value; + private final String name; + + PackageTypeEnum(Integer value, String name) { + this.value = value; + this.name = name; + } +} diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java index 87511b4..8bf2ae2 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java @@ -17,7 +17,8 @@ public enum BalanceEnum { RECHARGE("充值"), TRANSFER_OUT("转出"), TRANSFER_IN("转入"), - CONSUMPTION("消费"); + CONSUMPTION("消费"), + BONUS(" 奖励"); private String desc; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index 6c4fbfa..672e644 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -31,6 +31,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper; import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper; import cn.iocoder.yudao.module.system.dal.mysql.tenantbalance.TenantBalanceMapper; import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; +import cn.iocoder.yudao.module.system.enums.agencyTenantPackage.PackageTypeEnum; import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; import cn.iocoder.yudao.module.system.enums.tenant.TenantEnum; @@ -178,6 +179,15 @@ public class TenantServiceImpl implements TenantService { if (balanceService.consumption(createReqVO.getPackageId(), tenant.getId(), createReqVO.getRemark())) { log.info("代理: {} 开通租户:{} 成功,套餐 Id:{}", currentTenantId,tenant.getId(),createReqVO.getPackageId()); } + // 开通测试套餐扣除测试账号数 + if (tenantAgencyPackageDO.getPackageType().equals(PackageTypeEnum.TEST.getValue())){ + balanceService.reduceTestAccountNum(currentTenantId); + } + if (!tenantAgencyPackageDO.getPackageType().equals(PackageTypeEnum.AGENCY.getValue()) + && !tenantAgencyPackageDO.getPackageType().equals(PackageTypeEnum.TEST.getValue())) { + balanceService.addTestAccountNum(currentTenantId); + } + // 在新创建的租户上下文中执行管理员初始化操作 TenantUtils.execute(tenant.getId(), () -> { // 创建租户的默认角色 @@ -208,6 +218,7 @@ public class TenantServiceImpl implements TenantService { tenantBalance.setId(tenant.getId()); // 钱包ID与租户ID一致 tenantBalance.setBalance(0); // 初始余额设为0 tenantBalance.setVersion(0); // 初始版本号设为0 + tenantBalance.setTestAccountNum(15); tenantBalanceMapper.insert(tenantBalance); // 插入钱包记录 } 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 2f9a376..7a0c201 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 @@ -68,4 +68,8 @@ public interface TenantBalanceService { PageResult getSelfSubordinateTenantBalancePage(@Valid TenantBalancePageReqVO pageReqVO); Boolean consumption(Long PackageId, Long targetTenantId,String remark); + + Boolean reduceTestAccountNum(Long currentTenantId); + + Boolean addTestAccountNum(Long currentTenantId); } \ 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 a1bf7a2..792b1c0 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 @@ -358,4 +358,71 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { } + @Override + public Boolean reduceTestAccountNum(Long currentTenantId) { + TenantBalanceDO tenantBalanceDO = tenantBalanceMapper.selectById(currentTenantId); + if (tenantBalanceDO.getTestAccountNum()<=0) { + throw exception(TENANT_BALANCE_TEST_ACCOUNT_NUM_NOT_ENOUGH); + } + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + Integer oldVersion = tenantBalanceDO.getVersion(); + Integer newTestAccountNum = tenantBalanceDO.getTestAccountNum() - 1; + + Integer i = tenantBalanceMapper.updateTestAccountNumWithVersion(currentTenantId, -1, oldVersion); + if (i == 0) { + throw exception(TENANT_BALANCE_TEST_ACCOUNT_NUM_OPERATION_ERROR); + } + String consumption = BizNoGenerator.generate("CONSUMPTION"); + + // 消费积分变动记录 + TenantPointsDO tenantPointsDO = new TenantPointsDO(); + tenantPointsDO.setTenantId(currentTenantId); // 设置租户ID + tenantPointsDO.setPoints(-1); // 设置变动积分(负数表示减少) + tenantPointsDO.setBalance(tenantPointsDO.getBalance()); + tenantPointsDO.setTestAccountNum(newTestAccountNum); // 设置变动后的余额 + tenantPointsDO.setOperatorId(loginUserId); // 设置操作人ID + tenantPointsDO.setType(CONSUMPTION.getDesc()); // 设置交易类型为转账 + tenantPointsDO.setDescription("开通测试账户"); // 设置交易描述 + tenantPointsDO.setBizNo(consumption); // 设置业务流水号 + int tenantInsert = tenantPointsMapper.insert(tenantPointsDO); // 插入记录 + if (tenantInsert == 0) { + throw exception(TENANT_BALANCE_CONSUMPTION_OPERATION_ERROR); + } + return true; + } + + @Override + public Boolean addTestAccountNum(Long currentTenantId) { + TenantBalanceDO tenantBalanceDO = tenantBalanceMapper.selectById(currentTenantId); + + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + + Integer oldVersion = tenantBalanceDO.getVersion(); + + Integer newTestAccountNum = tenantBalanceDO.getTestAccountNum() + 5; + + Integer i = tenantBalanceMapper.updateTestAccountNumWithVersion(currentTenantId, 5, oldVersion); + if (i == 0) { + throw exception(TENANT_BALANCE_TEST_ACCOUNT_NUM_OPERATION_ERROR); + } + String bonus = BizNoGenerator.generate("BONUS"); + + // 消费积分变动记录 + TenantPointsDO tenantPointsDO = new TenantPointsDO(); + tenantPointsDO.setTenantId(currentTenantId); // 设置租户ID + tenantPointsDO.setPoints(5); // 设置变动积分(负数表示减少) + tenantPointsDO.setTestAccountNum(newTestAccountNum); // 设置变动后的余额 + tenantPointsDO.setBalance(tenantPointsDO.getBalance()); + tenantPointsDO.setOperatorId(loginUserId); // 设置操作人ID + tenantPointsDO.setType(BONUS.getDesc()); // 设置交易类型为转账 + tenantPointsDO.setDescription("开通测试账户,增加测试账号数量"); // 设置交易描述 + tenantPointsDO.setBizNo(bonus); // 设置业务流水号 + int tenantInsert = tenantPointsMapper.insert(tenantPointsDO); // 插入记录 + if (tenantInsert == 0) { + throw exception(TENANT_BALANCE_CONSUMPTION_OPERATION_ERROR); + } + + return true; + } + } \ No newline at end of file From a4ce439f7ca2d70ae168510aeabfca6454cec5ee Mon Sep 17 00:00:00 2001 From: ziin Date: Tue, 25 Nov 2025 16:20:23 +0800 Subject: [PATCH 28/37] =?UTF-8?q?refactor(system):=20=E4=B8=BA=E7=A7=9F?= =?UTF-8?q?=E6=88=B7=E6=B5=8B=E8=AF=95=E8=B4=A6=E5=8F=B7=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=A4=87=E6=B3=A8=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/system/service/tenant/TenantServiceImpl.java | 4 ++-- .../system/service/tenantbalance/TenantBalanceService.java | 4 ++-- .../service/tenantbalance/TenantBalanceServiceImpl.java | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index 672e644..73cb064 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -181,11 +181,11 @@ public class TenantServiceImpl implements TenantService { } // 开通测试套餐扣除测试账号数 if (tenantAgencyPackageDO.getPackageType().equals(PackageTypeEnum.TEST.getValue())){ - balanceService.reduceTestAccountNum(currentTenantId); + balanceService.reduceTestAccountNum(currentTenantId, createReqVO.getRemark()); } if (!tenantAgencyPackageDO.getPackageType().equals(PackageTypeEnum.AGENCY.getValue()) && !tenantAgencyPackageDO.getPackageType().equals(PackageTypeEnum.TEST.getValue())) { - balanceService.addTestAccountNum(currentTenantId); + balanceService.addTestAccountNum(currentTenantId, createReqVO.getRemark()); } // 在新创建的租户上下文中执行管理员初始化操作 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 7a0c201..adb7886 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 @@ -69,7 +69,7 @@ public interface TenantBalanceService { Boolean consumption(Long PackageId, Long targetTenantId,String remark); - Boolean reduceTestAccountNum(Long currentTenantId); + Boolean reduceTestAccountNum(Long currentTenantId, String remark); - Boolean addTestAccountNum(Long currentTenantId); + Boolean addTestAccountNum(Long currentTenantId, 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 792b1c0..4046ea6 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 @@ -359,7 +359,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { } @Override - public Boolean reduceTestAccountNum(Long currentTenantId) { + public Boolean reduceTestAccountNum(Long currentTenantId,String remark) { TenantBalanceDO tenantBalanceDO = tenantBalanceMapper.selectById(currentTenantId); if (tenantBalanceDO.getTestAccountNum()<=0) { throw exception(TENANT_BALANCE_TEST_ACCOUNT_NUM_NOT_ENOUGH); @@ -383,6 +383,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { tenantPointsDO.setOperatorId(loginUserId); // 设置操作人ID tenantPointsDO.setType(CONSUMPTION.getDesc()); // 设置交易类型为转账 tenantPointsDO.setDescription("开通测试账户"); // 设置交易描述 + tenantPointsDO.setRemark(remark); tenantPointsDO.setBizNo(consumption); // 设置业务流水号 int tenantInsert = tenantPointsMapper.insert(tenantPointsDO); // 插入记录 if (tenantInsert == 0) { @@ -392,7 +393,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { } @Override - public Boolean addTestAccountNum(Long currentTenantId) { + public Boolean addTestAccountNum(Long currentTenantId,String remark) { TenantBalanceDO tenantBalanceDO = tenantBalanceMapper.selectById(currentTenantId); Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); @@ -417,6 +418,7 @@ public class TenantBalanceServiceImpl implements TenantBalanceService { tenantPointsDO.setType(BONUS.getDesc()); // 设置交易类型为转账 tenantPointsDO.setDescription("开通测试账户,增加测试账号数量"); // 设置交易描述 tenantPointsDO.setBizNo(bonus); // 设置业务流水号 + tenantPointsDO.setRemark(remark); int tenantInsert = tenantPointsMapper.insert(tenantPointsDO); // 插入记录 if (tenantInsert == 0) { throw exception(TENANT_BALANCE_CONSUMPTION_OPERATION_ERROR); From d99bb17419643ec89f99c3d7e45f0f3f56e1dd36 Mon Sep 17 00:00:00 2001 From: ziin Date: Tue, 25 Nov 2025 18:40:36 +0800 Subject: [PATCH 29/37] =?UTF-8?q?fix(system):=20=E7=A7=BB=E9=99=A4BalanceE?= =?UTF-8?q?num=E4=B8=ADBONUS=E5=80=BC=E7=9A=84=E5=A4=9A=E4=BD=99=E7=A9=BA?= =?UTF-8?q?=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/module/system/enums/balance/BalanceEnum.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java index 8bf2ae2..a08a69a 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/balance/BalanceEnum.java @@ -18,7 +18,7 @@ public enum BalanceEnum { TRANSFER_OUT("转出"), TRANSFER_IN("转入"), CONSUMPTION("消费"), - BONUS(" 奖励"); + BONUS("奖励"); private String desc; From 42ec32581550d1cdb26a0980ade1d7c12efd5ca2 Mon Sep 17 00:00:00 2001 From: ziin Date: Wed, 26 Nov 2025 13:38:53 +0800 Subject: [PATCH 30/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E7=A7=9F=E6=88=B7=E7=BB=AD=E8=B4=B9=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=8F=8A=E5=A4=9A=E7=BA=A7=E4=BB=A3=E7=90=86=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/tenant/TenantController.java | 41 +++++++-- .../tenant/vo/tenant/TenantRenewalReqVO.java | 31 +++++++ .../admin/tenant/vo/tenant/TenantRespVO.java | 3 + .../dal/dataobject/tenant/TenantDO.java | 2 + .../system/dal/mysql/tenant/TenantMapper.java | 4 + .../dal/mysql/user/AdminUserMapper.java | 9 ++ .../system/enums/ErrorCodeConstants.java | 5 ++ .../system/service/tenant/TenantService.java | 5 ++ .../service/tenant/TenantServiceImpl.java | 86 +++++++++++++++++++ .../system/service/user/AdminUserService.java | 2 + .../service/user/AdminUserServiceImpl.java | 6 ++ .../main/resources/mapper/AdminUserMapper.xml | 63 ++++++++++++++ 12 files changed, 251 insertions(+), 6 deletions(-) create mode 100644 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRenewalReqVO.java diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java index 9d57581..b1245bf 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java @@ -9,10 +9,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantLevelRespVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantRespVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.*; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; import cn.iocoder.yudao.module.system.service.tenant.TenantService; import io.swagger.v3.oas.annotations.Operation; @@ -111,7 +108,11 @@ public class TenantController { @PreAuthorize("@ss.hasPermission('system:tenant:query')") public CommonResult> getTenantPage(@Valid TenantPageReqVO pageVO) { PageResult pageResult = tenantService.getTenantPage(pageVO); - return success(BeanUtils.toBean(pageResult, TenantRespVO.class)); + PageResult bean = BeanUtils.toBean(pageResult, TenantRespVO.class); + for (TenantRespVO tenantRespVO : bean.getList()) { + tenantRespVO.setHasChildren(tenantRespVO.getTenantType().equals("代理")); + } + return success(bean); } @GetMapping("/export-excel") @@ -135,7 +136,11 @@ public class TenantController { @PreAuthorize("@ss.hasPermission('system:tenant:query-self')") public CommonResult> getSelfTenantPage(@Valid TenantPageReqVO pageVO) { PageResult pageResult = tenantService.getSelfTenantPage(pageVO); - return success(BeanUtils.toBean(pageResult, TenantRespVO.class)); + PageResult bean = BeanUtils.toBean(pageResult, TenantRespVO.class); + for (TenantRespVO tenantRespVO : bean.getList()) { + tenantRespVO.setHasChildren(tenantRespVO.getTenantType().equals("代理")); + } + return success(bean); } @GetMapping("/getSelfTenantLevel") @@ -147,4 +152,28 @@ public class TenantController { return success(BeanUtils.toBean(tenant, TenantLevelRespVO.class)); } + + @GetMapping("/get-children") + @Operation(summary = "获得代理租户下级") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('system:tenant:query-children')") + public CommonResult> getChildrenTenant(@RequestParam("id") Long id) { + List tenantList = tenantService.getChildrenTenant(id); + List bean = BeanUtils.toBean(tenantList, TenantRespVO.class); + for (TenantRespVO tenantRespVO : bean) { + tenantRespVO.setHasChildren(tenantRespVO.getTenantType().equals("代理")); + } + return success(bean); + } + + + @PutMapping("/renewal") + @Operation(summary = "租户续费") + @PreAuthorize("@ss.hasPermission('system:tenant:renewal')") + public CommonResult renewalTenant(@Valid @RequestBody TenantRenewalReqVO renewalReqVO) { + tenantService.renewalTenant(renewalReqVO); + return success(true); + } + + } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRenewalReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRenewalReqVO.java new file mode 100644 index 0000000..2e054eb --- /dev/null +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRenewalReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; + +import cn.hutool.core.util.ObjectUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; + +/* + * @author: ziin + * @date: 2025/11/25 20:54 + */ +@Schema(description = "管理后台 - 租户续费 Request VO") +@Data +public class TenantRenewalReqVO { + @Schema(description = "租户编号", example = "1024") + private Long id; + + @Schema(description = "租户套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "租户套餐编号不能为空") + private Long packageId; + + @Schema(description = "备注", example = "备注") + private String remark; +} diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java index 3564a24..def5d13 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java @@ -72,4 +72,7 @@ public class TenantRespVO { @Schema(description = "租户等级",example = "1") private String tenantLevel; + + @Schema(description = "是否存在下级",example = "true") + private Boolean hasChildren; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java index 486af7b..9400f03 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java @@ -111,4 +111,6 @@ public class TenantDO extends BaseDO { * 代理级别 */ private Integer tenantLevel; + + private String initialUser; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java index dbd10fe..af18b79 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java @@ -78,4 +78,8 @@ public interface TenantMapper extends BaseMapperX { .likeIfPresent(TenantDO::getRemark, reqVO.getRemark()) .orderByDesc(TenantDO::getId)); } + + default List selectTenantByParentId(Long id){ + return selectList(TenantDO::getParentId, id); + } } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java index c303525..d598ead 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java @@ -3,10 +3,12 @@ package cn.iocoder.yudao.module.system.dal.mysql.user; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.Collection; import java.util.List; @@ -18,6 +20,7 @@ public interface AdminUserMapper extends BaseMapperX { return selectOne(AdminUserDO::getUsername, username); } + default AdminUserDO selectByUsernameAndTenantId(String username,Long tenantId) { return selectOne(AdminUserDO::getUsername, username ,AdminUserDO::getTenantId, tenantId); @@ -62,4 +65,10 @@ public interface AdminUserMapper extends BaseMapperX { } List selectTenantUserById(Long tenantId); + + @TenantIgnore + AdminUserDO selectByUsernameAndTenantIdWithAgencyRenewal(@Param("initialUser") String initialUser,@Param("targetTenantId") Long targetTenantId); + + @TenantIgnore + int updateByIdWithRenwal(AdminUserDO targetTenantUser); } 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 897c9df..9786772 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 @@ -111,11 +111,13 @@ public interface ErrorCodeConstants { ErrorCode TENANT_WEBSITE_DUPLICATE = new ErrorCode(1_002_015_005, "域名为【{}】的租户已存在"); ErrorCode TENANT_LEVEL_CANT_CREATE_AGENCY = new ErrorCode(1_002_015_006, "租户级别不能创建代理租户"); + // ========== 租户套餐 1-002-016-000 ========== ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1_002_016_000, "租户套餐不存在"); ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1_002_016_001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除"); ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1_002_016_002, "名字为【{}】的租户套餐已被禁用"); ErrorCode TENANT_PACKAGE_NAME_DUPLICATE = new ErrorCode(1_002_016_003, "已经存在该名字的租户套餐"); + ErrorCode TENANT_USER_NOT_EXISTS = new ErrorCode(1_002_016_004, "租户初始用户不存在"); // ========== 租户套餐 1-002-017-000 ========== ErrorCode TENANT_POINTS_NOT_EXISTS = new ErrorCode(1_002_017_000, "租户积分不存在"); @@ -138,6 +140,9 @@ public interface ErrorCodeConstants { ErrorCode TENANT_CREATE_FAIL = new ErrorCode(1_003_017_014, "租户创建失败"); ErrorCode TENANT_BALANCE_TEST_ACCOUNT_NUM_NOT_ENOUGH = new ErrorCode(1_003_017_015, "当前账户测试账户数量不足"); ErrorCode TENANT_BALANCE_TEST_ACCOUNT_NUM_OPERATION_ERROR = new ErrorCode(1_003_017_016, "租户测试账户数量操作错误"); + ErrorCode TENANT_IS_AGENCY = new ErrorCode(1_003_017_017, "代理租户,不能进行续费操作"); + ErrorCode TENANT_UPDATE_INITIAL_USER_INFO_FAIL = new ErrorCode(1_003_017_018, "更新租户初始用户信息失败"); + ErrorCode TENANT_RENEWAL_FAIL = new ErrorCode(1_003_017_019, "租户续费失败"); // ================= 租户套餐 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/tenant/TenantService.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java index e77b15e..3749144 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.service.tenant; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantRenewalReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler; @@ -136,4 +137,8 @@ public interface TenantService { void validTenant(Long id); PageResult getSelfTenantPage(@Valid TenantPageReqVO pageVO); + + List getChildrenTenant(Long id); + + void renewalTenant( TenantRenewalReqVO updateReqVO); } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index 73cb064..0482dd5 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -14,10 +14,12 @@ import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.tenant.config.TenantProperties; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantRenewalReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; import cn.iocoder.yudao.module.system.convert.tenant.TenantConvert; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; @@ -48,6 +50,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; @@ -97,6 +100,9 @@ public class TenantServiceImpl implements TenantService { private AdminUserMapper userMapper; @Resource private TenantBalanceService balanceService; + @Autowired + private TenantBalanceService tenantBalanceService; + @Override public List getTenantIdList() { List tenants = tenantMapper.selectList(); @@ -124,6 +130,84 @@ public class TenantServiceImpl implements TenantService { return tenantMapper.selectSelfPage(pageVO); } + @Override + public List getChildrenTenant(Long id) { + return tenantMapper.selectTenantByParentId(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @TenantIgnore + public void renewalTenant(TenantRenewalReqVO updateReqVO) { + // 校验租户是否存在 + TenantDO targetTenant = getTenant(updateReqVO.getId()); + Long currentTenantId = TenantContextHolder.getTenantId(); + if (targetTenant == null) { + throw exception(TENANT_NOT_EXISTS); + } + + // 校验租户是否为代理类型 + if (targetTenant.getTenantType().equals(TenantEnum.AGENCY.getTenantType())) { + throw exception(TENANT_IS_AGENCY); + } + + TenantAgencyPackageDO tenantAgencyPackage = tenantAgencyPackageService.getTenantAgencyPackage(updateReqVO.getPackageId()); + + TenantBalanceDO tenantBalance = tenantBalanceService.getTenantBalance(currentTenantId); + + AdminUserDO targetTenantUser = userService.getUserByTenantIdAndUserName(updateReqVO.getId(), targetTenant.getInitialUser()); + + + if (targetTenantUser == null) { + throw exception(TENANT_USER_NOT_EXISTS); + } + + if (tenantBalance.getBalance()<=tenantAgencyPackage.getPrice()){ + throw exception(TENANT_BALANCE_NOT_ENOUGH); + } + + if (balanceService.consumption(tenantAgencyPackage.getId(), targetTenant.getId(), updateReqVO.getRemark())) { + log.info("代理: {} 续费租户:{} 成功,套餐 Id:{}", currentTenantId,targetTenant.getId(),updateReqVO.getPackageId()); + } + + if (targetTenant.getExpireTime().isBefore(LocalDateTime.now())){ + targetTenant.setExpireTime(LocalDateTime.now().plusDays(tenantAgencyPackage.getDays())); + targetTenant.setStatus(CommonStatusEnum.ENABLE.getStatus()); + targetTenantUser.setCrawl((byte) 1); + }else { + targetTenant.setExpireTime(targetTenant.getExpireTime().plusDays(tenantAgencyPackage.getDays())); + } + + if (tenantAgencyPackage.getAiClient()==1){ + if (targetTenant.getAiExpireTime().isBefore(LocalDateTime.now())){ + targetTenant.setAiExpireTime(LocalDateTime.now().plusDays(tenantAgencyPackage.getDays())); + targetTenantUser.setAiReplay((byte) 1); + targetTenantUser.setAiChat((byte) 1); + }else { + targetTenant.setAiExpireTime(targetTenant.getAiExpireTime().plusDays(tenantAgencyPackage.getDays())); + } + } + + if (tenantAgencyPackage.getBrotherClient() ==1 ){ + if (targetTenant.getBrotherExpireTime().isBefore(LocalDateTime.now())){ + targetTenant.setBrotherExpireTime(LocalDateTime.now().plusDays(tenantAgencyPackage.getDays())); + targetTenantUser.setBigBrother((byte) 1); + }else { + targetTenant.setBrotherExpireTime(targetTenant.getBrotherExpireTime().plusDays(tenantAgencyPackage.getDays())); + } + } + int updateInitialUserCount = userMapper.updateByIdWithRenwal(targetTenantUser); + if (updateInitialUserCount <= 0) { + throw exception(TENANT_UPDATE_INITIAL_USER_INFO_FAIL); + } + + int updateTenantCount = tenantMapper.updateById(targetTenant); + if (updateTenantCount <= 0) { + throw exception(TENANT_RENEWAL_FAIL); + } + + } + @Override @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换 @DataPermission(enable = false) // 参见 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1154 说明 @@ -157,6 +241,7 @@ public class TenantServiceImpl implements TenantService { LocalDateTime localDateTime = LocalDateTimeUtil.of(dt); LocalDateTime offset = LocalDateTimeUtil.offset(localDateTime, tenantAgencyPackageDO.getDays(), ChronoUnit.DAYS); tenant.setExpireTime(offset); + tenant.setInitialUser(createReqVO.getUsername()); if (tenantAgencyPackageDO.getBrotherClient() == 1){ tenant.setBrotherExpireTime(offset); } @@ -274,6 +359,7 @@ public class TenantServiceImpl implements TenantService { tenantBalance.setId(tenant.getId()); // 钱包ID与租户ID一致 tenantBalance.setBalance(0); // 初始余额设为0 tenantBalance.setVersion(0); // 初始版本号设为0 + tenantBalance.setTestAccountNum(15); tenantBalanceMapper.insert(tenantBalance); // 插入钱包记录 } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java index 0b45730..9361d31 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java @@ -209,4 +209,6 @@ public interface AdminUserService { List getTenantUserById(Long tenantId); void updateUserWithClientRole(@Valid UserClientSaveReqVO reqVO); + + AdminUserDO getUserByTenantIdAndUserName(Long targetTenantId, String initialUser); } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java index f4cf966..cf17221 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.infra.api.config.ConfigApi; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO; import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; @@ -552,6 +553,11 @@ public class AdminUserServiceImpl implements AdminUserService { userMapper.updateById(updateObj); } + @Override + public AdminUserDO getUserByTenantIdAndUserName(Long targetTenantId, String initialUser) { + return userMapper.selectByUsernameAndTenantIdWithAgencyRenewal(initialUser,targetTenantId); + } + private AdminUserDO validateUserForCreateOrUpdate(Long id, String username,Long tenantId) { return DataPermissionUtils.executeIgnore(() -> { diff --git a/yudao-module-system/src/main/resources/mapper/AdminUserMapper.xml b/yudao-module-system/src/main/resources/mapper/AdminUserMapper.xml index 7ed6ff6..6a32c37 100644 --- a/yudao-module-system/src/main/resources/mapper/AdminUserMapper.xml +++ b/yudao-module-system/src/main/resources/mapper/AdminUserMapper.xml @@ -16,4 +16,67 @@ select * from system_users where tenant_id=#{tenantId,jdbcType=BIGINT} + + + + + update system_users set + + username = #{username,jdbcType=VARCHAR}, + + + password = #{password,jdbcType=VARCHAR}, + + + nickname = #{nickname,jdbcType=VARCHAR}, + + + remark = #{remark,jdbcType=VARCHAR}, + + + dept_id = #{deptId,jdbcType=BIGINT}, + + + post_ids = #{postIds,jdbcType=VARCHAR,typeHandler=com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler}, + + + email = #{email,jdbcType=VARCHAR}, + + + mobile = #{mobile,jdbcType=VARCHAR}, + + + sex = #{sex,jdbcType=INTEGER}, + + + avatar = #{avatar,jdbcType=VARCHAR}, + + + status = #{status,jdbcType=INTEGER}, + + + login_ip = #{loginIp,jdbcType=VARCHAR}, + + + login_date = #{loginDate,jdbcType=TIMESTAMP}, + + + crawl = #{crawl,jdbcType=TINYINT}, + + + big_brother = #{bigBrother,jdbcType=TINYINT}, + + + ai_chat = #{aiChat,jdbcType=TINYINT}, + + + ai_replay = #{aiReplay,jdbcType=TINYINT}, + + update_time = NOW() + where id = #{id,jdbcType=BIGINT} + \ No newline at end of file From 646bc77c7b010e7aff429ac5536a548d9d87e8d4 Mon Sep 17 00:00:00 2001 From: ziin Date: Wed, 26 Nov 2025 16:13:17 +0800 Subject: [PATCH 31/37] =?UTF-8?q?fix(system):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E5=A5=97=E9=A4=90=E7=9A=84=E7=A7=9F=E6=88=B7?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/tenant/TenantServiceImpl.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index 0482dd5..d158c06 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -407,15 +407,27 @@ public class TenantServiceImpl implements TenantService { // 校验租户域名是否重复 validTenantWebsiteDuplicate(updateReqVO.getWebsite(), updateReqVO.getId()); // 校验套餐被禁用 - TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(updateReqVO.getPackageId()); - // 更新租户 - TenantDO updateObj = BeanUtils.toBean(updateReqVO, TenantDO.class); - tenantMapper.updateById(updateObj); - // 如果套餐发生变化,则修改其角色的权限 - if (ObjectUtil.notEqual(tenant.getPackageId(), updateReqVO.getPackageId())) { - updateTenantRoleMenu(tenant.getId(), tenantPackage.getMenuIds()); + if (updateReqVO.getTenantType().equals(TenantEnum.AGENCY.getTenantType())) { + TenantAgencyPackageDO tenantAgencyPackageDO = tenantAgencyPackageService.validTenantPackage(updateReqVO.getPackageId()); + // 更新租户 + TenantDO updateObj = BeanUtils.toBean(updateReqVO, TenantDO.class); + tenantMapper.updateById(updateObj); + // 如果套餐发生变化,则修改其角色的权限 + if (ObjectUtil.notEqual(tenant.getPackageId(), updateReqVO.getPackageId())) { + updateTenantRoleMenu(tenant.getId(), tenantAgencyPackageDO.getMenuIds()); + } + }else { + TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(updateReqVO.getPackageId()); + // 更新租户 + TenantDO updateObj = BeanUtils.toBean(updateReqVO, TenantDO.class); + tenantMapper.updateById(updateObj); + // 如果套餐发生变化,则修改其角色的权限 + if (ObjectUtil.notEqual(tenant.getPackageId(), updateReqVO.getPackageId())) { + updateTenantRoleMenu(tenant.getId(), tenantPackage.getMenuIds()); + } } + } private void validTenantNameDuplicate(String name, Long id) { From aebeaaeabefc059d30a22ea224032ea0e2a779aa Mon Sep 17 00:00:00 2001 From: ziin Date: Wed, 26 Nov 2025 20:20:20 +0800 Subject: [PATCH 32/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9EAI?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=9B=9E=E5=A4=8D=E6=9D=83=E9=99=90=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E5=B9=B6=E8=A1=A5=E5=85=85=E5=AD=97=E6=AE=B5=E5=A4=87?= =?UTF-8?q?=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在代理套餐及积分相关VO/DO中: - 新增 aiReplay 字段(0关闭 1开启) - 为租户积分记录补充 remark 字段及描述 - 同步更新相关查询、保存、响应VO与Service实现 --- .../vo/TenantAgencyPackagePageReqVO.java | 3 +++ .../vo/TenantAgencyPackageRespVO.java | 3 +++ .../vo/TenantAgencyPackageSaveReqVO.java | 2 ++ .../vo/TenantPointsPageRespVO.java | 4 ++++ .../TenantAgencyPackageDO.java | 5 ++++- .../service/tenant/TenantServiceImpl.java | 21 ++++++++++++++----- 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java index 1345191..515d8ed 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java @@ -44,6 +44,9 @@ public class TenantAgencyPackagePageReqVO extends PageParam { @Schema(description = "AI 客户端 0 关闭 1 开启") private Integer aiClient; + @Schema(description = "Ai自动回复权限 0关闭 1 开启") + private Integer aiReplay; + @Schema(description = "套餐类型", example = "2") private Integer packageType; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java index 2beb224..d40b8c5 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java @@ -60,4 +60,7 @@ public class TenantAgencyPackageRespVO { @ExcelProperty("套餐类型") private Integer packageType; + @Schema(description = "Ai自动回复权限 0关闭 1 开启") + @ExcelProperty("Ai 自动回复权限 0关闭 1开启") + private Integer aiReplay; } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java index 49e0004..6ad445f 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java @@ -47,4 +47,6 @@ public class TenantAgencyPackageSaveReqVO { @Schema(description = "套餐类型", example = "2") private Integer packageType; + @Schema(description = "Ai自动回复权限 0关闭 1 开启") + private Integer aiReplay; } \ No newline at end of file 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 f455491..170fd00 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 @@ -59,4 +59,8 @@ public class TenantPointsPageRespVO { @Schema(description = "测试账号数", example = "1") @ExcelProperty("测试账号数") private Integer testAccountNum; + + @Schema(description = "备注", example = "转账金额:1000") + @ExcelProperty("备注") + private String remark; } \ No newline at end of file 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 e56ec4f..8b39f38 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 @@ -74,5 +74,8 @@ public class TenantAgencyPackageDO extends BaseDO { */ private Integer packageType; - + /** + * Ai自动回复权限 0关闭 1开启 + */ + private Integer aiReplay; } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index d158c06..e6d202f 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -236,15 +236,24 @@ public class TenantServiceImpl implements TenantService { // 将请求参数转换为租户数据对象 TenantDO tenant = BeanUtils.toBean(createReqVO, TenantDO.class); - String now = DateUtil.now(); - DateTime dt = DateUtil.parse(now); - LocalDateTime localDateTime = LocalDateTimeUtil.of(dt); + // 获取当前时间并计算租户过期时间 + String now = DateUtil.now(); // 获取当前时间字符串 + DateTime dt = DateUtil.parse(now); // 将时间字符串解析为DateTime对象 + LocalDateTime localDateTime = LocalDateTimeUtil.of(dt); // 转换为LocalDateTime对象 + // 根据套餐天数计算过期时间:当前时间 + 套餐天数 LocalDateTime offset = LocalDateTimeUtil.offset(localDateTime, tenantAgencyPackageDO.getDays(), ChronoUnit.DAYS); + + // 设置租户的基本过期时间 tenant.setExpireTime(offset); + // 设置租户的初始用户名(创建者) tenant.setInitialUser(createReqVO.getUsername()); + + // 根据套餐配置设置特定功能的过期时间 + // 如果套餐包含"大哥客户端"功能,则设置大哥客户端的过期时间 if (tenantAgencyPackageDO.getBrotherClient() == 1){ tenant.setBrotherExpireTime(offset); } + // 如果套餐包含"AI客户端"功能,则设置AI客户端的过期时间 if (tenantAgencyPackageDO.getAiClient() == 1){ tenant.setAiExpireTime(offset); } @@ -284,11 +293,13 @@ public class TenantServiceImpl implements TenantService { if (tenantAgencyPackageDO.getHostslClient() == 1){ user.setCrawl((byte) 1); } - if (tenantAgencyPackageDO.getHostslClient() == 1){ + if (tenantAgencyPackageDO.getBrotherClient() == 1){ user.setBigBrother((byte) 1); } if (tenantAgencyPackageDO.getAiClient() == 1){ user.setAiChat((byte) 1); + } + if (tenantAgencyPackageDO.getAiReplay() == 1){ user.setAiReplay((byte) 1); } userMapper.updateById(user); @@ -408,7 +419,7 @@ public class TenantServiceImpl implements TenantService { validTenantWebsiteDuplicate(updateReqVO.getWebsite(), updateReqVO.getId()); // 校验套餐被禁用 - if (updateReqVO.getTenantType().equals(TenantEnum.AGENCY.getTenantType())) { + if (updateReqVO.getTenantType().equals(TenantEnum.AGENCY.getTenantType()) || tenant.getParentId() != 1) { TenantAgencyPackageDO tenantAgencyPackageDO = tenantAgencyPackageService.validTenantPackage(updateReqVO.getPackageId()); // 更新租户 TenantDO updateObj = BeanUtils.toBean(updateReqVO, TenantDO.class); From cdaf7ce631fe7e04f7fa31ae29e48eb23001085e Mon Sep 17 00:00:00 2001 From: ziin Date: Thu, 27 Nov 2025 13:26:32 +0800 Subject: [PATCH 33/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9EAi?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=9B=9E=E5=A4=8D=E6=9D=83=E9=99=90=E5=AD=97?= =?UTF-8?q?=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/AgencyTenantPackageSimpleRespVO.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java index a0003b4..dda04b7 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java @@ -17,4 +17,7 @@ public class AgencyTenantPackageSimpleRespVO { @NotNull(message = "套餐名不能为空") private String name; + @Schema(description = "Ai自动回复权限 0关闭 1 开启", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "Ai自动回复权限不能为空") + private Integer aiReplay; } From 7cda6e8781ad2771e26a9cd4c73774e93ce30c95 Mon Sep 17 00:00:00 2001 From: ziin Date: Thu, 27 Nov 2025 14:18:44 +0800 Subject: [PATCH 34/37] =?UTF-8?q?feat(test):=20=E6=96=B0=E5=A2=9E=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=8E=AF=E5=A2=83=E4=B8=93=E7=94=A8=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-test.yaml | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 yudao-server/src/main/resources/application-test.yaml diff --git a/yudao-server/src/main/resources/application-test.yaml b/yudao-server/src/main/resources/application-test.yaml new file mode 100644 index 0000000..86ce684 --- /dev/null +++ b/yudao-server/src/main/resources/application-test.yaml @@ -0,0 +1,216 @@ +server: + port: 48080 + +--- #################### 数据库相关配置 #################### +spring: + autoconfigure: + # noinspection SpringBootApplicationYaml + exclude: + - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 +# - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置 + - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 + - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 + - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 + - org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建 + - org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建 + # 数据源配置项 + datasource: + druid: # Druid 【监控】相关的全局配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + allow: # 设置白名单,不填则允许所有访问 + url-pattern: /druid/* + login-username: # 控制台管理用户名和密码 + login-password: + filter: + stat: + enabled: true + log-slow-sql: true # 慢 SQL 记录 + slow-sql-millis: 100 + merge-sql: true + wall: + config: + multi-statement-allow: true + dynamic: # 多数据源配置 + druid: # Druid 【连接池】相关的全局配置 + initial-size: 1 # 初始连接数 + min-idle: 1 # 最小连接池数量 + max-active: 20 # 最大连接池数量 + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 + test-while-idle: true + test-on-borrow: false + test-on-return: false + primary: master + datasource: + master: + url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&allowMultiQueries=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例 + # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 + # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer 连接的示例 + # url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 + # url: jdbc:kingbase8://127.0.0.1:54321/test # 人大金仓 KingbaseES 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 连接的示例 + username: ruoyi-vue-pro + password: ki7kbrP3TXADPddS + # username: sa # SQL Server 连接的示例 + # password: Yudao@2024 # SQL Server 连接的示例 + # username: SYSDBA # DM 连接的示例 + # password: SYSDBA001 # DM 连接的示例 + # username: root # OpenGauss 连接的示例 + # password: Yudao@2024 # OpenGauss 连接的示例 +# slave: # 模拟从库,可根据自己需要修改 +# lazy: true # 开启懒加载,保证启动速度 +# url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true +# username: root +# password: 123456 +# tdengine: # IoT 数据库(需要 IoT 物联网再开启噢!) +# url: jdbc:TAOS-RS://127.0.0.1:6041/ruoyi_vue_pro +# driver-class-name: com.taosdata.jdbc.rs.RestfulDriver +# username: root +# password: taosdata +# druid: +# validation-query: SELECT SERVER_STATUS() # TDengine 数据源的有效性检查 SQL + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + redis: + host: 127.0.0.1 # 地址 + port: 6379 # 端口 + database: 0 # 数据库索引 +# password: dev # 密码,建议生产环境开启 + +--- #################### 定时任务相关配置 #################### + +# Quartz 配置项,对应 QuartzProperties 配置类 +spring: + quartz: + auto-startup: true # 本地开发环境,尽量不要开启 Job + scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName + job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。 + wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true + properties: # 添加 Quartz Scheduler 附加属性,更多可以看 http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html 文档 + org: + quartz: + # Scheduler 相关配置 + scheduler: + instanceName: schedulerName + instanceId: AUTO # 自动生成 instance ID + # JobStore 相关配置 + jobStore: + # JobStore 实现类。可见博客:https://blog.csdn.net/weixin_42458219/article/details/122247162 + class: org.springframework.scheduling.quartz.LocalDataSourceJobStore + isClustered: true # 是集群模式 + clusterCheckinInterval: 15000 # 集群检查频率,单位:毫秒。默认为 15000,即 15 秒 + misfireThreshold: 60000 # misfire 阀值,单位:毫秒。 + # 线程池相关配置 + threadPool: + threadCount: 25 # 线程池大小。默认为 10 。 + threadPriority: 5 # 线程优先级 + class: org.quartz.simpl.SimpleThreadPool # 线程池类型 + jdbc: # 使用 JDBC 的 JobStore 的时候,JDBC 的配置 + initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。 + +--- #################### 消息队列相关 #################### + +spring: + # RabbitMQ 配置项,对应 RabbitProperties 配置类 + rabbitmq: + host: 127.0.0.1 # RabbitMQ 服务的地址 + port: 5672 # RabbitMQ 服务的端口 + username: guest # RabbitMQ 服务的账号 + password: guest # RabbitMQ 服务的密码 + + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项 +lock4j: + acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 + expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 + +--- #################### 监控相关配置 #################### + +# Actuator 监控端点的配置项 +management: + endpoints: + web: + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator + exposure: + include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 + +# Spring Boot Admin 配置项 +spring: + boot: + admin: + # Spring Boot Admin Client 客户端的相关配置 + client: + url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址 + instance: + service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME] + # Spring Boot Admin Server 服务端的相关配置 + context-path: /admin # 配置 Spring + +# 日志文件配置 +logging: + file: + name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 + level: + # 配置自己写的 MyBatis Mapper 打印日志 + cn.iocoder.yudao.module.bpm.dal.mysql: debug + cn.iocoder.yudao.module.infra.dal.mysql: debug + cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper: INFO # 配置 ApiErrorLogMapper 的日志级别为 info,避免和 GlobalExceptionHandler 重复打印 + cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info + cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper: INFO # 配置 FileConfigMapper 的日志级别为 info + cn.iocoder.yudao.module.pay.dal.mysql: debug + cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 PayNotifyTaskMapper 的日志级别为 info + cn.iocoder.yudao.module.system.dal.mysql: debug + cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info + cn.iocoder.yudao.module.tool.dal.mysql: debug + cn.iocoder.yudao.module.member.dal.mysql: debug + cn.iocoder.yudao.module.trade.dal.mysql: debug + cn.iocoder.yudao.module.promotion.dal.mysql: debug + cn.iocoder.yudao.module.statistics.dal.mysql: debug + cn.iocoder.yudao.module.crm.dal.mysql: debug + cn.iocoder.yudao.module.erp.dal.mysql: debug + cn.iocoder.yudao.module.iot.dal.mysql: debug + cn.iocoder.yudao.module.iot.dal.tdengine: DEBUG + cn.iocoder.yudao.module.ai.dal.mysql: debug + cn.iocoder.yudao.module.tkdata.dal.mysql: debug + org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示 + +debug: false + + + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + captcha: + enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试; + security: + mock-enable: true + pay: + order-notify-url: https://yutou.mynatapp.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址 + refund-notify-url: https://yutou.mynatapp.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址 + transfer-notify-url: https://yutou.mynatapp.cc/admin-api/pay/notify/transfer # 支付渠道的【转账】回调地址 + access-log: # 访问日志的配置项 + enable: false + demo: false # 关闭演示模式 + wxa-code: + env-version: develop # 小程序版本: 正式版为 "release";体验版为 "trial";开发版为 "develop" + wxa-subscribe-message: + miniprogram-state: developer # 跳转小程序类型:开发版为 “developer”;体验版为 “trial”为;正式版为 “formal” + tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc + + +--- #################### iot相关配置 TODO 芋艿【IOT】:再瞅瞅 #################### +pf4j: +# pluginsDir: /tmp/ + pluginsDir: ../plugins \ No newline at end of file From cece05fd1f800ec5dcc2e797c8ed58a8984d0677 Mon Sep 17 00:00:00 2001 From: ziin Date: Fri, 28 Nov 2025 14:27:39 +0800 Subject: [PATCH 35/37] =?UTF-8?q?refactor(tenant-package):=20=E7=B2=BE?= =?UTF-8?q?=E7=AE=80=E4=BB=A3=E7=90=86=E5=A5=97=E9=A4=90VO=E5=B9=B6?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=9E=9A=E4=B8=BE=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 去除AgencyTenantPackageSimpleRespVO的冗余校验注解 - 调整PackageTypeEnum代理类型数值199→999 - 精简列表接口返回TenantAgencyPackageDO并补充packageType、price字段 - 同步更新Service与Controller类型与调用链 --- .../admin/tenant/TenantPackageController.java | 3 ++- .../vo/packages/TenantPackageSimpleRespVO.java | 3 +++ .../vo/AgencyTenantPackageSimpleRespVO.java | 14 +++++++------- .../enums/agencyTenantPackage/PackageTypeEnum.java | 2 +- .../service/tenant/TenantPackageService.java | 3 ++- .../service/tenant/TenantPackageServiceImpl.java | 9 +++++---- .../src/main/resources/application-dev.yaml | 3 +++ .../src/main/resources/application-local.yaml | 2 +- 8 files changed, 24 insertions(+), 15 deletions(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantPackageController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantPackageController.java index f523d51..2958275 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantPackageController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantPackageController.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.*; 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.service.tenant.TenantPackageService; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Parameter; @@ -73,7 +74,7 @@ public class TenantPackageController { @GetMapping({"/get-simple-list", "simple-list"}) @Operation(summary = "获取租户套餐精简信息列表", description = "只包含被开启的租户套餐,主要用于前端的下拉选项") public CommonResult> getTenantPackageList() { - List list = tenantPackageService.getTenantPackageListByStatus(CommonStatusEnum.ENABLE.getStatus()); + List list = tenantPackageService.getTenantPackageListByStatus(CommonStatusEnum.ENABLE.getStatus()); return success(BeanUtils.toBean(list, TenantPackageSimpleRespVO.class)); } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSimpleRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSimpleRespVO.java index bc3d62a..91af9fd 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSimpleRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSimpleRespVO.java @@ -17,4 +17,7 @@ public class TenantPackageSimpleRespVO { @NotNull(message = "套餐名不能为空") private String name; + private Integer packageType; + + private Integer price; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java index dda04b7..0148bcc 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/AgencyTenantPackageSimpleRespVO.java @@ -9,15 +9,15 @@ import javax.validation.constraints.NotNull; @Data public class AgencyTenantPackageSimpleRespVO { - @Schema(description = "套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "套餐编号不能为空") + @Schema(description = "套餐编号", example = "1024") private Long id; - @Schema(description = "套餐名", requiredMode = Schema.RequiredMode.REQUIRED, example = "VIP") - @NotNull(message = "套餐名不能为空") + @Schema(description = "套餐名", example = "VIP") private String name; - @Schema(description = "Ai自动回复权限 0关闭 1 开启", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "Ai自动回复权限不能为空") - private Integer aiReplay; + @Schema(description = "Ai自动回复权限 0关闭 1 开启", example = "1") + private Integer packageType; + + @Schema(description = "套餐价格", example = "1000") + private Integer price; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/agencyTenantPackage/PackageTypeEnum.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/agencyTenantPackage/PackageTypeEnum.java index aee0460..298e97c 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/agencyTenantPackage/PackageTypeEnum.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/agencyTenantPackage/PackageTypeEnum.java @@ -14,7 +14,7 @@ public enum PackageTypeEnum { CRAWL(1, "爬虫"), BROTHER_CRAWL(2, "兄弟爬虫"), TEST(99, "测试账户"), - AGENCY(199, "代理"); + AGENCY(999, "代理"); private final Integer value; private final String name; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageService.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageService.java index 1abe4fe..c190ab7 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageService.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageService.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; +import cn.iocoder.yudao.module.system.dal.dataobject.tenantagencypackage.TenantAgencyPackageDO; import javax.validation.Valid; import java.util.List; @@ -67,6 +68,6 @@ public interface TenantPackageService { * @param status 状态 * @return 租户套餐 */ - List getTenantPackageListByStatus(Integer status); + List getTenantPackageListByStatus(Integer status); } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java index 7b0b3d5..88d8123 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java @@ -121,13 +121,14 @@ public class TenantPackageServiceImpl implements TenantPackageService { } @Override - public List getTenantPackageListByStatus(Integer status) { + public List getTenantPackageListByStatus(Integer status) { Long tenantId = TenantContextHolder.getTenantId(); if (tenantId != 1) { - List tenantAgencyPackageDOS = tenantAgencyPackageMapper.selectListByStatus(status); - return BeanUtils.toBean(tenantAgencyPackageDOS, TenantPackageDO.class); + return tenantAgencyPackageMapper.selectListByStatus(status); } - return tenantPackageMapper.selectListByStatus(status); + List tenantPackageDOS = tenantPackageMapper.selectListByStatus(status); + return BeanUtils.toBean(tenantPackageDOS, TenantAgencyPackageDO.class); + } diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 8da4943..999695d 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -7,6 +7,9 @@ spring: autoconfigure: exclude: - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 禁用 AI 模块的 Milvus,手动创建 + - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 + - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 + - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 # 数据源配置项 datasource: diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index b7307c1..b1e2b79 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -12,7 +12,7 @@ spring: - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 - org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建 - - org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建 + - org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模tenant-agency-package/get-simple-list块的 Milvus,手动创建 # 数据源配置项 datasource: druid: # Druid 【监控】相关的全局配置 From aa3171d1ab381ed356b095a5ec346942a010a20c Mon Sep 17 00:00:00 2001 From: ziin Date: Fri, 5 Dec 2025 15:11:36 +0800 Subject: [PATCH 36/37] =?UTF-8?q?feat(system):=20=E6=96=B0=E5=A2=9E=20Web?= =?UTF-8?q?=20AI=20=E5=AE=A2=E6=88=B7=E7=AB=AF=E6=9D=83=E9=99=90=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java | 4 ++++ .../tenantagencypackage/vo/TenantAgencyPackageRespVO.java | 4 ++++ .../tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java | 3 +++ .../controller/admin/user/vo/user/UserClientSaveReqVO.java | 3 +++ .../system/controller/admin/user/vo/user/UserRespVO.java | 3 +++ .../system/controller/admin/user/vo/user/UserSaveReqVO.java | 3 +++ .../tenantagencypackage/TenantAgencyPackageDO.java | 5 +++++ .../yudao/module/system/dal/dataobject/user/AdminUserDO.java | 3 +++ .../module/system/service/tenant/TenantServiceImpl.java | 4 ++++ 9 files changed, 32 insertions(+) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java index 515d8ed..f62954f 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackagePageReqVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.controller.admin.tenantagencypackage.vo; +import com.alibaba.excel.annotation.ExcelProperty; import lombok.*; import java.util.*; import io.swagger.v3.oas.annotations.media.Schema; @@ -50,4 +51,7 @@ public class TenantAgencyPackagePageReqVO extends PageParam { @Schema(description = "套餐类型", example = "2") private Integer packageType; + @Schema(description = "WebAi权限 0关闭 1开启") + private Integer webAi; + } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java index d40b8c5..dffd552 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageRespVO.java @@ -63,4 +63,8 @@ public class TenantAgencyPackageRespVO { @Schema(description = "Ai自动回复权限 0关闭 1 开启") @ExcelProperty("Ai 自动回复权限 0关闭 1开启") private Integer aiReplay; + + @Schema(description = "WebAi权限 0关闭 1开启") + @ExcelProperty("WebAi权限 0关闭 1开启") + private Integer webAi; } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java index 6ad445f..c124bac 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenantagencypackage/vo/TenantAgencyPackageSaveReqVO.java @@ -49,4 +49,7 @@ public class TenantAgencyPackageSaveReqVO { @Schema(description = "Ai自动回复权限 0关闭 1 开启") private Integer aiReplay; + + @Schema(description = "WebAi权限 0关闭 1开启") + private Integer webAi; } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserClientSaveReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserClientSaveReqVO.java index e0d5e7e..bbb4fdd 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserClientSaveReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserClientSaveReqVO.java @@ -36,4 +36,7 @@ public class UserClientSaveReqVO { @Schema(description = "是否允许使用 AI 回复", example = "0不允许,1允许") private Byte aiReplay; + + @Schema(description = "是否允许登录 Web AI 客户端", example = "0不允许,1允许") + private Byte webAi; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java index 4f4cffd..3745302 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java @@ -83,4 +83,7 @@ public class UserRespVO{ @Schema(description = "是否允许使用 AI 回复", example = "0不允许,1允许") private Byte aiReplay; + + @Schema(description = "是否允许登录 Web AI 客户端", example = "0不允许,1允许") + private Byte webAi; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java index be7689b..091525e 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java @@ -91,4 +91,7 @@ public class UserSaveReqVO { @Schema(description = "是否允许使用 AI 回复", example = "0不允许,1允许") private Byte aiReplay; + + @Schema(description = "是否允许登录 Web AI 客户端", example = "0不允许,1允许") + private Byte webAi; } 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 8b39f38..1a4b31c 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 @@ -78,4 +78,9 @@ public class TenantAgencyPackageDO extends BaseDO { * Ai自动回复权限 0关闭 1开启 */ private Integer aiReplay; + + /** + * WebAi权限 0关闭 1开启 + */ + private Integer webAi; } \ No newline at end of file diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java index b0a20c7..08cb237 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java @@ -108,4 +108,7 @@ public class AdminUserDO extends TenantBaseDO { @Schema(description = "是否允许使用AI回复", example = "0不允许,1允许") private Byte aiReplay; + + @Schema(description = "是否允许登录Web AI客户端", example = "0不允许,1允许") + private Byte webAi; } diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index e6d202f..69a7877 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -257,6 +257,7 @@ public class TenantServiceImpl implements TenantService { if (tenantAgencyPackageDO.getAiClient() == 1){ tenant.setAiExpireTime(offset); } + if(tenantAgencyPackageDO.getBrotherClient() == 2){} // 设置新租户的级别为当前租户级别+1(层级关系) if (createReqVO.getTenantType().equals(TenantEnum.AGENCY.getTenantType())){ tenant.setTenantLevel(currentTenant.getTenantLevel() + 1); @@ -302,6 +303,9 @@ public class TenantServiceImpl implements TenantService { if (tenantAgencyPackageDO.getAiReplay() == 1){ user.setAiReplay((byte) 1); } + if (tenantAgencyPackageDO.getWebAi() == 1){ + user.setWebAi((byte) 1); + } userMapper.updateById(user); // 将创建的用户设置为租户的联系人(管理员) tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId)); From 4dffbb4e11dc41b9eb99c558c1d7667909a7f50a Mon Sep 17 00:00:00 2001 From: ziin Date: Fri, 5 Dec 2025 20:37:22 +0800 Subject: [PATCH 37/37] =?UTF-8?q?fix(system):=20=E4=B8=BA=E7=A7=9F?= =?UTF-8?q?=E6=88=B7=E5=A5=97=E9=A4=90=E5=93=8D=E5=BA=94VO=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=AD=97=E6=AE=B5Swagger=E6=B3=A8=E8=A7=A3=E5=B9=B6?= =?UTF-8?q?=E8=A1=A5=E5=85=85days=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/tenant/vo/packages/TenantPackageSimpleRespVO.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSimpleRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSimpleRespVO.java index 91af9fd..5a07ce7 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSimpleRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSimpleRespVO.java @@ -17,7 +17,12 @@ public class TenantPackageSimpleRespVO { @NotNull(message = "套餐名不能为空") private String name; + @Schema(description = "套餐类型", example = "1") private Integer packageType; + @Schema(description = "套餐价格", example = "30") private Integer price; + + @Schema(description = "套餐有效期天数", example = "30") + private Integer days; }