소스 검색

完善 CRM-客户 数据权限校验2

puhui999 1 년 전
부모
커밋
c6422dc657
26개의 변경된 파일386개의 추가작업 그리고 360개의 파일을 삭제
  1. 1 2
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
  2. 0 31
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/PermissionTypeEnum.java
  3. 0 38
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/TransferTypeEnum.java
  4. 22 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.http
  5. 20 16
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmTransferBusinessReqVO.java
  6. 4 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java
  7. 4 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java
  8. 4 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java
  9. 4 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java
  10. 13 22
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java
  11. 28 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java
  12. 10 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java
  13. 49 35
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java
  14. 13 5
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmBizTypeEnum.java
  15. 50 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmPermissionLevelEnum.java
  16. 0 40
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/OperationTypeEnum.java
  17. 8 7
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
  18. 7 7
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/ContactServiceImpl.java
  19. 7 7
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImpl.java
  20. 7 7
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
  21. 20 9
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java
  22. 54 52
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java
  23. 3 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateBO.java
  24. 3 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateBO.java
  25. 55 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmTransferPermissionReqBO.java
  26. 0 53
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/TransferCrmPermissionBO.java

+ 1 - 2
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java

@@ -34,8 +34,7 @@ public interface ErrorCodeConstants {
     // ========== 客户管理 1_020_006_000 ==========
     ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_006_000, "客户不存在");
 
-    // TODO @puhui999:权限管理???
-    // ========== 客户管理 1_020_007_000 ==========
+    // ========== 权限管理 1_020_007_000 ==========
     ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在");
     ErrorCode CRM_PERMISSION_DENIED = new ErrorCode(1_020_007_001, "{}操作失败,原因:没有权限");
     ErrorCode CRM_PERMISSION_MODEL_NOT_EXISTS = new ErrorCode(1_020_007_002, "{}不存在");

+ 0 - 31
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/PermissionTypeEnum.java

@@ -1,31 +0,0 @@
-package cn.iocoder.yudao.module.crm.enums.common;
-
-import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-@Getter
-@AllArgsConstructor
-public enum PermissionTypeEnum implements IntArrayValuable {
-
-    READONLY(1, "只读"),
-    READ_AND_WRITE(2, "读写");
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PermissionTypeEnum::getType).toArray();
-
-    /**
-     * 类型
-     */
-    private final Integer type;
-    /**
-     * 类型名
-     */
-    private final String name;
-
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-
-}

+ 0 - 38
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/TransferTypeEnum.java

@@ -1,38 +0,0 @@
-package cn.iocoder.yudao.module.crm.enums.common;
-
-import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-// TODO @puhui999:这个可以不用哈
-/**
- * Crm 负责人转移后原负责人的处理方式
- *
- * @author HUIHUI
- */
-@Getter
-@AllArgsConstructor
-public enum TransferTypeEnum implements IntArrayValuable {
-
-    REMOVE(1, "移除"),
-    TEAM(2, "转为团队成员");
-
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TransferTypeEnum::getType).toArray();
-
-    /**
-     * 类型
-     */
-    private final Integer type;
-    /**
-     * 类型名
-     */
-    private final String name;
-
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-
-}

+ 22 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.http

@@ -1,3 +1,4 @@
+### 请求 /transfer
 PUT {{baseUrl}}/crm/business/transfer
 Content-Type: application/json
 Authorization: Bearer {{token}}
@@ -8,4 +9,24 @@ tenant-id: {{adminTenentId}}
   "ownerUserId": 2,
   "transferType": 2,
   "permissionType": 2
-}
+}
+
+### 请求 /update
+PUT {{baseUrl}}/crm/business/update
+Content-Type: application/json
+Authorization: Bearer {{token}}
+tenant-id: {{adminTenentId}}
+
+{
+  "id": 1,
+  "name": "2",
+  "statusTypeId": 2,
+  "statusId": 2,
+  "customerId": 1
+}
+
+### 请求 /get
+GET {{baseUrl}}/crm/business/get?id=1024
+Content-Type: application/json
+Authorization: Bearer {{token}}
+tenant-id: {{adminTenentId}}

+ 20 - 16
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmTransferBusinessReqVO.java

@@ -1,8 +1,6 @@
 package cn.iocoder.yudao.module.crm.controller.admin.business.vo;
 
-import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.crm.enums.common.PermissionTypeEnum;
-import cn.iocoder.yudao.module.crm.enums.common.TransferTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
@@ -16,19 +14,25 @@ public class CrmTransferBusinessReqVO {
     @NotNull(message = "联系人编号不能为空")
     private Long id;
 
-    @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
+    /**
+     * 新负责人的用户编号
+     */
     @NotNull(message = "新负责人的用户编号不能为空")
-    private Long ownerUserId;
-
-    @Schema(description = "原负责人移除方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
-    @InEnum(TransferTypeEnum.class)
-    @NotNull(message = "原负责人移除方式不能为空")
-    private Integer transferType;
-
-    @Schema(description = "权限类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
-    @InEnum(PermissionTypeEnum.class)
-    @NotNull(message = "权限类型不能为空")
-    private Integer permissionType;
-
+    @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
+    private Long newOwnerUserId;
+
+    /**
+     * 老负责人是否加入团队,是/否
+     */
+    @Schema(description = "老负责人是否加入团队", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
+    @NotNull(message = "老负责人是否加入团队不能为空")
+    private Boolean joinTeam;
+
+    /**
+     * 老负责人加入团队后的权限级别。如果 {@link #joinTeam} 为 false, permissionLevel 为 null
+     * 关联 {@link CrmPermissionLevelEnum}
+     */
+    @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    private Integer permissionLevel;
 
 }

+ 4 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.crm.convert.business;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
-import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
+import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.Mappings;
@@ -32,9 +32,9 @@ public interface CrmBusinessConvert {
     List<CrmBusinessExcelVO> convertList02(List<CrmBusinessDO> list);
 
     @Mappings({
-            @Mapping(target = "userId", source = "userId"),
-            @Mapping(target = "crmDataId", source = "reqVO.id")
+            @Mapping(target = "bizId", source = "reqVO.id"),
+            @Mapping(target = "newOwnerUserId", source = "reqVO.id")
     })
-    TransferCrmPermissionBO convert(CrmTransferBusinessReqVO reqVO, Long userId);
+    CrmTransferPermissionReqBO convert(CrmTransferBusinessReqVO reqVO, Long userId);
 
 }

+ 4 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.crm.convert.contact;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO;
-import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
+import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.Mappings;
@@ -34,9 +34,9 @@ public interface ContactConvert {
     List<ContactExcelVO> convertList02(List<ContactDO> list);
 
     @Mappings({
-            @Mapping(target = "userId", source = "userId"),
-            @Mapping(target = "crmDataId", source = "reqVO.id")
+            @Mapping(target = "bizId", source = "reqVO.id"),
+            @Mapping(target = "newOwnerUserId", source = "reqVO.id")
     })
-    TransferCrmPermissionBO convert(CrmTransferContactReqVO reqVO, Long userId);
+    CrmTransferPermissionReqBO convert(CrmTransferContactReqVO reqVO, Long userId);
 
 }

+ 4 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.crm.convert.contract;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
-import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
+import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.Mappings;
@@ -34,9 +34,9 @@ public interface ContractConvert {
     List<ContractExcelVO> convertList02(List<ContractDO> list);
 
     @Mappings({
-            @Mapping(target = "userId", source = "userId"),
-            @Mapping(target = "crmDataId", source = "reqVO.id")
+            @Mapping(target = "bizId", source = "reqVO.id"),
+            @Mapping(target = "newOwnerUserId", source = "reqVO.id")
     })
-    TransferCrmPermissionBO convert(CrmTransferContractReqVO reqVO, Long userId);
+    CrmTransferPermissionReqBO convert(CrmTransferContractReqVO reqVO, Long userId);
 
 }

+ 4 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.crm.convert.customer;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
-import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
+import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.Mappings;
@@ -32,9 +32,9 @@ public interface CrmCustomerConvert {
     List<CrmCustomerExcelVO> convertList02(List<CrmCustomerDO> list);
 
     @Mappings({
-            @Mapping(target = "userId", source = "userId"),
-            @Mapping(target = "crmDataId", source = "reqVO.id")
+            @Mapping(target = "bizId", source = "reqVO.id"),
+            @Mapping(target = "newOwnerUserId", source = "reqVO.id")
     })
-    TransferCrmPermissionBO convert(CrmTransferCustomerReqVO reqVO, Long userId);
+    CrmTransferPermissionReqBO convert(CrmTransferCustomerReqVO reqVO, Long userId);
 
 }

+ 13 - 22
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java

@@ -1,23 +1,20 @@
 package cn.iocoder.yudao.module.crm.dal.dataobject.permission;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
 import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
 
-import java.util.Set;
-
 /**
- * crm 数据权限 DO
+ * Crm 数据权限 DO
  *
  * @author HUIHUI
  */
-@TableName("crm_receivable")
-@KeySequence("crm_receivable_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@TableName("crm_permission")
+@KeySequence("crm_permission_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
@@ -32,26 +29,20 @@ public class CrmPermissionDO extends BaseDO {
     @TableId
     private Long id;
     /**
-     * 数据类型 关联 {@link CrmEnum}
-     */
-    private Integer crmType;
-    /**
-     * 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId()
+     * 数据类型,关联 {@link CrmBizTypeEnum}
      */
-    private Long crmDataId;
+    private Integer bizType;
     /**
-     * 负责人的用户编号 关联 AdminUser#id
+     * 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
      */
-    private Long ownerUserId;
+    private Long bizId;
     /**
-     * 只读权限的用户编号数组
+     * 团队成员,关联 AdminUser#id
      */
-    @TableField(typeHandler = JsonLongSetTypeHandler.class)
-    private Set<Long> roUserIds;
+    private Long userId;
     /**
-     * 读写权限的用户编号数组
+     * 权限级别,关联 {@link CrmPermissionLevelEnum}
      */
-    @TableField(typeHandler = JsonLongSetTypeHandler.class)
-    private Set<Long> rwUserIds;
+    private Integer permissionLevel;
 
 }

+ 28 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java

@@ -3,8 +3,11 @@ package cn.iocoder.yudao.module.crm.dal.mysql.permission;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+
 /**
  * crm 数据权限 mapper
  *
@@ -13,9 +16,32 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> {
 
-    default CrmPermissionDO selectByCrmTypeAndCrmDataId(Integer crmType, Long crmDataId) {
+    /**
+     * 获取用户数据权限通过 数据类型 x 某个数据 x 用户编号
+     *
+     * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
+     * @param bizId   数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
+     * @param userId  用户编号,AdminUser#id
+     * @return Crm 数据权限
+     */
+    default CrmPermissionDO selectByBizTypeAndBizIdByUserId(Integer bizType, Long bizId, Long userId) {
         return selectOne(new LambdaQueryWrapperX<CrmPermissionDO>()
-                .eq(CrmPermissionDO::getCrmType, crmType).eq(CrmPermissionDO::getCrmDataId, crmDataId));
+                .eq(CrmPermissionDO::getBizType, bizType)
+                .eq(CrmPermissionDO::getBizId, bizId)
+                .eq(CrmPermissionDO::getUserId, userId));
+    }
+
+    /**
+     * 获取数据权限列表通过 数据类型 x 某个数据
+     *
+     * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
+     * @param bizId   数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
+     * @return Crm 数据权限列表
+     */
+    default List<CrmPermissionDO> selectByBizTypeAndBizId(Integer bizType, Long bizId) {
+        return selectList(new LambdaQueryWrapperX<CrmPermissionDO>()
+                .eq(CrmPermissionDO::getBizType, bizType)
+                .eq(CrmPermissionDO::getBizId, bizId));
     }
 
 }

+ 10 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.crm.framework.core.annotations;
 
-import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
@@ -24,11 +24,17 @@ public @interface CrmPermission {
     /**
      * crm 类型
      */
-    CrmEnum crmType();
+    CrmBizTypeEnum bizType();
+
+    /**
+     * 数据编号获取来源类,确保数据 id 编号在此类中,不能在父类中。
+     * 例:如果在 baseVO 中需要把 id 弄到 updateVO 中。
+     */
+    Class<?>[] getIdFor() default {};
 
     /**
      * 操作类型
      */
-    OperationTypeEnum operationType();
+    CrmPermissionLevelEnum permissionLevel();
 
 }

+ 49 - 35
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java

@@ -5,7 +5,6 @@ import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
-import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import lombok.extern.slf4j.Slf4j;
 import org.aspectj.lang.JoinPoint;
@@ -14,11 +13,13 @@ import org.aspectj.lang.annotation.Before;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
+import java.lang.reflect.Field;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED;
-import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_MODEL_NOT_EXISTS;
+import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum.*;
 
 /**
  * Crm 数据权限校验 AOP 切面
@@ -42,54 +43,67 @@ public class CrmPermissionAspect {
         return WebFrameworkUtils.getLoginUserId();
     }
 
+    private Long getBizId(JoinPoint joinPoint, CrmPermission crmPermission) throws NoSuchFieldException, IllegalAccessException {
+        Object[] args = joinPoint.getArgs();
+        for (Object arg : args) {
+            if (arg == null) {
+                continue;
+            }
+            if (ObjUtil.notEqual(arg.getClass().getName(), crmPermission.getIdFor()[0].getName())) {
+                continue;
+            }
+            // 使用反射获取id属性
+            Field idValue = arg.getClass().getDeclaredField("id");
+            // 设置字段为可访问
+            idValue.setAccessible(true);
+            return (Long) idValue.get(arg);
+        }
+        return null;
+    }
+
     @Before("@annotation(crmPermission)")
     public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) {
         try {
-            Integer crmType = crmPermission.crmType().getType();
-            Integer operationType = crmPermission.operationType().getType();
-            // TODO @puhui999:不一定是 id 参数噢;例如说,ContactServiceImpl 的 updateContact
-            Long id = (Long) joinPoint.getArgs()[0];// 获取操作数据的编号
+            Long bizId = crmPermission.getIdFor().length > 0 ? getBizId(joinPoint, crmPermission) : (Long) joinPoint.getArgs()[0]; // 获取操作数据的编号
+            Integer bizType = crmPermission.bizType().getType(); // 模块类型
+            Integer permissionLevel = crmPermission.permissionLevel().getLevel(); // 需要的权限级别
 
-            // 1.1 获取数据权限
-            CrmPermissionDO permission = crmPermissionService.getCrmPermissionByCrmTypeAndCrmDataId(crmType, id);
-            if (permission == null) {
-                // 不存在说明数据也不存在
-                throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, crmPermission.crmType().getName());
-            }
-            // 1.2 校验是否为公海数据
-            // TODO @puhui999:这个判断去掉比较合适哈。这里更多是业务逻辑,不算权限判断。例如说,公海的客户,只要没负责人,就可以领取了;
-            if (permission.getOwnerUserId() == null) {
-                return;
-            }
-            // 1.3 校验当前负责人是不是自己
-            if (ObjUtil.equal(permission.getOwnerUserId(), getUserId())) {
+            // TODO 如果是超级管理员则直接通过
+            //if (superAdmin){
+            //    return;
+            //}
+
+            // 1. 获取数据权限
+            List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
+            CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, item -> ObjUtil.equal(item.getUserId(), getUserId()));
+            if (isOwner(userPermission.getPermissionLevel())) { // 校验自己是否是负责人
                 return;
             }
-            // 1.4 TODO 校验是否为超级管理员
-
-            // 2. 校验是否有读权限
-            if (OperationTypeEnum.isRead(operationType)) {
-                // 校验该数据当前用户是否可读
-                // TODO @puhui999:直接 CollUtil.contains 就好,因为就是有某个 userId 呀
-                boolean isRead = CollUtil.contains(permission.getRoUserIds(), item -> ObjUtil.equal(item, getUserId()))
-                        || CollUtil.contains(permission.getRwUserIds(), item -> ObjUtil.equal(item, getUserId()));
-                if (isRead) {
+            if (isRead(permissionLevel)) { // 读权限
+                // 如果没有数据权限或没有负责人则表示此记录为公海数据所有人都有只读权限
+                if (CollUtil.isEmpty(bizPermissions) || !CollUtil.anyMatch(bizPermissions, item -> isOwner(item.getPermissionLevel()))) {
+                    return;
+                }
+                if (isRead(userPermission.getPermissionLevel())) { // 校验当前用户是否有读权限
+                    return;
+                }
+                //如果查询数据的话拥有写权限的也能查询
+                if (isWrite(userPermission.getPermissionLevel())) { // 校验当前用户是否有写权限
                     return;
                 }
             }
-
-            // 3. 校验是否有编辑权限
-            if (OperationTypeEnum.isEdit(operationType)) {
-                // 校验该数据当前用户是否可读写
-                if (CollUtil.contains(permission.getRwUserIds(), item -> ObjUtil.equal(item, getUserId()))) {
+            if (isWrite(permissionLevel)) { // 写权限
+                if (isWrite(userPermission.getPermissionLevel())) { // 校验当前用户是否有写权限
                     return;
                 }
             }
 
-            // 4. 没通过结束,报错 {}操作失败,原因:没有权限
-            throw exception(CRM_PERMISSION_DENIED, crmPermission.crmType().getName());
+            // 2. 没通过结束,报错 {}操作失败,原因:没有权限
+            throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType().getName());
         } catch (Exception ex) {
             log.error("[doBefore][crmPermission({}) 数据校验错误]", toJsonString(crmPermission), ex);
+            // TODO 报错抛个什么异常好呢
+            throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType().getName());
         }
     }
 

+ 13 - 5
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmEnum.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmBizTypeEnum.java

@@ -1,10 +1,12 @@
 package cn.iocoder.yudao.module.crm.framework.enums;
 
 import cn.hutool.core.util.ObjUtil;
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 
-// TODO @puhui999:可以改成 CrmBizTypeEnum,CRM 业务类型枚举
+import java.util.Arrays;
+
 /**
  * Crm 类型枚举
  *
@@ -12,7 +14,7 @@ import lombok.RequiredArgsConstructor;
  */
 @RequiredArgsConstructor
 @Getter
-public enum CrmEnum {
+public enum CrmBizTypeEnum implements IntArrayValuable {
 
     CRM_LEADS(1, "线索"),
     CRM_CUSTOMER(2, "客户"),
@@ -20,6 +22,7 @@ public enum CrmEnum {
     CRM_BUSINESS(5, "商机"),
     CRM_CONTRACT(6, "合同");
 
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizTypeEnum::getType).toArray();
     /**
      * 类型
      */
@@ -30,12 +33,17 @@ public enum CrmEnum {
     private final String name;
 
     public static String getNameByType(Integer type) {
-        for (CrmEnum crmEnum : CrmEnum.values()) {
-            if (ObjUtil.equal(crmEnum.type, type)) {
-                return crmEnum.name;
+        for (CrmBizTypeEnum crmBizTypeEnum : CrmBizTypeEnum.values()) {
+            if (ObjUtil.equal(crmBizTypeEnum.type, type)) {
+                return crmBizTypeEnum.name;
             }
         }
         return "";
     }
 
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+
 }

+ 50 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmPermissionLevelEnum.java

@@ -0,0 +1,50 @@
+package cn.iocoder.yudao.module.crm.framework.enums;
+
+import cn.hutool.core.util.ObjUtil;
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * Crm 数据权限级别枚举
+ *
+ * @author HUIHUI
+ */
+@Getter
+@AllArgsConstructor
+public enum CrmPermissionLevelEnum implements IntArrayValuable {
+
+    OWNER(1, "负责人"),
+    READ(2, "读"),
+    WRITE(3, "写");
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmPermissionLevelEnum::getLevel).toArray();
+
+    /**
+     * 级别
+     */
+    private final Integer level;
+    /**
+     * 级别名称
+     */
+    private final String name;
+
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+
+    public static boolean isOwner(Integer level) {
+        return ObjUtil.equal(OWNER.level, level);
+    }
+
+    public static boolean isRead(Integer level) {
+        return ObjUtil.equal(READ.level, level);
+    }
+
+    public static boolean isWrite(Integer level) {
+        return ObjUtil.equal(WRITE.level, level);
+    }
+
+}

+ 0 - 40
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/OperationTypeEnum.java

@@ -1,40 +0,0 @@
-package cn.iocoder.yudao.module.crm.framework.enums;
-
-import cn.hutool.core.util.ObjUtil;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-// TODO @puhui999:是不是可以和 PermissionTypeEnum 合并,就是 CrmPermissionEnum,负责人、读取、读写;目前阶段,不用做的特别细致;类似 linux 的 acl;
-/**
- * Crm 数据操作类型枚举
- *
- * @author HUIHUI
- */
-@RequiredArgsConstructor
-@Getter
-public enum OperationTypeEnum {
-
-    // TODO @puhui999:抽象上,就分三种,会更合理。一个 OWNER 负责人,一个 READ 读,一个 WRITE 写;
-    DELETE(1, "删除"),
-    UPDATE(2, "修改"),
-    READ(3, "查询");
-
-    /**
-     * 类型
-     */
-    private final Integer type;
-
-    /**
-     * 名称
-     */
-    private final String name;
-
-    public static boolean isRead(Integer type) {
-        return ObjUtil.equal(type, READ.getType());
-    }
-
-    public static boolean isEdit(Integer type) {
-        return ObjUtil.equal(type, UPDATE.getType()) || ObjUtil.equal(type, DELETE.getType());
-    }
-
-}

+ 8 - 7
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java

@@ -8,8 +8,8 @@ import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
 import org.springframework.stereotype.Service;
@@ -46,7 +46,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
         businessMapper.insert(business);
 
         // 创建数据权限
-        crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_BUSINESS.getType())
+        crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmBizTypeEnum.CRM_BUSINESS.getType())
                 .setCrmDataId(business.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人
 
         // 返回
@@ -55,7 +55,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    @CrmPermission(crmType = CrmEnum.CRM_BUSINESS, operationType = OperationTypeEnum.UPDATE)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, getIdFor = CrmBusinessUpdateReqVO.class,
+            permissionLevel = CrmPermissionLevelEnum.WRITE)
     public void updateBusiness(CrmBusinessUpdateReqVO updateReqVO) {
         // 校验存在
         validateBusinessExists(updateReqVO.getId());
@@ -66,7 +67,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    @CrmPermission(crmType = CrmEnum.CRM_BUSINESS, operationType = OperationTypeEnum.DELETE)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, permissionLevel = CrmPermissionLevelEnum.WRITE)
     public void deleteBusiness(Long id) {
         // 校验存在
         validateBusinessExists(id);
@@ -83,7 +84,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
     }
 
     @Override
-    @CrmPermission(crmType = CrmEnum.CRM_BUSINESS, operationType = OperationTypeEnum.READ)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, permissionLevel = CrmPermissionLevelEnum.READ)
     public CrmBusinessDO getBusiness(Long id) {
         return businessMapper.selectById(id);
     }
@@ -114,7 +115,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
 
         // 2. 数据权限转移
         crmPermissionService.transferCrmPermission(
-                CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_BUSINESS.getType()));
+                CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()));
 
     }
 

+ 7 - 7
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/ContactServiceImpl.java

@@ -8,8 +8,8 @@ import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO;
 import cn.iocoder.yudao.module.crm.dal.mysql.contact.ContactMapper;
 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
 import org.springframework.stereotype.Service;
@@ -46,7 +46,7 @@ public class ContactServiceImpl implements ContactService {
         contactMapper.insert(contact);
 
         // 创建数据权限
-        crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_BUSINESS.getType())
+        crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmBizTypeEnum.CRM_BUSINESS.getType())
                 .setCrmDataId(contact.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人
 
         // 返回
@@ -55,7 +55,7 @@ public class ContactServiceImpl implements ContactService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    @CrmPermission(crmType = CrmEnum.CRM_CONTACTS, operationType = OperationTypeEnum.UPDATE)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, permissionLevel = CrmPermissionLevelEnum.WRITE)
     public void updateContact(ContactUpdateReqVO updateReqVO) {
         // 校验存在
         validateContactExists(updateReqVO.getId());
@@ -68,7 +68,7 @@ public class ContactServiceImpl implements ContactService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    @CrmPermission(crmType = CrmEnum.CRM_CONTACTS, operationType = OperationTypeEnum.DELETE)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, permissionLevel = CrmPermissionLevelEnum.WRITE)
     public void deleteContact(Long id) {
         // 校验存在
         validateContactExists(id);
@@ -85,7 +85,7 @@ public class ContactServiceImpl implements ContactService {
     }
 
     @Override
-    @CrmPermission(crmType = CrmEnum.CRM_CONTACTS, operationType = OperationTypeEnum.READ)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, permissionLevel = CrmPermissionLevelEnum.READ)
     public ContactDO getContact(Long id) {
         return contactMapper.selectById(id);
     }
@@ -115,7 +115,7 @@ public class ContactServiceImpl implements ContactService {
 
         // 2. 数据权限转移
         crmPermissionService.transferCrmPermission(
-                ContactConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_CONTACTS.getType()));
+                ContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACTS.getType()));
 
     }
 

+ 7 - 7
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImpl.java

@@ -8,8 +8,8 @@ import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
 import cn.iocoder.yudao.module.crm.dal.mysql.contract.ContractMapper;
 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
 import org.springframework.stereotype.Service;
@@ -45,7 +45,7 @@ public class ContractServiceImpl implements ContractService {
         contractMapper.insert(contract);
 
         // 创建数据权限
-        crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_CONTRACT.getType())
+        crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmBizTypeEnum.CRM_CONTRACT.getType())
                 .setCrmDataId(contract.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人
 
         // 返回
@@ -54,7 +54,7 @@ public class ContractServiceImpl implements ContractService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    @CrmPermission(crmType = CrmEnum.CRM_CONTRACT, operationType = OperationTypeEnum.DELETE)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, permissionLevel = CrmPermissionLevelEnum.WRITE)
     public void updateContract(ContractUpdateReqVO updateReqVO) {
         // 校验存在
         validateContractExists(updateReqVO.getId());
@@ -65,7 +65,7 @@ public class ContractServiceImpl implements ContractService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    @CrmPermission(crmType = CrmEnum.CRM_CONTRACT, operationType = OperationTypeEnum.DELETE)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, permissionLevel = CrmPermissionLevelEnum.WRITE)
     public void deleteContract(Long id) {
         // 校验存在
         validateContractExists(id);
@@ -82,7 +82,7 @@ public class ContractServiceImpl implements ContractService {
     }
 
     @Override
-    @CrmPermission(crmType = CrmEnum.CRM_CONTRACT, operationType = OperationTypeEnum.READ)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, permissionLevel = CrmPermissionLevelEnum.READ)
     public ContractDO getContract(Long id) {
         return contractMapper.selectById(id);
     }
@@ -113,7 +113,7 @@ public class ContractServiceImpl implements ContractService {
 
         // 2. 数据权限转移
         crmPermissionService.transferCrmPermission(
-                ContractConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_CONTRACT.getType()));
+                ContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()));
 
     }
 

+ 7 - 7
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java

@@ -8,8 +8,8 @@ import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
 import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper;
 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
@@ -48,7 +48,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
         customerMapper.insert(customer);
 
         // 创建数据权限
-        crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_CUSTOMER.getType())
+        crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
                 .setCrmDataId(customer.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人
 
         // 返回
@@ -57,7 +57,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    @CrmPermission(crmType = CrmEnum.CRM_CUSTOMER, operationType = OperationTypeEnum.UPDATE)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, permissionLevel = CrmPermissionLevelEnum.WRITE)
     public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) {
         // 校验存在
         validateCustomerExists(updateReqVO.getId());
@@ -70,7 +70,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    @CrmPermission(crmType = CrmEnum.CRM_CUSTOMER, operationType = OperationTypeEnum.DELETE)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, permissionLevel = CrmPermissionLevelEnum.WRITE)
     public void deleteCustomer(Long id) {
         // 校验存在
         validateCustomerExists(id);
@@ -87,7 +87,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
     }
 
     @Override
-    @CrmPermission(crmType = CrmEnum.CRM_CUSTOMER, operationType = OperationTypeEnum.READ)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, permissionLevel = CrmPermissionLevelEnum.READ)
     public CrmCustomerDO getCustomer(Long id) {
         return customerMapper.selectById(id);
     }
@@ -135,7 +135,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
 
         // 2. 数据权限转移
         crmPermissionService.transferCrmPermission(
-                CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_CUSTOMER.getType()));
+                CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()));
     }
 
 }

+ 20 - 9
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java

@@ -2,12 +2,13 @@ package cn.iocoder.yudao.module.crm.service.permission;
 
 
 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateBO;
-import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
+import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
 
 import javax.validation.Valid;
+import java.util.List;
 
 /**
  * crm 数据权限 Service 接口
@@ -40,19 +41,29 @@ public interface CrmPermissionService {
     void deleteCrmPermission(Long id);
 
     /**
-     * 获得数据权限
+     * 获取用户数据权限通过 数据类型 x 某个数据 x 用户编号
      *
-     * @param crmType 数据类型 关联 {@link CrmEnum}
-     * @param crmDataId 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId()
-     * @return 数据权限
+     * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
+     * @param bizId   数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
+     * @param userId  用户编号,AdminUser#id
+     * @return Crm 数据权限
      */
-    CrmPermissionDO getCrmPermissionByCrmTypeAndCrmDataId(Integer crmType, Long crmDataId);
+    CrmPermissionDO getPermissionByBizTypeAndBizIdAndUserId(Integer bizType, Long bizId, Long userId);
+
+    /**
+     * 获取数据权限列表,通过 数据类型 x 某个数据
+     *
+     * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
+     * @param bizId   数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
+     * @return Crm 数据权限列表
+     */
+    List<CrmPermissionDO> getPermissionByBizTypeAndBizId(Integer bizType, Long bizId);
 
     /**
      * 数据权限转移
      *
-     * @param transferCrmPermissionBO 数据权限转移请求
+     * @param crmTransferPermissionReqBO 数据权限转移请求
      */
-    void transferCrmPermission(@Valid TransferCrmPermissionBO transferCrmPermissionBO);
+    void transferCrmPermission(@Valid CrmTransferPermissionReqBO crmTransferPermissionReqBO);
 
 }

+ 54 - 52
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java

@@ -5,12 +5,11 @@ import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
 import cn.iocoder.yudao.module.crm.dal.mysql.permission.CrmPermissionMapper;
-import cn.iocoder.yudao.module.crm.enums.common.PermissionTypeEnum;
-import cn.iocoder.yudao.module.crm.enums.common.TransferTypeEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateBO;
-import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
+import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import org.springframework.stereotype.Service;
@@ -18,10 +17,11 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
-import java.util.Set;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum.isOwner;
 
 /**
  * crm 数据权限 Service 接口实现类
@@ -41,10 +41,9 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long createCrmPermission(CrmPermissionCreateBO createBO) {
-        // TODO @puhui999:createDO 改成 permission,保持统一哈;
-        CrmPermissionDO createDO = CrmPermissionConvert.INSTANCE.convert(createBO);
-        crmPermissionMapper.insert(createDO);
-        return createDO.getId();
+        CrmPermissionDO permission = CrmPermissionConvert.INSTANCE.convert(createBO);
+        crmPermissionMapper.insert(permission);
+        return permission.getId();
     }
 
     @Override
@@ -64,64 +63,67 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
         crmPermissionMapper.deleteById(id);
     }
 
+    @Override
+    public CrmPermissionDO getPermissionByBizTypeAndBizIdAndUserId(Integer bizType, Long bizId, Long userId) {
+        return crmPermissionMapper.selectByBizTypeAndBizIdByUserId(bizType, bizId, userId);
+    }
+
+    @Override
+    public List<CrmPermissionDO> getPermissionByBizTypeAndBizId(Integer bizType, Long bizId) {
+        return crmPermissionMapper.selectByBizTypeAndBizId(bizType, bizId);
+    }
+
     private void validateCrmPermissionExists(Long id) {
         if (crmPermissionMapper.selectById(id) == null) {
             throw exception(CRM_PERMISSION_NOT_EXISTS);
         }
     }
 
-    @Override
-    public CrmPermissionDO getCrmPermissionByCrmTypeAndCrmDataId(Integer crmType, Long crmDataId) {
-        return crmPermissionMapper.selectByCrmTypeAndCrmDataId(crmType, crmDataId);
-    }
 
-    // TODO @puhui999:参数名,是不是 transferReqBO
     @Override
-    public void transferCrmPermission(TransferCrmPermissionBO transferCrmPermissionBO) {
-        // 1.1 校验商机是否存在
-        // TODO puhui999:这里直接调用 crmPermissionMapper 的 selectByCrmTypeAndCrmDataId 方法,会更简洁一点;
-        CrmPermissionDO permission = getCrmPermissionByCrmTypeAndCrmDataId(transferCrmPermissionBO.getCrmType(),
-                transferCrmPermissionBO.getCrmDataId());
-        String crmName = CrmEnum.getNameByType(transferCrmPermissionBO.getCrmType());
-        if (permission == null) {
-            throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, crmName);
-        }
-        // 1.2 校验转移对象是否已经是该负责人
-        if (ObjUtil.equal(permission.getOwnerUserId(), permission.getOwnerUserId())) {
-            // TODO @puhui999:是不是这个错误码不太对。。。
-            throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_NOT_EXISTS, crmName);
+    public void transferCrmPermission(CrmTransferPermissionReqBO transferReqBO) {
+        // 1. 校验数据权限-是否是负责人,只有负责人才可以转移
+        CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId(transferReqBO.getBizType(),
+                transferReqBO.getBizId(), transferReqBO.getUserId());
+        String crmName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType());
+        // TODO 校验是否为超级管理员 || 1
+        if (oldPermission == null || !isOwner(oldPermission.getPermissionLevel())) {
+            throw exception(CRM_PERMISSION_DENIED, crmName);
         }
-        // 1.3 校验新负责人是否存在
-        AdminUserRespDTO user = adminUserApi.getUser(permission.getOwnerUserId());
-        if (user == null) {
+
+        // 2. 校验转移对象是否已经是该负责人
+        if (ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) {
             throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, crmName);
         }
-        // TODO 校验是否为超级管理员 || 1.4
-        // 1.4 校验是否有写权限
-        // TODO puhui999:CollUtil.contains 就够了,不用后面写个表达式;
-        if (!CollUtil.contains(permission.getRwUserIds(), id -> ObjUtil.equal(id, transferCrmPermissionBO.getUserId()))) {
-            throw exception(CRM_PERMISSION_DENIED, crmName);
+        // 2.1 校验新负责人是否存在
+        AdminUserRespDTO user = adminUserApi.getUser(transferReqBO.getNewOwnerUserId());
+        if (user == null) {
+            throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_NOT_EXISTS, crmName);
         }
 
-        // 2. 权限转移
-        CrmPermissionDO updateCrmPermission = new CrmPermissionDO().setId(permission.getId())
-                .setOwnerUserId(transferCrmPermissionBO.getOwnerUserId());
-        if (ObjUtil.equal(TransferTypeEnum.TEAM.getType(), transferCrmPermissionBO.getTransferType())) {
-            if (ObjUtil.equal(PermissionTypeEnum.READONLY.getType(), transferCrmPermissionBO.getPermissionType())) {
-                Set<Long> roUserIds = permission.getRoUserIds();
-                roUserIds.add(permission.getOwnerUserId()); // 老负责人加入团队有只读权限
-                updateCrmPermission.setRoUserIds(roUserIds);
-            }
-            if (ObjUtil.equal(PermissionTypeEnum.READ_AND_WRITE.getType(), transferCrmPermissionBO.getPermissionType())) {
-                Set<Long> rwUserIds = permission.getRwUserIds();
-                rwUserIds.add(permission.getOwnerUserId()); // 老负责人加入团队有读写权限
-                updateCrmPermission.setRoUserIds(rwUserIds);
-            }
+        // 3. 权限转移
+        List<CrmPermissionDO> permissions = crmPermissionMapper.selectByBizTypeAndBizId(
+                transferReqBO.getBizType(), transferReqBO.getBizId()); // 获取所有团队成员
+        // 3.1 校验新负责人是否在团队成员中
+        CrmPermissionDO permission = CollUtil.findOne(permissions,
+                item -> ObjUtil.equal(item.getUserId(), transferReqBO.getNewOwnerUserId()));
+        if (permission == null) { // 不存在则以负责人的级别加入这个团队
+            crmPermissionMapper.insert(new CrmPermissionDO().setBizType(transferReqBO.getBizType())
+                    .setBizId(transferReqBO.getBizId()).setUserId(transferReqBO.getNewOwnerUserId())
+                    .setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
+
+        } else { // 存在则修改权限级别
+            crmPermissionMapper.updateById(new CrmPermissionDO().setId(permission.getId())
+                    .setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
         }
-        crmPermissionMapper.updateById(updateCrmPermission);
 
-        // 3. TODO 记录机转移日志
-        // TODO @puhui999:是不是交给业务记录哈;
+        // 4. 老负责人处理
+        if (transferReqBO.getJoinTeam()) { // 加入团队
+            crmPermissionMapper.updateById(new CrmPermissionDO().setId(oldPermission.getId())
+                    .setPermissionLevel(transferReqBO.getPermissionLevel())); // 设置加入团队后的级别
+            return;
+        }
+        crmPermissionMapper.deleteById(oldPermission.getId()); // 移除
     }
 
 }

+ 3 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateBO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.crm.service.permission.bo;
 
-import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
 import lombok.Data;
 
 import javax.validation.constraints.NotNull;
@@ -18,12 +18,12 @@ public class CrmPermissionCreateBO {
     // TODO @puhui999:如果是关联字段,换一行写它的注释;不然看着略乱哈
 
     /**
-     * Crm 类型 关联 {@link CrmEnum}
+     * Crm 类型 关联 {@link CrmBizTypeEnum}
      */
     @NotNull(message = "Crm 类型不能为空")
     private Integer crmType;
     /**
-     * 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId()
+     * 数据编号 关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
      */
     @NotNull(message = "Crm 数据编号不能为空")
     private Long crmDataId;

+ 3 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateBO.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.crm.service.permission.bo;
 
 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
 import lombok.Data;
 
 import javax.validation.constraints.NotNull;
@@ -24,12 +24,12 @@ public class CrmPermissionUpdateBO {
     private Long id;
 
     /**
-     * Crm 类型 关联 {@link CrmEnum}
+     * Crm 类型 关联 {@link CrmBizTypeEnum}
      */
     @NotNull(message = "Crm 类型不能为空")
     private Integer crmType;
     /**
-     * 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId()
+     * 数据编号 关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
      */
     @NotNull(message = "Crm 数据编号不能为空")
     private Long crmDataId;

+ 55 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmTransferPermissionReqBO.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.crm.service.permission.bo;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 数据权限转移 Request BO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class CrmTransferPermissionReqBO {
+
+    /**
+     * 当前登录用户编号
+     */
+    @NotNull(message = "用户编号不能为空")
+    private Long userId;
+
+    /**
+     * Crm 类型
+     */
+    @NotNull(message = "Crm 类型不能为空")
+    @InEnum(CrmBizTypeEnum.class)
+    private Integer bizType;
+
+    /**
+     * 数据编号
+     */
+    @NotNull(message = "Crm 数据编号不能为空")
+    private Long bizId;
+
+    /**
+     * 新负责人的用户编号
+     */
+    @NotNull(message = "新负责人的用户编号不能为空")
+    private Long newOwnerUserId;
+
+    /**
+     * 老负责人是否加入团队,是/否
+     */
+    @NotNull(message = "老负责人是否加入团队不能为空")
+    private Boolean joinTeam;
+
+    /**
+     * 老负责人加入团队后的权限级别。如果 {@link #joinTeam} 为 false, permissionLevel 为 null
+     * 关联 {@link CrmPermissionLevelEnum}
+     */
+    private Integer permissionLevel;
+
+}

+ 0 - 53
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/TransferCrmPermissionBO.java

@@ -1,53 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.permission.bo;
-
-import cn.iocoder.yudao.module.crm.enums.common.PermissionTypeEnum;
-import cn.iocoder.yudao.module.crm.enums.common.TransferTypeEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
-import lombok.Data;
-
-import javax.validation.constraints.NotNull;
-
-// TODO @puhui999:CrmTransferPermissionReqBO,一个是 Crm 前缀,一个 Req 表示入参
-/**
- * 数据权限转移 BO
- *
- * @author HUIHUI
- */
-@Data
-public class TransferCrmPermissionBO {
-
-    // TODO @puhui999:参数的注释
-    @NotNull(message = "用户编号不能为空")
-    private Long userId;
-
-    // TODO @puhui999:bizType
-    /**
-     * Crm 类型 关联 {@link CrmEnum} TODO 这种不用再写关联了,直接 @InEnum 参数校验
-     */
-    @NotNull(message = "Crm 类型不能为空")
-    private Integer crmType;
-
-    // TODO @puhui999:bizId
-    /**
-     * 数据编号
-     */
-    @NotNull(message = "Crm 数据编号不能为空")
-    private Long crmDataId;
-
-    // TODO @puhui999:要不这里改成 newOwnerUserId;然后,transferType 和 permissionType,合并成 oldOwnerPermission(空就是移除)
-    @NotNull(message = "新负责人的用户编号不能为空")
-    private Long ownerUserId;
-
-    /**
-     * 原负责人移除方式, 关联 {@link TransferTypeEnum} TODO 这种不用再写关联了,直接 @InEnum 参数校验
-     */
-    @NotNull(message = "原负责人移除方式不能为空")
-    private Integer transferType;
-
-    /**
-     * 权限类型, 关联 {@link PermissionTypeEnum}
-     */
-    @NotNull(message = "权限类型不能为空")
-    private Integer permissionType;
-
-}