Prechádzať zdrojové kódy

CRM:完善数据分页查询条件构造 CrmQueryWrapperUtils

puhui999 1 rok pred
rodič
commit
3e91ac73c4
13 zmenil súbory, kde vykonal 91 pridanie a 82 odobranie
  1. 27 0
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java
  2. 2 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http
  3. 8 14
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
  4. 1 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java
  5. 1 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java
  6. 1 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java
  7. 1 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
  8. 1 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
  9. 1 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
  10. 1 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java
  11. 35 37
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java
  12. 1 0
      yudao-server/src/main/resources/application-local.yaml
  13. 11 1
      yudao-server/src/main/resources/application.yaml

+ 27 - 0
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java

@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.crm.enums.permission;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Crm 数据权限角色枚举
+ *
+ * @author HUIHUI
+ */
+@Getter
+@AllArgsConstructor
+public enum CrmPermissionRoleCodeEnum {
+
+    CRM_ADMIN("crm_admin", "CRM 管理员");
+
+    /**
+     * 角色标识
+     */
+    private String code;
+    /**
+     * 角色名称
+     */
+    private String name;
+
+}
+

+ 2 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http

@@ -1,8 +1,8 @@
 ### 请求 /transfer
 PUT {{baseUrl}}/crm/customer/transfer
-Content-Type: application/json
+Content-Type: application/-id: {{adminTenentId}}json
 Authorization: Bearer {{token}}
-tenant-id: {{adminTenentId}}
+tenant
 
 {
   "id": 10,

+ 8 - 14
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java

@@ -3,8 +3,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer;
 import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 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.operatelog.core.annotations.OperateLog;
+import cn.iocoder.yudao.framework.operatelogv2.core.vo.OperateLogV2PageReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
 import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
@@ -12,6 +14,7 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
+import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO;
 import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
@@ -135,23 +138,14 @@ public class CrmCustomerController {
         return success(true);
     }
 
-    // TODO @puhui999:operate-log-list 或者 operate-log-page 如果分页
-    @GetMapping("/operate-log")
+    @GetMapping("/operate-log-page")
     @Operation(summary = "获得客户操作日志")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('crm:customer:query')")
-    // TODO @puhui999:最好有读权限;方法名改成 getCustomerOperateLog
-    public CommonResult<List<OperateLogV2RespDTO>> getOperateLog(@RequestParam("id") Long id) {
-        // 1. 获取客户
-        // TODO @puhui999:这个校验可以去掉哈;
-        CrmCustomerDO customer = customerService.getCustomer(id);
-        if (customer == null) {
-            return success(null);
-        }
-
-        // 2. 获取操作日志
-        // TODO @puhui999:操作日志,返回可能要分页哈;
-        return success(operateLogApi.getOperateLogByModuleAndBizId(CRM_CUSTOMER, id));
+    public CommonResult<PageResult<OperateLogV2RespDTO>> getCustomerOperateLog(OperateLogV2PageReqVO reqVO) {
+        reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页
+        reqVO.setBizType(CRM_CUSTOMER);
+        return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class)));
     }
 
     // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了;

+ 1 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java

@@ -38,11 +38,8 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> {
     default PageResult<CrmBusinessDO> selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) {
         MPJLambdaWrapperX<CrmBusinessDO> query = new MPJLambdaWrapperX<>();
         // 拼接数据权限的查询条件
-        boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(),
+        CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(),
                 CrmBusinessDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
-        if (!condition) {
-            return PageResult.empty();
-        }
         // 拼接自身的查询条件
         query.selectAll(CrmBusinessDO.class)
                 .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName())

+ 1 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java

@@ -30,11 +30,8 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> {
     default PageResult<CrmClueDO> selectPage(CrmCluePageReqVO pageReqVO, Long userId) {
         MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>();
         // 拼接数据权限的查询条件
-        boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(),
+        CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(),
                 CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool());
-        if (!condition) {
-            return PageResult.empty();
-        }
         // 拼接自身的查询条件
         query.selectAll(CrmClueDO.class)
                 .likeIfPresent(CrmClueDO::getName, pageReqVO.getName())

+ 1 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java

@@ -43,11 +43,8 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> {
     default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO pageReqVO, Long userId) {
         MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>();
         // 拼接数据权限的查询条件
-        boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(),
+        CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(),
                 CrmContactDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
-        if (!condition) {
-            return PageResult.empty();
-        }
         // 拼接自身的查询条件
         query.selectAll(CrmContactDO.class)
                 .likeIfPresent(CrmContactDO::getName, pageReqVO.getName())

+ 1 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java

@@ -41,11 +41,8 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> {
     default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) {
         MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>();
         // 拼接数据权限的查询条件
-        boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(),
+        CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(),
                 CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
-        if (!condition) {
-            return PageResult.empty();
-        }
         // 拼接自身的查询条件
         mpjLambdaWrapperX.selectAll(CrmContractDO.class)
                 .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo())

+ 1 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java

@@ -30,11 +30,8 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
     default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) {
         MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
         // 拼接数据权限的查询条件
-        boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
+        CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
                 CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool());
-        if (!condition) {
-            return PageResult.empty();
-        }
         // 拼接自身的查询条件
         query.selectAll(CrmCustomerDO.class)
                 .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName())

+ 1 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java

@@ -39,11 +39,8 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> {
     default PageResult<CrmReceivableDO> selectPage(CrmReceivablePageReqVO pageReqVO, Long userId) {
         MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>();
         // 拼接数据权限的查询条件
-        boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(),
+        CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(),
                 CrmReceivableDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
-        if (!condition) {
-            return PageResult.empty();
-        }
         // 拼接自身的查询条件
         query.selectAll(CrmReceivableDO.class)
                 .eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo())

+ 1 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java

@@ -38,11 +38,8 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO
     default PageResult<CrmReceivablePlanDO> selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) {
         MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>();
         // 拼接数据权限的查询条件
-        boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(),
+        CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(),
                 CrmReceivablePlanDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
-        if (!condition) {
-            return PageResult.empty();
-        }
         // 拼接自身的查询条件
         query.selectAll(CrmReceivablePlanDO.class)
                 .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId())

+ 35 - 37
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java

@@ -7,9 +7,12 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
 import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum;
+import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import com.github.yulichang.autoconfigure.MybatisPlusJoinProperties;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 
 import java.util.Collection;
@@ -33,46 +36,41 @@ public class CrmQueryWrapperUtils {
      * @param userId    用户编号
      * @param sceneType 场景类型
      * @param pool      公海
-     * @return 是否 (是:需要执行查询,否:不需要查询调用方法直接返回空)
      */
-    // TODO @puhui999:bizId 直接传递会不会简单点 回复:还是需要 SFunction 因为分页连表时不知道 bizId 是多少;是不是把 bizId 传入就好啦?
-    public static <T extends MPJLambdaWrapper<?>, S> boolean appendPermissionCondition(T query, Integer bizType, SFunction<S, ?> bizId,
-                                                                                       Long userId, Integer sceneType, Boolean pool) {
+    public static <T extends MPJLambdaWrapper<?>, S> void appendPermissionCondition(T query, Integer bizType, SFunction<S, ?> bizId,
+                                                                                    Long userId, Integer sceneType, Boolean pool) {
+        final String ownerUserIdField = SingletonManager.getMybatisPlusJoinProperties().getTableAlias() + ".owner_user_id";
         // 1. 构建数据权限连表条件
-        if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限
+        if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限
             query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType)
-                    .eq(CrmPermissionDO::getBizId, bizId)
+                    .eq(CrmPermissionDO::getBizId, bizId) // 只能使用 SFunction 如果传 id 解析出来的 sql 不对
                     .eq(CrmPermissionDO::getUserId, userId));
         }
         // 2.1 场景一:我负责的数据
         if (CrmSceneTypeEnum.isOwner(sceneType)) {
-            query.eq("owner_user_id", userId);
+            query.eq(ownerUserIdField, userId);
         }
         // 2.2 场景二:我参与的数据
         if (CrmSceneTypeEnum.isInvolved(sceneType)) {
-            query.ne("owner_user_id", userId)
-                    // TODO @puhui999:IN 是不是更合适哈;
-                    .and(q -> q.eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel())
-                            .or()
-                            .eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.WRITE.getLevel()));
+            query.ne(ownerUserIdField, userId)
+                    .in(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel(), CrmPermissionLevelEnum.WRITE.getLevel());
         }
         // 2.3 场景三:下属负责的数据
         if (CrmSceneTypeEnum.isSubordinate(sceneType)) {
-            // TODO @puhui999:要不如果没有下属,拼一个 owner_user_id in null,不返回结果就好啦;
-            List<AdminUserRespDTO> subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId);
+            List<AdminUserRespDTO> subordinateUsers = SingletonManager.getAdminUserApi().getUserListBySubordinate(userId);
             if (CollUtil.isEmpty(subordinateUsers)) {
-                return false;
+                query.eq(ownerUserIdField, -1); // 不返回任何结果
+            } else {
+                query.in(ownerUserIdField, convertSet(subordinateUsers, AdminUserRespDTO::getId));
             }
-            query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId));
         }
 
         // 3. 拼接公海的查询条件
         if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海
-            query.isNull("owner_user_id");
+            query.isNull(ownerUserIdField);
         } else { // 情况二:不是公海
-            query.isNotNull("owner_user_id");
+            query.isNotNull(ownerUserIdField);
         }
-        return true;
     }
 
     /**
@@ -93,38 +91,38 @@ public class CrmQueryWrapperUtils {
                         .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId));
     }
 
-    private static AdminUserApi getAdminUserApi() {
-        return AdminUserApiHolder.ADMIN_USER_API;
-    }
-
     /**
-     * 校验用户是否是管理员
+     * 校验用户是否是 CRM 管理员
      *
      * @param userId 用户编号
      * @return 是/否
      */
     private static boolean validateAdminUser(Long userId) {
-        // TODO 查询权限配置表用户的角色信息
-        // TODO @puhui999:查询用户的角色;CRM_ADMIN("crm_admin", "CRM 管理员"),
-        //CrmPermissionConfig permissionConfig = crmPermissionConfigService.getPermissionConfigByUserId(userId);
-        //if (permissionConfig == null) {
-        //    return false;
-        //}
-        //// 校验是否为管理员
-        //if (permissionConfig.getIsAdmin()){
-        //    return true;
-        //}
-        return false;
+        return SingletonManager.getPermissionApi().hasAnyRoles(userId, CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode());
     }
 
     /**
-     * 静态内部类实现 AdminUserApi 单例获取
+     * 静态内部类实现单例获取
      *
      * @author HUIHUI
      */
-    private static class AdminUserApiHolder {
+    private static class SingletonManager {
 
         private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class);
+        private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class);
+        private static final MybatisPlusJoinProperties MYBATIS_PLUS_JOIN_PROPERTIES = SpringUtil.getBean(MybatisPlusJoinProperties.class);
+
+        public static AdminUserApi getAdminUserApi() {
+            return ADMIN_USER_API;
+        }
+
+        public static PermissionApi getPermissionApi() {
+            return PERMISSION_API;
+        }
+
+        public static MybatisPlusJoinProperties getMybatisPlusJoinProperties() {
+            return MYBATIS_PLUS_JOIN_PROPERTIES;
+        }
 
     }
 

+ 1 - 0
yudao-server/src/main/resources/application-local.yaml

@@ -188,6 +188,7 @@ logging:
     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
 
 debug: false
 

+ 11 - 1
yudao-server/src/main/resources/application.yaml

@@ -79,7 +79,17 @@ mybatis-plus:
     password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成
 
 mybatis-plus-join:
-  banner: false # 关闭控制台的 Banner 打印
+  #是否打印 mybatis plus join banner 默认true
+  banner: false
+  #全局启用副表逻辑删除(默认true) 关闭后关联查询不会加副表逻辑删除
+  sub-table-logic: true
+  #拦截器MappedStatement缓存(默认true)
+  ms-cache: true
+  #表别名(默认 t)
+  table-alias: t
+  #副表逻辑删除条件的位置,支持where、on
+  #默认ON (1.4.7.2及之前版本默认为where)
+  logic-del-type: on
 
 # Spring Data Redis 配置
 spring: