From 848fcdf329d2df1e9b5f0028e6b359c370b10e75 Mon Sep 17 00:00:00 2001
From: YunaiV <zhijiantianya@gmail.com>
Date: Wed, 23 Feb 2022 19:08:45 +0800
Subject: [PATCH] =?UTF-8?q?=E7=A7=9F=E6=88=B7=E5=88=9B=E5=BB=BA=E4=BA=BA?=
 =?UTF-8?q?=E6=95=B0=E7=9A=84=E9=99=90=E5=88=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../mybatis/core/mapper/BaseMapperX.java      |  4 ++++
 .../system/enums/ErrorCodeConstants.java      |  3 ++-
 .../system/service/tenant/TenantService.java  | 10 ++++++++-
 .../service/tenant/TenantServiceImpl.java     | 15 +++++++++++++
 .../tenant/handler/TenantInfoHandler.java     | 21 +++++++++++++++++++
 .../service/user/AdminUserServiceImpl.java    | 10 +++++++++
 6 files changed, 61 insertions(+), 2 deletions(-)
 create mode 100644 yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/handler/TenantInfoHandler.java

diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
index ec3194cec..47f50fc49 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
@@ -43,6 +43,10 @@ public interface BaseMapperX<T> extends BaseMapper<T> {
         return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
     }
 
+    default Long selectCount() {
+        return selectCount(new QueryWrapper<T>());
+    }
+
     default Integer selectCount(String field, Object value) {
         return selectCount(new QueryWrapper<T>().eq(field, value)).intValue();
     }
diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
index 9ba7ed8c8..d34bf3647 100644
--- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
+++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
@@ -40,7 +40,8 @@ public interface ErrorCodeConstants {
     ErrorCode USER_NOT_EXISTS = new ErrorCode(1002004003, "用户不存在");
     ErrorCode USER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1002004004, "导入用户数据不能为空!");
     ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1002004005, "用户密码校验失败");
-    ErrorCode USER_IS_DISABLE = new ErrorCode(1002003004, "名字为【{}】的用户已被禁用");
+    ErrorCode USER_IS_DISABLE = new ErrorCode(1002004006, "名字为【{}】的用户已被禁用");
+    ErrorCode USER_COUNT_MAX = new ErrorCode(1002004007, "创建用户失败,原因:超过租户最大租户配额({})!");
 
     // ========== 部门模块 1002005000 ==========
     ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1002004001, "已经存在该名字的部门");
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java
index 25092fd07..ad99c6226 100755
--- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java
+++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantEx
 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
+import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler;
 import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler;
 
 import javax.validation.Valid;
@@ -113,6 +114,14 @@ public interface TenantService extends TenantFrameworkService {
      */
     List<TenantDO> getTenantListByPackageId(Long packageId);
 
+    /**
+     * 进行租户的信息处理逻辑
+     * 其中,租户编号从 {@link TenantContextHolder} 上下文中获取
+     *
+     * @param handler 处理器
+     */
+    void handleTenantInfo(TenantInfoHandler handler);
+
     /**
      * 进行租户的菜单处理逻辑
      * 其中,租户编号从 {@link TenantContextHolder} 上下文中获取
@@ -120,5 +129,4 @@ public interface TenantService extends TenantFrameworkService {
      * @param handler 处理器
      */
     void handleTenantMenu(TenantMenuHandler handler);
-
 }
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java
index 576492599..9bc010bd4 100755
--- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java
@@ -25,9 +25,11 @@ import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum;
 import cn.iocoder.yudao.module.system.mq.producer.tenant.TenantProducer;
 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.user.AdminUserService;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -79,6 +81,7 @@ public class TenantServiceImpl implements TenantService {
     @Resource
     private TenantPackageService tenantPackageService;
     @Resource
+    @Lazy // 延迟,避免循环依赖报错
     private AdminUserService userService;
     @Resource
     private RoleService roleService;
@@ -298,6 +301,18 @@ public class TenantServiceImpl implements TenantService {
         return tenantMapper.selectListByPackageId(packageId);
     }
 
+    @Override
+    public void handleTenantInfo(TenantInfoHandler handler) {
+        // 如果禁用,则不执行逻辑
+        if (Boolean.FALSE.equals(tenantProperties.getEnable())) {
+            return;
+        }
+        // 获得租户
+        TenantDO tenant = getTenant(TenantContextHolder.getRequiredTenantId());
+        // 执行处理器
+        handler.handle(tenant);
+    }
+
     @Override
     public void handleTenantMenu(TenantMenuHandler handler) {
         // 如果禁用,则不执行逻辑
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/handler/TenantInfoHandler.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/handler/TenantInfoHandler.java
new file mode 100644
index 000000000..5b5b9fe30
--- /dev/null
+++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/handler/TenantInfoHandler.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.system.service.tenant.handler;
+
+import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
+
+/**
+ * 租户信息处理
+ * 目的:尽量减少租户逻辑耦合到系统中
+ *
+ * @author 芋道源码
+ */
+public interface TenantInfoHandler {
+
+    /**
+     * 基于传入的租户信息,进行相关逻辑的执行
+     * 例如说,创建用户时,超过最大账户配额
+     *
+     * @param tenant 租户信息
+     */
+    void handle(TenantDO tenant);
+
+}
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
index a0682485a..279be9d57 100644
--- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
@@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
 import cn.iocoder.yudao.module.system.service.dept.PostService;
 import cn.iocoder.yudao.module.system.service.permission.PermissionService;
+import cn.iocoder.yudao.module.system.service.tenant.TenantService;
 import com.google.common.annotations.VisibleForTesting;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
@@ -55,12 +56,21 @@ public class AdminUserServiceImpl implements AdminUserService {
     private PermissionService permissionService;
     @Resource
     private PasswordEncoder passwordEncoder;
+    @Resource
+    private TenantService tenantService;
 
     @Resource
     private FileApi fileApi;
 
     @Override
     public Long createUser(UserCreateReqVO reqVO) {
+        // 校验账户配合
+        tenantService.handleTenantInfo(tenant -> {
+            long count = userMapper.selectCount();
+            if (count >= tenant.getAccountCount()) {
+                throw exception(USER_COUNT_MAX, tenant.getAccountCount());
+            }
+        });
         // 校验正确性
         this.checkCreateOrUpdate(null, reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(),
             reqVO.getDeptId(), reqVO.getPostIds());