Commit c6422dc6574b975a62da0abaad2f30c9d451afb8

Authored by puhui999
1 parent 4dab376c

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

Showing 25 changed files with 359 additions and 333 deletions
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 {
34 34 // ========== 客户管理 1_020_006_000 ==========
35 35 ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_006_000, "客户不存在");
36 36  
37   - // TODO @puhui999:权限管理???
38   - // ========== 客户管理 1_020_007_000 ==========
  37 + // ========== 权限管理 1_020_007_000 ==========
39 38 ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在");
40 39 ErrorCode CRM_PERMISSION_DENIED = new ErrorCode(1_020_007_001, "{}操作失败,原因:没有权限");
41 40 ErrorCode CRM_PERMISSION_MODEL_NOT_EXISTS = new ErrorCode(1_020_007_002, "{}不存在");
... ...
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/PermissionTypeEnum.java deleted
1   -package cn.iocoder.yudao.module.crm.enums.common;
2   -
3   -import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
4   -import lombok.AllArgsConstructor;
5   -import lombok.Getter;
6   -
7   -import java.util.Arrays;
8   -
9   -@Getter
10   -@AllArgsConstructor
11   -public enum PermissionTypeEnum implements IntArrayValuable {
12   -
13   - READONLY(1, "只读"),
14   - READ_AND_WRITE(2, "读写");
15   - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PermissionTypeEnum::getType).toArray();
16   -
17   - /**
18   - * 类型
19   - */
20   - private final Integer type;
21   - /**
22   - * 类型名
23   - */
24   - private final String name;
25   -
26   - @Override
27   - public int[] array() {
28   - return ARRAYS;
29   - }
30   -
31   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.http
  1 +### 请求 /transfer
1 2 PUT {{baseUrl}}/crm/business/transfer
2 3 Content-Type: application/json
3 4 Authorization: Bearer {{token}}
... ... @@ -8,4 +9,24 @@ tenant-id: {{adminTenentId}}
8 9 "ownerUserId": 2,
9 10 "transferType": 2,
10 11 "permissionType": 2
11   -}
12 12 \ No newline at end of file
  13 +}
  14 +
  15 +### 请求 /update
  16 +PUT {{baseUrl}}/crm/business/update
  17 +Content-Type: application/json
  18 +Authorization: Bearer {{token}}
  19 +tenant-id: {{adminTenentId}}
  20 +
  21 +{
  22 + "id": 1,
  23 + "name": "2",
  24 + "statusTypeId": 2,
  25 + "statusId": 2,
  26 + "customerId": 1
  27 +}
  28 +
  29 +### 请求 /get
  30 +GET {{baseUrl}}/crm/business/get?id=1024
  31 +Content-Type: application/json
  32 +Authorization: Bearer {{token}}
  33 +tenant-id: {{adminTenentId}}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmTransferBusinessReqVO.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.business.vo;
2 2  
3   -import cn.iocoder.yudao.framework.common.validation.InEnum;
4   -import cn.iocoder.yudao.module.crm.enums.common.PermissionTypeEnum;
5   -import cn.iocoder.yudao.module.crm.enums.common.TransferTypeEnum;
  3 +import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
6 4 import io.swagger.v3.oas.annotations.media.Schema;
7 5 import lombok.Data;
8 6  
... ... @@ -16,19 +14,25 @@ public class CrmTransferBusinessReqVO {
16 14 @NotNull(message = "联系人编号不能为空")
17 15 private Long id;
18 16  
19   - @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
  17 + /**
  18 + * 新负责人的用户编号
  19 + */
20 20 @NotNull(message = "新负责人的用户编号不能为空")
21   - private Long ownerUserId;
22   -
23   - @Schema(description = "原负责人移除方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
24   - @InEnum(TransferTypeEnum.class)
25   - @NotNull(message = "原负责人移除方式不能为空")
26   - private Integer transferType;
27   -
28   - @Schema(description = "权限类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
29   - @InEnum(PermissionTypeEnum.class)
30   - @NotNull(message = "权限类型不能为空")
31   - private Integer permissionType;
32   -
  21 + @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
  22 + private Long newOwnerUserId;
  23 +
  24 + /**
  25 + * 老负责人是否加入团队,是/否
  26 + */
  27 + @Schema(description = "老负责人是否加入团队", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
  28 + @NotNull(message = "老负责人是否加入团队不能为空")
  29 + private Boolean joinTeam;
  30 +
  31 + /**
  32 + * 老负责人加入团队后的权限级别。如果 {@link #joinTeam} 为 false, permissionLevel 为 null
  33 + * 关联 {@link CrmPermissionLevelEnum}
  34 + */
  35 + @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  36 + private Integer permissionLevel;
33 37  
34 38 }
... ...
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;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*;
5 5 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
6   -import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
  6 +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
7 7 import org.mapstruct.Mapper;
8 8 import org.mapstruct.Mapping;
9 9 import org.mapstruct.Mappings;
... ... @@ -32,9 +32,9 @@ public interface CrmBusinessConvert {
32 32 List<CrmBusinessExcelVO> convertList02(List<CrmBusinessDO> list);
33 33  
34 34 @Mappings({
35   - @Mapping(target = "userId", source = "userId"),
36   - @Mapping(target = "crmDataId", source = "reqVO.id")
  35 + @Mapping(target = "bizId", source = "reqVO.id"),
  36 + @Mapping(target = "newOwnerUserId", source = "reqVO.id")
37 37 })
38   - TransferCrmPermissionBO convert(CrmTransferBusinessReqVO reqVO, Long userId);
  38 + CrmTransferPermissionReqBO convert(CrmTransferBusinessReqVO reqVO, Long userId);
39 39  
40 40 }
... ...
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;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
5 5 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO;
6   -import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
  6 +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
7 7 import org.mapstruct.Mapper;
8 8 import org.mapstruct.Mapping;
9 9 import org.mapstruct.Mappings;
... ... @@ -34,9 +34,9 @@ public interface ContactConvert {
34 34 List<ContactExcelVO> convertList02(List<ContactDO> list);
35 35  
36 36 @Mappings({
37   - @Mapping(target = "userId", source = "userId"),
38   - @Mapping(target = "crmDataId", source = "reqVO.id")
  37 + @Mapping(target = "bizId", source = "reqVO.id"),
  38 + @Mapping(target = "newOwnerUserId", source = "reqVO.id")
39 39 })
40   - TransferCrmPermissionBO convert(CrmTransferContactReqVO reqVO, Long userId);
  40 + CrmTransferPermissionReqBO convert(CrmTransferContactReqVO reqVO, Long userId);
41 41  
42 42 }
... ...
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;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*;
5 5 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
6   -import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
  6 +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
7 7 import org.mapstruct.Mapper;
8 8 import org.mapstruct.Mapping;
9 9 import org.mapstruct.Mappings;
... ... @@ -34,9 +34,9 @@ public interface ContractConvert {
34 34 List<ContractExcelVO> convertList02(List<ContractDO> list);
35 35  
36 36 @Mappings({
37   - @Mapping(target = "userId", source = "userId"),
38   - @Mapping(target = "crmDataId", source = "reqVO.id")
  37 + @Mapping(target = "bizId", source = "reqVO.id"),
  38 + @Mapping(target = "newOwnerUserId", source = "reqVO.id")
39 39 })
40   - TransferCrmPermissionBO convert(CrmTransferContractReqVO reqVO, Long userId);
  40 + CrmTransferPermissionReqBO convert(CrmTransferContractReqVO reqVO, Long userId);
41 41  
42 42 }
... ...
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;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
5 5 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
6   -import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
  6 +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
7 7 import org.mapstruct.Mapper;
8 8 import org.mapstruct.Mapping;
9 9 import org.mapstruct.Mappings;
... ... @@ -32,9 +32,9 @@ public interface CrmCustomerConvert {
32 32 List<CrmCustomerExcelVO> convertList02(List<CrmCustomerDO> list);
33 33  
34 34 @Mappings({
35   - @Mapping(target = "userId", source = "userId"),
36   - @Mapping(target = "crmDataId", source = "reqVO.id")
  35 + @Mapping(target = "bizId", source = "reqVO.id"),
  36 + @Mapping(target = "newOwnerUserId", source = "reqVO.id")
37 37 })
38   - TransferCrmPermissionBO convert(CrmTransferCustomerReqVO reqVO, Long userId);
  38 + CrmTransferPermissionReqBO convert(CrmTransferCustomerReqVO reqVO, Long userId);
39 39  
40 40 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java
1 1 package cn.iocoder.yudao.module.crm.dal.dataobject.permission;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4   -import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
5   -import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
  4 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
  5 +import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
6 6 import com.baomidou.mybatisplus.annotation.KeySequence;
7   -import com.baomidou.mybatisplus.annotation.TableField;
8 7 import com.baomidou.mybatisplus.annotation.TableId;
9 8 import com.baomidou.mybatisplus.annotation.TableName;
10 9 import lombok.*;
11 10  
12   -import java.util.Set;
13   -
14 11 /**
15   - * crm 数据权限 DO
  12 + * Crm 数据权限 DO
16 13 *
17 14 * @author HUIHUI
18 15 */
19   -@TableName("crm_receivable")
20   -@KeySequence("crm_receivable_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  16 +@TableName("crm_permission")
  17 +@KeySequence("crm_permission_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
21 18 @Data
22 19 @EqualsAndHashCode(callSuper = true)
23 20 @ToString(callSuper = true)
... ... @@ -32,26 +29,20 @@ public class CrmPermissionDO extends BaseDO {
32 29 @TableId
33 30 private Long id;
34 31 /**
35   - * 数据类型 关联 {@link CrmEnum}
36   - */
37   - private Integer crmType;
38   - /**
39   - * 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId()
  32 + * 数据类型,关联 {@link CrmBizTypeEnum}
40 33 */
41   - private Long crmDataId;
  34 + private Integer bizType;
42 35 /**
43   - * 负责人的用户编号 关联 AdminUser#id
  36 + * 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
44 37 */
45   - private Long ownerUserId;
  38 + private Long bizId;
46 39 /**
47   - * 只读权限的用户编号数组
  40 + * 团队成员,关联 AdminUser#id
48 41 */
49   - @TableField(typeHandler = JsonLongSetTypeHandler.class)
50   - private Set<Long> roUserIds;
  42 + private Long userId;
51 43 /**
52   - * 读写权限的用户编号数组
  44 + * 权限级别,关联 {@link CrmPermissionLevelEnum}
53 45 */
54   - @TableField(typeHandler = JsonLongSetTypeHandler.class)
55   - private Set<Long> rwUserIds;
  46 + private Integer permissionLevel;
56 47  
57 48 }
... ...
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;
3 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 4 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
5 5 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
  6 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
6 7 import org.apache.ibatis.annotations.Mapper;
7 8  
  9 +import java.util.List;
  10 +
8 11 /**
9 12 * crm 数据权限 mapper
10 13 *
... ... @@ -13,9 +16,32 @@ import org.apache.ibatis.annotations.Mapper;
13 16 @Mapper
14 17 public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> {
15 18  
16   - default CrmPermissionDO selectByCrmTypeAndCrmDataId(Integer crmType, Long crmDataId) {
  19 + /**
  20 + * 获取用户数据权限通过 数据类型 x 某个数据 x 用户编号
  21 + *
  22 + * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
  23 + * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
  24 + * @param userId 用户编号,AdminUser#id
  25 + * @return Crm 数据权限
  26 + */
  27 + default CrmPermissionDO selectByBizTypeAndBizIdByUserId(Integer bizType, Long bizId, Long userId) {
17 28 return selectOne(new LambdaQueryWrapperX<CrmPermissionDO>()
18   - .eq(CrmPermissionDO::getCrmType, crmType).eq(CrmPermissionDO::getCrmDataId, crmDataId));
  29 + .eq(CrmPermissionDO::getBizType, bizType)
  30 + .eq(CrmPermissionDO::getBizId, bizId)
  31 + .eq(CrmPermissionDO::getUserId, userId));
  32 + }
  33 +
  34 + /**
  35 + * 获取数据权限列表通过 数据类型 x 某个数据
  36 + *
  37 + * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
  38 + * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
  39 + * @return Crm 数据权限列表
  40 + */
  41 + default List<CrmPermissionDO> selectByBizTypeAndBizId(Integer bizType, Long bizId) {
  42 + return selectList(new LambdaQueryWrapperX<CrmPermissionDO>()
  43 + .eq(CrmPermissionDO::getBizType, bizType)
  44 + .eq(CrmPermissionDO::getBizId, bizId));
19 45 }
20 46  
21 47 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java
1 1 package cn.iocoder.yudao.module.crm.framework.core.annotations;
2 2  
3   -import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
4   -import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
  3 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
  4 +import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
5 5  
6 6 import java.lang.annotation.Documented;
7 7 import java.lang.annotation.Retention;
... ... @@ -24,11 +24,17 @@ public @interface CrmPermission {
24 24 /**
25 25 * crm 类型
26 26 */
27   - CrmEnum crmType();
  27 + CrmBizTypeEnum bizType();
  28 +
  29 + /**
  30 + * 数据编号获取来源类,确保数据 id 编号在此类中,不能在父类中。
  31 + * 例:如果在 baseVO 中需要把 id 弄到 updateVO 中。
  32 + */
  33 + Class<?>[] getIdFor() default {};
28 34  
29 35 /**
30 36 * 操作类型
31 37 */
32   - OperationTypeEnum operationType();
  38 + CrmPermissionLevelEnum permissionLevel();
33 39  
34 40 }
... ...
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;
5 5 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
6 6 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
7 7 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
8   -import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
9 8 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
10 9 import lombok.extern.slf4j.Slf4j;
11 10 import org.aspectj.lang.JoinPoint;
... ... @@ -14,11 +13,13 @@ import org.aspectj.lang.annotation.Before;
14 13 import org.springframework.stereotype.Component;
15 14  
16 15 import javax.annotation.Resource;
  16 +import java.lang.reflect.Field;
  17 +import java.util.List;
17 18  
18 19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
19 20 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
20 21 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED;
21   -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_MODEL_NOT_EXISTS;
  22 +import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum.*;
22 23  
23 24 /**
24 25 * Crm 数据权限校验 AOP 切面
... ... @@ -42,54 +43,67 @@ public class CrmPermissionAspect {
42 43 return WebFrameworkUtils.getLoginUserId();
43 44 }
44 45  
  46 + private Long getBizId(JoinPoint joinPoint, CrmPermission crmPermission) throws NoSuchFieldException, IllegalAccessException {
  47 + Object[] args = joinPoint.getArgs();
  48 + for (Object arg : args) {
  49 + if (arg == null) {
  50 + continue;
  51 + }
  52 + if (ObjUtil.notEqual(arg.getClass().getName(), crmPermission.getIdFor()[0].getName())) {
  53 + continue;
  54 + }
  55 + // 使用反射获取id属性
  56 + Field idValue = arg.getClass().getDeclaredField("id");
  57 + // 设置字段为可访问
  58 + idValue.setAccessible(true);
  59 + return (Long) idValue.get(arg);
  60 + }
  61 + return null;
  62 + }
  63 +
45 64 @Before("@annotation(crmPermission)")
46 65 public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) {
47 66 try {
48   - Integer crmType = crmPermission.crmType().getType();
49   - Integer operationType = crmPermission.operationType().getType();
50   - // TODO @puhui999:不一定是 id 参数噢;例如说,ContactServiceImpl 的 updateContact
51   - Long id = (Long) joinPoint.getArgs()[0];// 获取操作数据的编号
  67 + Long bizId = crmPermission.getIdFor().length > 0 ? getBizId(joinPoint, crmPermission) : (Long) joinPoint.getArgs()[0]; // 获取操作数据的编号
  68 + Integer bizType = crmPermission.bizType().getType(); // 模块类型
  69 + Integer permissionLevel = crmPermission.permissionLevel().getLevel(); // 需要的权限级别
52 70  
53   - // 1.1 获取数据权限
54   - CrmPermissionDO permission = crmPermissionService.getCrmPermissionByCrmTypeAndCrmDataId(crmType, id);
55   - if (permission == null) {
56   - // 不存在说明数据也不存在
57   - throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, crmPermission.crmType().getName());
58   - }
59   - // 1.2 校验是否为公海数据
60   - // TODO @puhui999:这个判断去掉比较合适哈。这里更多是业务逻辑,不算权限判断。例如说,公海的客户,只要没负责人,就可以领取了;
61   - if (permission.getOwnerUserId() == null) {
62   - return;
63   - }
64   - // 1.3 校验当前负责人是不是自己
65   - if (ObjUtil.equal(permission.getOwnerUserId(), getUserId())) {
  71 + // TODO 如果是超级管理员则直接通过
  72 + //if (superAdmin){
  73 + // return;
  74 + //}
  75 +
  76 + // 1. 获取数据权限
  77 + List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
  78 + CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, item -> ObjUtil.equal(item.getUserId(), getUserId()));
  79 + if (isOwner(userPermission.getPermissionLevel())) { // 校验自己是否是负责人
66 80 return;
67 81 }
68   - // 1.4 TODO 校验是否为超级管理员
69   -
70   - // 2. 校验是否有读权限
71   - if (OperationTypeEnum.isRead(operationType)) {
72   - // 校验该数据当前用户是否可读
73   - // TODO @puhui999:直接 CollUtil.contains 就好,因为就是有某个 userId 呀
74   - boolean isRead = CollUtil.contains(permission.getRoUserIds(), item -> ObjUtil.equal(item, getUserId()))
75   - || CollUtil.contains(permission.getRwUserIds(), item -> ObjUtil.equal(item, getUserId()));
76   - if (isRead) {
  82 + if (isRead(permissionLevel)) { // 读权限
  83 + // 如果没有数据权限或没有负责人则表示此记录为公海数据所有人都有只读权限
  84 + if (CollUtil.isEmpty(bizPermissions) || !CollUtil.anyMatch(bizPermissions, item -> isOwner(item.getPermissionLevel()))) {
  85 + return;
  86 + }
  87 + if (isRead(userPermission.getPermissionLevel())) { // 校验当前用户是否有读权限
  88 + return;
  89 + }
  90 + //如果查询数据的话拥有写权限的也能查询
  91 + if (isWrite(userPermission.getPermissionLevel())) { // 校验当前用户是否有写权限
77 92 return;
78 93 }
79 94 }
80   -
81   - // 3. 校验是否有编辑权限
82   - if (OperationTypeEnum.isEdit(operationType)) {
83   - // 校验该数据当前用户是否可读写
84   - if (CollUtil.contains(permission.getRwUserIds(), item -> ObjUtil.equal(item, getUserId()))) {
  95 + if (isWrite(permissionLevel)) { // 写权限
  96 + if (isWrite(userPermission.getPermissionLevel())) { // 校验当前用户是否有写权限
85 97 return;
86 98 }
87 99 }
88 100  
89   - // 4. 没通过结束,报错 {}操作失败,原因:没有权限
90   - throw exception(CRM_PERMISSION_DENIED, crmPermission.crmType().getName());
  101 + // 2. 没通过结束,报错 {}操作失败,原因:没有权限
  102 + throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType().getName());
91 103 } catch (Exception ex) {
92 104 log.error("[doBefore][crmPermission({}) 数据校验错误]", toJsonString(crmPermission), ex);
  105 + // TODO 报错抛个什么异常好呢
  106 + throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType().getName());
93 107 }
94 108 }
95 109  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmEnum.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmBizTypeEnum.java
1 1 package cn.iocoder.yudao.module.crm.framework.enums;
2 2  
3 3 import cn.hutool.core.util.ObjUtil;
  4 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
4 5 import lombok.Getter;
5 6 import lombok.RequiredArgsConstructor;
6 7  
7   -// TODO @puhui999:可以改成 CrmBizTypeEnum,CRM 业务类型枚举
  8 +import java.util.Arrays;
  9 +
8 10 /**
9 11 * Crm 类型枚举
10 12 *
... ... @@ -12,7 +14,7 @@ import lombok.RequiredArgsConstructor;
12 14 */
13 15 @RequiredArgsConstructor
14 16 @Getter
15   -public enum CrmEnum {
  17 +public enum CrmBizTypeEnum implements IntArrayValuable {
16 18  
17 19 CRM_LEADS(1, "线索"),
18 20 CRM_CUSTOMER(2, "客户"),
... ... @@ -20,6 +22,7 @@ public enum CrmEnum {
20 22 CRM_BUSINESS(5, "商机"),
21 23 CRM_CONTRACT(6, "合同");
22 24  
  25 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizTypeEnum::getType).toArray();
23 26 /**
24 27 * 类型
25 28 */
... ... @@ -30,12 +33,17 @@ public enum CrmEnum {
30 33 private final String name;
31 34  
32 35 public static String getNameByType(Integer type) {
33   - for (CrmEnum crmEnum : CrmEnum.values()) {
34   - if (ObjUtil.equal(crmEnum.type, type)) {
35   - return crmEnum.name;
  36 + for (CrmBizTypeEnum crmBizTypeEnum : CrmBizTypeEnum.values()) {
  37 + if (ObjUtil.equal(crmBizTypeEnum.type, type)) {
  38 + return crmBizTypeEnum.name;
36 39 }
37 40 }
38 41 return "";
39 42 }
40 43  
  44 + @Override
  45 + public int[] array() {
  46 + return ARRAYS;
  47 + }
  48 +
41 49 }
... ...
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/TransferTypeEnum.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmPermissionLevelEnum.java
1   -package cn.iocoder.yudao.module.crm.enums.common;
  1 +package cn.iocoder.yudao.module.crm.framework.enums;
2 2  
  3 +import cn.hutool.core.util.ObjUtil;
3 4 import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
4 5 import lombok.AllArgsConstructor;
5 6 import lombok.Getter;
6 7  
7 8 import java.util.Arrays;
8 9  
9   -// TODO @puhui999:这个可以不用哈
10 10 /**
11   - * Crm 负责人转移后原负责人的处理方式
  11 + * Crm 数据权限级别枚举
12 12 *
13 13 * @author HUIHUI
14 14 */
15 15 @Getter
16 16 @AllArgsConstructor
17   -public enum TransferTypeEnum implements IntArrayValuable {
  17 +public enum CrmPermissionLevelEnum implements IntArrayValuable {
18 18  
19   - REMOVE(1, "移除"),
20   - TEAM(2, "转为团队成员");
21   -
22   - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TransferTypeEnum::getType).toArray();
  19 + OWNER(1, "负责人"),
  20 + READ(2, "读"),
  21 + WRITE(3, "写");
  22 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmPermissionLevelEnum::getLevel).toArray();
23 23  
24 24 /**
25   - * 类型
  25 + * 级别
26 26 */
27   - private final Integer type;
  27 + private final Integer level;
28 28 /**
29   - * 类型名
  29 + * 级别名称
30 30 */
31 31 private final String name;
32 32  
... ... @@ -35,4 +35,16 @@ public enum TransferTypeEnum implements IntArrayValuable {
35 35 return ARRAYS;
36 36 }
37 37  
  38 + public static boolean isOwner(Integer level) {
  39 + return ObjUtil.equal(OWNER.level, level);
  40 + }
  41 +
  42 + public static boolean isRead(Integer level) {
  43 + return ObjUtil.equal(READ.level, level);
  44 + }
  45 +
  46 + public static boolean isWrite(Integer level) {
  47 + return ObjUtil.equal(WRITE.level, level);
  48 + }
  49 +
38 50 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/OperationTypeEnum.java deleted
1   -package cn.iocoder.yudao.module.crm.framework.enums;
2   -
3   -import cn.hutool.core.util.ObjUtil;
4   -import lombok.Getter;
5   -import lombok.RequiredArgsConstructor;
6   -
7   -// TODO @puhui999:是不是可以和 PermissionTypeEnum 合并,就是 CrmPermissionEnum,负责人、读取、读写;目前阶段,不用做的特别细致;类似 linux 的 acl;
8   -/**
9   - * Crm 数据操作类型枚举
10   - *
11   - * @author HUIHUI
12   - */
13   -@RequiredArgsConstructor
14   -@Getter
15   -public enum OperationTypeEnum {
16   -
17   - // TODO @puhui999:抽象上,就分三种,会更合理。一个 OWNER 负责人,一个 READ 读,一个 WRITE 写;
18   - DELETE(1, "删除"),
19   - UPDATE(2, "修改"),
20   - READ(3, "查询");
21   -
22   - /**
23   - * 类型
24   - */
25   - private final Integer type;
26   -
27   - /**
28   - * 名称
29   - */
30   - private final String name;
31   -
32   - public static boolean isRead(Integer type) {
33   - return ObjUtil.equal(type, READ.getType());
34   - }
35   -
36   - public static boolean isEdit(Integer type) {
37   - return ObjUtil.equal(type, UPDATE.getType()) || ObjUtil.equal(type, DELETE.getType());
38   - }
39   -
40   -}
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;
8 8 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
9 9 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
10 10 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
11   -import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
12   -import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
  11 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
  12 +import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
13 13 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
14 14 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
15 15 import org.springframework.stereotype.Service;
... ... @@ -46,7 +46,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
46 46 businessMapper.insert(business);
47 47  
48 48 // 创建数据权限
49   - crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_BUSINESS.getType())
  49 + crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmBizTypeEnum.CRM_BUSINESS.getType())
50 50 .setCrmDataId(business.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人
51 51  
52 52 // 返回
... ... @@ -55,7 +55,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
55 55  
56 56 @Override
57 57 @Transactional(rollbackFor = Exception.class)
58   - @CrmPermission(crmType = CrmEnum.CRM_BUSINESS, operationType = OperationTypeEnum.UPDATE)
  58 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, getIdFor = CrmBusinessUpdateReqVO.class,
  59 + permissionLevel = CrmPermissionLevelEnum.WRITE)
59 60 public void updateBusiness(CrmBusinessUpdateReqVO updateReqVO) {
60 61 // 校验存在
61 62 validateBusinessExists(updateReqVO.getId());
... ... @@ -66,7 +67,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
66 67  
67 68 @Override
68 69 @Transactional(rollbackFor = Exception.class)
69   - @CrmPermission(crmType = CrmEnum.CRM_BUSINESS, operationType = OperationTypeEnum.DELETE)
  70 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, permissionLevel = CrmPermissionLevelEnum.WRITE)
70 71 public void deleteBusiness(Long id) {
71 72 // 校验存在
72 73 validateBusinessExists(id);
... ... @@ -83,7 +84,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
83 84 }
84 85  
85 86 @Override
86   - @CrmPermission(crmType = CrmEnum.CRM_BUSINESS, operationType = OperationTypeEnum.READ)
  87 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, permissionLevel = CrmPermissionLevelEnum.READ)
87 88 public CrmBusinessDO getBusiness(Long id) {
88 89 return businessMapper.selectById(id);
89 90 }
... ... @@ -114,7 +115,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
114 115  
115 116 // 2. 数据权限转移
116 117 crmPermissionService.transferCrmPermission(
117   - CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_BUSINESS.getType()));
  118 + CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()));
118 119  
119 120 }
120 121  
... ...
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;
8 8 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO;
9 9 import cn.iocoder.yudao.module.crm.dal.mysql.contact.ContactMapper;
10 10 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
11   -import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
12   -import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
  11 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
  12 +import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
13 13 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
14 14 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
15 15 import org.springframework.stereotype.Service;
... ... @@ -46,7 +46,7 @@ public class ContactServiceImpl implements ContactService {
46 46 contactMapper.insert(contact);
47 47  
48 48 // 创建数据权限
49   - crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_BUSINESS.getType())
  49 + crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmBizTypeEnum.CRM_BUSINESS.getType())
50 50 .setCrmDataId(contact.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人
51 51  
52 52 // 返回
... ... @@ -55,7 +55,7 @@ public class ContactServiceImpl implements ContactService {
55 55  
56 56 @Override
57 57 @Transactional(rollbackFor = Exception.class)
58   - @CrmPermission(crmType = CrmEnum.CRM_CONTACTS, operationType = OperationTypeEnum.UPDATE)
  58 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, permissionLevel = CrmPermissionLevelEnum.WRITE)
59 59 public void updateContact(ContactUpdateReqVO updateReqVO) {
60 60 // 校验存在
61 61 validateContactExists(updateReqVO.getId());
... ... @@ -68,7 +68,7 @@ public class ContactServiceImpl implements ContactService {
68 68  
69 69 @Override
70 70 @Transactional(rollbackFor = Exception.class)
71   - @CrmPermission(crmType = CrmEnum.CRM_CONTACTS, operationType = OperationTypeEnum.DELETE)
  71 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, permissionLevel = CrmPermissionLevelEnum.WRITE)
72 72 public void deleteContact(Long id) {
73 73 // 校验存在
74 74 validateContactExists(id);
... ... @@ -85,7 +85,7 @@ public class ContactServiceImpl implements ContactService {
85 85 }
86 86  
87 87 @Override
88   - @CrmPermission(crmType = CrmEnum.CRM_CONTACTS, operationType = OperationTypeEnum.READ)
  88 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, permissionLevel = CrmPermissionLevelEnum.READ)
89 89 public ContactDO getContact(Long id) {
90 90 return contactMapper.selectById(id);
91 91 }
... ... @@ -115,7 +115,7 @@ public class ContactServiceImpl implements ContactService {
115 115  
116 116 // 2. 数据权限转移
117 117 crmPermissionService.transferCrmPermission(
118   - ContactConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_CONTACTS.getType()));
  118 + ContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACTS.getType()));
119 119  
120 120 }
121 121  
... ...
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;
8 8 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
9 9 import cn.iocoder.yudao.module.crm.dal.mysql.contract.ContractMapper;
10 10 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
11   -import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
12   -import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
  11 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
  12 +import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
13 13 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
14 14 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
15 15 import org.springframework.stereotype.Service;
... ... @@ -45,7 +45,7 @@ public class ContractServiceImpl implements ContractService {
45 45 contractMapper.insert(contract);
46 46  
47 47 // 创建数据权限
48   - crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_CONTRACT.getType())
  48 + crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmBizTypeEnum.CRM_CONTRACT.getType())
49 49 .setCrmDataId(contract.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人
50 50  
51 51 // 返回
... ... @@ -54,7 +54,7 @@ public class ContractServiceImpl implements ContractService {
54 54  
55 55 @Override
56 56 @Transactional(rollbackFor = Exception.class)
57   - @CrmPermission(crmType = CrmEnum.CRM_CONTRACT, operationType = OperationTypeEnum.DELETE)
  57 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, permissionLevel = CrmPermissionLevelEnum.WRITE)
58 58 public void updateContract(ContractUpdateReqVO updateReqVO) {
59 59 // 校验存在
60 60 validateContractExists(updateReqVO.getId());
... ... @@ -65,7 +65,7 @@ public class ContractServiceImpl implements ContractService {
65 65  
66 66 @Override
67 67 @Transactional(rollbackFor = Exception.class)
68   - @CrmPermission(crmType = CrmEnum.CRM_CONTRACT, operationType = OperationTypeEnum.DELETE)
  68 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, permissionLevel = CrmPermissionLevelEnum.WRITE)
69 69 public void deleteContract(Long id) {
70 70 // 校验存在
71 71 validateContractExists(id);
... ... @@ -82,7 +82,7 @@ public class ContractServiceImpl implements ContractService {
82 82 }
83 83  
84 84 @Override
85   - @CrmPermission(crmType = CrmEnum.CRM_CONTRACT, operationType = OperationTypeEnum.READ)
  85 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, permissionLevel = CrmPermissionLevelEnum.READ)
86 86 public ContractDO getContract(Long id) {
87 87 return contractMapper.selectById(id);
88 88 }
... ... @@ -113,7 +113,7 @@ public class ContractServiceImpl implements ContractService {
113 113  
114 114 // 2. 数据权限转移
115 115 crmPermissionService.transferCrmPermission(
116   - ContractConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_CONTRACT.getType()));
  116 + ContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()));
117 117  
118 118 }
119 119  
... ...
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;
8 8 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
9 9 import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper;
10 10 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
11   -import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
12   -import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum;
  11 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
  12 +import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
13 13 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
14 14 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
15 15 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
... ... @@ -48,7 +48,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
48 48 customerMapper.insert(customer);
49 49  
50 50 // 创建数据权限
51   - crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_CUSTOMER.getType())
  51 + crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
52 52 .setCrmDataId(customer.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人
53 53  
54 54 // 返回
... ... @@ -57,7 +57,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
57 57  
58 58 @Override
59 59 @Transactional(rollbackFor = Exception.class)
60   - @CrmPermission(crmType = CrmEnum.CRM_CUSTOMER, operationType = OperationTypeEnum.UPDATE)
  60 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, permissionLevel = CrmPermissionLevelEnum.WRITE)
61 61 public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) {
62 62 // 校验存在
63 63 validateCustomerExists(updateReqVO.getId());
... ... @@ -70,7 +70,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
70 70  
71 71 @Override
72 72 @Transactional(rollbackFor = Exception.class)
73   - @CrmPermission(crmType = CrmEnum.CRM_CUSTOMER, operationType = OperationTypeEnum.DELETE)
  73 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, permissionLevel = CrmPermissionLevelEnum.WRITE)
74 74 public void deleteCustomer(Long id) {
75 75 // 校验存在
76 76 validateCustomerExists(id);
... ... @@ -87,7 +87,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
87 87 }
88 88  
89 89 @Override
90   - @CrmPermission(crmType = CrmEnum.CRM_CUSTOMER, operationType = OperationTypeEnum.READ)
  90 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, permissionLevel = CrmPermissionLevelEnum.READ)
91 91 public CrmCustomerDO getCustomer(Long id) {
92 92 return customerMapper.selectById(id);
93 93 }
... ... @@ -135,7 +135,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
135 135  
136 136 // 2. 数据权限转移
137 137 crmPermissionService.transferCrmPermission(
138   - CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_CUSTOMER.getType()));
  138 + CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()));
139 139 }
140 140  
141 141 }
... ...
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;
2 2  
3 3  
4 4 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
5   -import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
  5 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
6 6 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
7 7 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateBO;
8   -import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
  8 +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
9 9  
10 10 import javax.validation.Valid;
  11 +import java.util.List;
11 12  
12 13 /**
13 14 * crm 数据权限 Service 接口
... ... @@ -40,19 +41,29 @@ public interface CrmPermissionService {
40 41 void deleteCrmPermission(Long id);
41 42  
42 43 /**
43   - * 获得数据权限
  44 + * 获取用户数据权限通过 数据类型 x 某个数据 x 用户编号
44 45 *
45   - * @param crmType 数据类型 关联 {@link CrmEnum}
46   - * @param crmDataId 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId()
47   - * @return 数据权限
  46 + * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
  47 + * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
  48 + * @param userId 用户编号,AdminUser#id
  49 + * @return Crm 数据权限
48 50 */
49   - CrmPermissionDO getCrmPermissionByCrmTypeAndCrmDataId(Integer crmType, Long crmDataId);
  51 + CrmPermissionDO getPermissionByBizTypeAndBizIdAndUserId(Integer bizType, Long bizId, Long userId);
  52 +
  53 + /**
  54 + * 获取数据权限列表,通过 数据类型 x 某个数据
  55 + *
  56 + * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
  57 + * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
  58 + * @return Crm 数据权限列表
  59 + */
  60 + List<CrmPermissionDO> getPermissionByBizTypeAndBizId(Integer bizType, Long bizId);
50 61  
51 62 /**
52 63 * 数据权限转移
53 64 *
54   - * @param transferCrmPermissionBO 数据权限转移请求
  65 + * @param crmTransferPermissionReqBO 数据权限转移请求
55 66 */
56   - void transferCrmPermission(@Valid TransferCrmPermissionBO transferCrmPermissionBO);
  67 + void transferCrmPermission(@Valid CrmTransferPermissionReqBO crmTransferPermissionReqBO);
57 68  
58 69 }
... ...
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;
5 5 import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert;
6 6 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
7 7 import cn.iocoder.yudao.module.crm.dal.mysql.permission.CrmPermissionMapper;
8   -import cn.iocoder.yudao.module.crm.enums.common.PermissionTypeEnum;
9   -import cn.iocoder.yudao.module.crm.enums.common.TransferTypeEnum;
10   -import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
  8 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
  9 +import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
11 10 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO;
12 11 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateBO;
13   -import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO;
  12 +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
14 13 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
15 14 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
16 15 import org.springframework.stereotype.Service;
... ... @@ -18,10 +17,11 @@ import org.springframework.transaction.annotation.Transactional;
18 17 import org.springframework.validation.annotation.Validated;
19 18  
20 19 import javax.annotation.Resource;
21   -import java.util.Set;
  20 +import java.util.List;
22 21  
23 22 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
24 23 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
  24 +import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum.isOwner;
25 25  
26 26 /**
27 27 * crm 数据权限 Service 接口实现类
... ... @@ -41,10 +41,9 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
41 41 @Override
42 42 @Transactional(rollbackFor = Exception.class)
43 43 public Long createCrmPermission(CrmPermissionCreateBO createBO) {
44   - // TODO @puhui999:createDO 改成 permission,保持统一哈;
45   - CrmPermissionDO createDO = CrmPermissionConvert.INSTANCE.convert(createBO);
46   - crmPermissionMapper.insert(createDO);
47   - return createDO.getId();
  44 + CrmPermissionDO permission = CrmPermissionConvert.INSTANCE.convert(createBO);
  45 + crmPermissionMapper.insert(permission);
  46 + return permission.getId();
48 47 }
49 48  
50 49 @Override
... ... @@ -64,64 +63,67 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
64 63 crmPermissionMapper.deleteById(id);
65 64 }
66 65  
  66 + @Override
  67 + public CrmPermissionDO getPermissionByBizTypeAndBizIdAndUserId(Integer bizType, Long bizId, Long userId) {
  68 + return crmPermissionMapper.selectByBizTypeAndBizIdByUserId(bizType, bizId, userId);
  69 + }
  70 +
  71 + @Override
  72 + public List<CrmPermissionDO> getPermissionByBizTypeAndBizId(Integer bizType, Long bizId) {
  73 + return crmPermissionMapper.selectByBizTypeAndBizId(bizType, bizId);
  74 + }
  75 +
67 76 private void validateCrmPermissionExists(Long id) {
68 77 if (crmPermissionMapper.selectById(id) == null) {
69 78 throw exception(CRM_PERMISSION_NOT_EXISTS);
70 79 }
71 80 }
72 81  
73   - @Override
74   - public CrmPermissionDO getCrmPermissionByCrmTypeAndCrmDataId(Integer crmType, Long crmDataId) {
75   - return crmPermissionMapper.selectByCrmTypeAndCrmDataId(crmType, crmDataId);
76   - }
77 82  
78   - // TODO @puhui999:参数名,是不是 transferReqBO
79 83 @Override
80   - public void transferCrmPermission(TransferCrmPermissionBO transferCrmPermissionBO) {
81   - // 1.1 校验商机是否存在
82   - // TODO puhui999:这里直接调用 crmPermissionMapper 的 selectByCrmTypeAndCrmDataId 方法,会更简洁一点;
83   - CrmPermissionDO permission = getCrmPermissionByCrmTypeAndCrmDataId(transferCrmPermissionBO.getCrmType(),
84   - transferCrmPermissionBO.getCrmDataId());
85   - String crmName = CrmEnum.getNameByType(transferCrmPermissionBO.getCrmType());
86   - if (permission == null) {
87   - throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, crmName);
88   - }
89   - // 1.2 校验转移对象是否已经是该负责人
90   - if (ObjUtil.equal(permission.getOwnerUserId(), permission.getOwnerUserId())) {
91   - // TODO @puhui999:是不是这个错误码不太对。。。
92   - throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_NOT_EXISTS, crmName);
  84 + public void transferCrmPermission(CrmTransferPermissionReqBO transferReqBO) {
  85 + // 1. 校验数据权限-是否是负责人,只有负责人才可以转移
  86 + CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId(transferReqBO.getBizType(),
  87 + transferReqBO.getBizId(), transferReqBO.getUserId());
  88 + String crmName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType());
  89 + // TODO 校验是否为超级管理员 || 1
  90 + if (oldPermission == null || !isOwner(oldPermission.getPermissionLevel())) {
  91 + throw exception(CRM_PERMISSION_DENIED, crmName);
93 92 }
94   - // 1.3 校验新负责人是否存在
95   - AdminUserRespDTO user = adminUserApi.getUser(permission.getOwnerUserId());
96   - if (user == null) {
  93 +
  94 + // 2. 校验转移对象是否已经是该负责人
  95 + if (ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) {
97 96 throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, crmName);
98 97 }
99   - // TODO 校验是否为超级管理员 || 1.4
100   - // 1.4 校验是否有写权限
101   - // TODO puhui999:CollUtil.contains 就够了,不用后面写个表达式;
102   - if (!CollUtil.contains(permission.getRwUserIds(), id -> ObjUtil.equal(id, transferCrmPermissionBO.getUserId()))) {
103   - throw exception(CRM_PERMISSION_DENIED, crmName);
  98 + // 2.1 校验新负责人是否存在
  99 + AdminUserRespDTO user = adminUserApi.getUser(transferReqBO.getNewOwnerUserId());
  100 + if (user == null) {
  101 + throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_NOT_EXISTS, crmName);
104 102 }
105 103  
106   - // 2. 权限转移
107   - CrmPermissionDO updateCrmPermission = new CrmPermissionDO().setId(permission.getId())
108   - .setOwnerUserId(transferCrmPermissionBO.getOwnerUserId());
109   - if (ObjUtil.equal(TransferTypeEnum.TEAM.getType(), transferCrmPermissionBO.getTransferType())) {
110   - if (ObjUtil.equal(PermissionTypeEnum.READONLY.getType(), transferCrmPermissionBO.getPermissionType())) {
111   - Set<Long> roUserIds = permission.getRoUserIds();
112   - roUserIds.add(permission.getOwnerUserId()); // 老负责人加入团队有只读权限
113   - updateCrmPermission.setRoUserIds(roUserIds);
114   - }
115   - if (ObjUtil.equal(PermissionTypeEnum.READ_AND_WRITE.getType(), transferCrmPermissionBO.getPermissionType())) {
116   - Set<Long> rwUserIds = permission.getRwUserIds();
117   - rwUserIds.add(permission.getOwnerUserId()); // 老负责人加入团队有读写权限
118   - updateCrmPermission.setRoUserIds(rwUserIds);
119   - }
  104 + // 3. 权限转移
  105 + List<CrmPermissionDO> permissions = crmPermissionMapper.selectByBizTypeAndBizId(
  106 + transferReqBO.getBizType(), transferReqBO.getBizId()); // 获取所有团队成员
  107 + // 3.1 校验新负责人是否在团队成员中
  108 + CrmPermissionDO permission = CollUtil.findOne(permissions,
  109 + item -> ObjUtil.equal(item.getUserId(), transferReqBO.getNewOwnerUserId()));
  110 + if (permission == null) { // 不存在则以负责人的级别加入这个团队
  111 + crmPermissionMapper.insert(new CrmPermissionDO().setBizType(transferReqBO.getBizType())
  112 + .setBizId(transferReqBO.getBizId()).setUserId(transferReqBO.getNewOwnerUserId())
  113 + .setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
  114 +
  115 + } else { // 存在则修改权限级别
  116 + crmPermissionMapper.updateById(new CrmPermissionDO().setId(permission.getId())
  117 + .setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
120 118 }
121   - crmPermissionMapper.updateById(updateCrmPermission);
122 119  
123   - // 3. TODO 记录机转移日志
124   - // TODO @puhui999:是不是交给业务记录哈;
  120 + // 4. 老负责人处理
  121 + if (transferReqBO.getJoinTeam()) { // 加入团队
  122 + crmPermissionMapper.updateById(new CrmPermissionDO().setId(oldPermission.getId())
  123 + .setPermissionLevel(transferReqBO.getPermissionLevel())); // 设置加入团队后的级别
  124 + return;
  125 + }
  126 + crmPermissionMapper.deleteById(oldPermission.getId()); // 移除
125 127 }
126 128  
127 129 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateBO.java
1 1 package cn.iocoder.yudao.module.crm.service.permission.bo;
2 2  
3   -import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
  3 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
4 4 import lombok.Data;
5 5  
6 6 import javax.validation.constraints.NotNull;
... ... @@ -18,12 +18,12 @@ public class CrmPermissionCreateBO {
18 18 // TODO @puhui999:如果是关联字段,换一行写它的注释;不然看着略乱哈
19 19  
20 20 /**
21   - * Crm 类型 关联 {@link CrmEnum}
  21 + * Crm 类型 关联 {@link CrmBizTypeEnum}
22 22 */
23 23 @NotNull(message = "Crm 类型不能为空")
24 24 private Integer crmType;
25 25 /**
26   - * 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId()
  26 + * 数据编号 关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
27 27 */
28 28 @NotNull(message = "Crm 数据编号不能为空")
29 29 private Long crmDataId;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateBO.java
1 1 package cn.iocoder.yudao.module.crm.service.permission.bo;
2 2  
3 3 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
4   -import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
  4 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
5 5 import lombok.Data;
6 6  
7 7 import javax.validation.constraints.NotNull;
... ... @@ -24,12 +24,12 @@ public class CrmPermissionUpdateBO {
24 24 private Long id;
25 25  
26 26 /**
27   - * Crm 类型 关联 {@link CrmEnum}
  27 + * Crm 类型 关联 {@link CrmBizTypeEnum}
28 28 */
29 29 @NotNull(message = "Crm 类型不能为空")
30 30 private Integer crmType;
31 31 /**
32   - * 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId()
  32 + * 数据编号 关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
33 33 */
34 34 @NotNull(message = "Crm 数据编号不能为空")
35 35 private Long crmDataId;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmTransferPermissionReqBO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.service.permission.bo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  4 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
  5 +import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
  6 +import lombok.Data;
  7 +
  8 +import javax.validation.constraints.NotNull;
  9 +
  10 +/**
  11 + * 数据权限转移 Request BO
  12 + *
  13 + * @author HUIHUI
  14 + */
  15 +@Data
  16 +public class CrmTransferPermissionReqBO {
  17 +
  18 + /**
  19 + * 当前登录用户编号
  20 + */
  21 + @NotNull(message = "用户编号不能为空")
  22 + private Long userId;
  23 +
  24 + /**
  25 + * Crm 类型
  26 + */
  27 + @NotNull(message = "Crm 类型不能为空")
  28 + @InEnum(CrmBizTypeEnum.class)
  29 + private Integer bizType;
  30 +
  31 + /**
  32 + * 数据编号
  33 + */
  34 + @NotNull(message = "Crm 数据编号不能为空")
  35 + private Long bizId;
  36 +
  37 + /**
  38 + * 新负责人的用户编号
  39 + */
  40 + @NotNull(message = "新负责人的用户编号不能为空")
  41 + private Long newOwnerUserId;
  42 +
  43 + /**
  44 + * 老负责人是否加入团队,是/否
  45 + */
  46 + @NotNull(message = "老负责人是否加入团队不能为空")
  47 + private Boolean joinTeam;
  48 +
  49 + /**
  50 + * 老负责人加入团队后的权限级别。如果 {@link #joinTeam} 为 false, permissionLevel 为 null
  51 + * 关联 {@link CrmPermissionLevelEnum}
  52 + */
  53 + private Integer permissionLevel;
  54 +
  55 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/TransferCrmPermissionBO.java deleted
1   -package cn.iocoder.yudao.module.crm.service.permission.bo;
2   -
3   -import cn.iocoder.yudao.module.crm.enums.common.PermissionTypeEnum;
4   -import cn.iocoder.yudao.module.crm.enums.common.TransferTypeEnum;
5   -import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum;
6   -import lombok.Data;
7   -
8   -import javax.validation.constraints.NotNull;
9   -
10   -// TODO @puhui999:CrmTransferPermissionReqBO,一个是 Crm 前缀,一个 Req 表示入参
11   -/**
12   - * 数据权限转移 BO
13   - *
14   - * @author HUIHUI
15   - */
16   -@Data
17   -public class TransferCrmPermissionBO {
18   -
19   - // TODO @puhui999:参数的注释
20   - @NotNull(message = "用户编号不能为空")
21   - private Long userId;
22   -
23   - // TODO @puhui999:bizType
24   - /**
25   - * Crm 类型 关联 {@link CrmEnum} TODO 这种不用再写关联了,直接 @InEnum 参数校验
26   - */
27   - @NotNull(message = "Crm 类型不能为空")
28   - private Integer crmType;
29   -
30   - // TODO @puhui999:bizId
31   - /**
32   - * 数据编号
33   - */
34   - @NotNull(message = "Crm 数据编号不能为空")
35   - private Long crmDataId;
36   -
37   - // TODO @puhui999:要不这里改成 newOwnerUserId;然后,transferType 和 permissionType,合并成 oldOwnerPermission(空就是移除)
38   - @NotNull(message = "新负责人的用户编号不能为空")
39   - private Long ownerUserId;
40   -
41   - /**
42   - * 原负责人移除方式, 关联 {@link TransferTypeEnum} TODO 这种不用再写关联了,直接 @InEnum 参数校验
43   - */
44   - @NotNull(message = "原负责人移除方式不能为空")
45   - private Integer transferType;
46   -
47   - /**
48   - * 权限类型, 关联 {@link PermissionTypeEnum}
49   - */
50   - @NotNull(message = "权限类型不能为空")
51   - private Integer permissionType;
52   -
53   -}