Browse Source

crm:code review 数据权限的实现

YunaiV 1 year ago
parent
commit
899e40deb9
14 changed files with 191 additions and 190 deletions
  1. 34 34
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
  2. 1 1
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java
  3. 28 32
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
  4. 10 5
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java
  5. 7 11
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java
  6. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java
  7. 2 9
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
  8. 44 41
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java
  9. 2 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmBizTypeEnum.java
  10. 18 15
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
  11. 13 10
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
  12. 3 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java
  13. 27 27
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java
  14. 1 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java

+ 34 - 34
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java

@@ -73,6 +73,23 @@ public class CollectionUtils {
         return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toList());
     }
 
+    public static <T, U> List<U> convertListByFlatMap(Collection<T> from,
+                                                      Function<T, ? extends Stream<? extends U>> func) {
+        if (CollUtil.isEmpty(from)) {
+            return new ArrayList<>();
+        }
+        return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
+    }
+
+    public static <T, U, R> List<R> convertListByFlatMap(Collection<T> from,
+                                                         Function<? super T, ? extends U> mapper,
+                                                         Function<U, ? extends Stream<? extends R>> func) {
+        if (CollUtil.isEmpty(from)) {
+            return new ArrayList<>();
+        }
+        return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
+    }
+
     public static <K, V> List<V> mergeValuesFromMap(Map<K, List<V>> map) {
         return map.values()
                 .stream()
@@ -101,6 +118,23 @@ public class CollectionUtils {
         return from.stream().filter(filter).collect(Collectors.toMap(keyFunc, v -> v));
     }
 
+    public static <T, U> Set<U> convertSetByFlatMap(Collection<T> from,
+                                                    Function<T, ? extends Stream<? extends U>> func) {
+        if (CollUtil.isEmpty(from)) {
+            return new HashSet<>();
+        }
+        return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
+    }
+
+    public static <T, U, R> Set<R> convertSetByFlatMap(Collection<T> from,
+                                                       Function<? super T, ? extends U> mapper,
+                                                       Function<U, ? extends Stream<? extends R>> func) {
+        if (CollUtil.isEmpty(from)) {
+            return new HashSet<>();
+        }
+        return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
+    }
+
     public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc) {
         if (CollUtil.isEmpty(from)) {
             return new HashMap<>();
@@ -272,38 +306,4 @@ public class CollectionUtils {
         return deptId == null ? Collections.emptyList() : Collections.singleton(deptId);
     }
 
-    public static <T, U> List<U> convertListByFlatMap(Collection<T> from,
-                                                      Function<T, ? extends Stream<? extends U>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
-    }
-
-    public static <T, U, R> List<R> convertListByFlatMap(Collection<T> from,
-                                                         Function<? super T, ? extends U> mapper,
-                                                         Function<U, ? extends Stream<? extends R>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
-    }
-
-    public static <T, U> Set<U> convertSetByFlatMap(Collection<T> from,
-                                                    Function<T, ? extends Stream<? extends U>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashSet<>();
-        }
-        return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
-    }
-
-    public static <T, U, R> Set<R> convertSetByFlatMap(Collection<T> from,
-                                                       Function<? super T, ? extends U> mapper,
-                                                       Function<U, ? extends Stream<? extends R>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashSet<>();
-        }
-        return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
-    }
-
 }

+ 1 - 1
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java

@@ -25,7 +25,7 @@ import java.util.Map;
 public class SpringExpressionUtils {
 
     /**
-     * spel表达式解析器
+     * Spring EL 表达式解析器
      */
     private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
     /**

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

@@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.Parameters;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import org.mapstruct.ap.internal.util.Collections;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -25,14 +26,13 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.IOException;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
+import java.util.stream.Stream;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
@@ -84,19 +84,14 @@ public class CrmCustomerController {
         if (customer == null) {
             return success(null);
         }
-
         // 2. 拼接数据
-        // 2.1 获取负责人详情
-        Set<Long> userIds = new HashSet<>();
-        userIds.add(customer.getOwnerUserId()); // 负责人
-        userIds.add(Long.parseLong(customer.getCreator())); // 加入创建者
-        List<AdminUserRespDTO> userList = adminUserApi.getUserList(userIds);
-        Map<Long, AdminUserRespDTO> userMap = convertMap(userList, AdminUserRespDTO::getId);
-        // 2.2 获取部门详情
-        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
+                Collections.asSet(Long.valueOf(customer.getCreator()), customer.getOwnerUserId()));
+        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
         return success(CrmCustomerConvert.INSTANCE.convert(customer, userMap, deptMap));
     }
 
+    // TODO @puhui999:合并到 receiveCustomer
     @PutMapping("/receive")
     @Operation(summary = "领取客户公海数据")
     @Parameter(name = "id", description = "客户编号", required = true, example = "1024")
@@ -106,30 +101,20 @@ public class CrmCustomerController {
         return success(true);
     }
 
-    @PutMapping("/put-pool")
-    @Operation(summary = "数据放入公海")
-    @Parameter(name = "id", description = "客户编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('crm:customer:update')")
-    public CommonResult<Boolean> putPool(@RequestParam("id") Long id) {
-        customerService.putPool(id);
-        return success(true);
-    }
-
     @GetMapping("/page")
     @Operation(summary = "获得客户分页")
     @PreAuthorize("@ss.hasPermission('crm:customer:query')")
     public CommonResult<PageResult<CrmCustomerRespVO>> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) {
+        // 1. 查询客户分页
         PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(pageVO, getLoginUserId());
         if (CollUtil.isEmpty(pageResult.getList())) {
             return success(PageResult.empty(pageResult.getTotal()));
         }
-        // 1.1 获取负责人详情
-        Set<Long> userIds = convertSet(pageResult.getList(), CrmCustomerDO::getOwnerUserId);
-        userIds.addAll(convertSet(pageResult.getList(), item -> Long.parseLong(item.getCreator()))); // 加入创建者
-        List<AdminUserRespDTO> userList = adminUserApi.getUserList(userIds);
-        Map<Long, AdminUserRespDTO> userMap = convertMap(userList, AdminUserRespDTO::getId);
-        // 1.2 获取部门详情
-        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
+
+        // 2. 拼接数据
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
+                convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId())));
+        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
         return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap));
     }
 
@@ -162,6 +147,17 @@ public class CrmCustomerController {
         return success(true);
     }
 
+    // ==================== 公海相关操作 ====================
+
+    @PutMapping("/put-pool")
+    @Operation(summary = "数据放入公海")
+    @Parameter(name = "id", description = "客户编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('crm:customer:update')")
+    public CommonResult<Boolean> putCustomerPool(@RequestParam("id") Long id) {
+        customerService.putCustomerPool(id);
+        return success(true);
+    }
+
     @PutMapping("/receive")
     @Operation(summary = "领取公海客户")
     @Parameter(name = "ids", description = "编号数组", required = true,example = "1,2,3")
@@ -174,12 +170,12 @@ public class CrmCustomerController {
     @PutMapping("/distribute")
     @Operation(summary = "分配公海给对应负责人")
     @Parameters({
-            @Parameter(name = "ownerUserId", description = "分配的负责人编号", required = true, example = "12345"),
-            @Parameter(name = "ids", description = "客户编号数组", required = true, example = "1,2,3")
+            @Parameter(name = "ids", description = "客户编号数组", required = true, example = "1,2,3"),
+            @Parameter(name = "ownerUserId", description = "分配的负责人编号", required = true, example = "12345")
     })
     @PreAuthorize("@ss.hasPermission('crm:customer:distribute')")
-    public CommonResult<Boolean> distributeCustomer(@RequestParam(value = "ownerUserId") Long ownerUserId,
-                                                    @RequestParam(value = "ids") List<Long> ids){
+    public CommonResult<Boolean> distributeCustomer(@RequestParam(value = "ids") List<Long> ids,
+                                                    @RequestParam(value = "ownerUserId") Long ownerUserId){
         customerService.distributeCustomer(ids, ownerUserId);
         return success(true);
     }

+ 10 - 5
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java

@@ -71,29 +71,32 @@ public class CrmPermissionController {
         return success(true);
     }
 
+    // TODO @puhui999:这个要不要放到 Service 实现,让 Controller 还轻一点;
     @DeleteMapping("/delete")
     @Operation(summary = "删除数据权限")
     @Parameter(name = "ids", description = "数据权限编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('crm:permission:delete')")
     public CommonResult<Boolean> deletePermission(@RequestParam("ids") Collection<Long> ids) {
-        List<CrmPermissionDO> permissions = permissionService.getPermissionListByIds(ids);
+        List<CrmPermissionDO> permissions = permissionService.getPermissionList(ids);
         if (CollUtil.isEmpty(permissions)) {
             throw exception(CRM_PERMISSION_NOT_EXISTS);
         }
         Set<Long> bizIds = convertSet(permissions, CrmPermissionDO::getBizId);
-        if (bizIds.size() > 1) { // 情况一:数据权限的模块数据编号是一致的不可能存在两个
+        if (bizIds.size() > 1) { // 情况一:数据权限的模块数据编号是一致的不可能存在两个 TODO @puhui999:这里可以额外说明下原因,就是批量删除权限的时候,只能属于同一个 bizId 下;
             throw exception(CRM_PERMISSION_DELETE_FAIL);
         }
+        // TODO @puhui999:下面 2 个,可以忽略。简单点哈;
         if (permissions.size() != ids.size()) { // 情况二:期望数量和实际结果不一致
             throw exception(CRM_PERMISSION_NOT_EXISTS);
         }
         // 情况三:不能包含负责人
+        // TODO @puhui999:isOwner 可以直接放到判断里,不用单独取个变量名
         boolean isOwner = CollectionUtils.anyMatch(permissions, item -> ObjUtil.equal(item.getLevel(), CrmPermissionLevelEnum.OWNER.getLevel()));
         if (isOwner) {
             throw exception(CRM_PERMISSION_DELETE_FAIL_EXIST_OWNER);
         }
         // 校验操作人是否为负责人
-        CrmPermissionDO permission = permissionService.getPermissionByIdAndUserId(permissions.get(0).getBizId(), getLoginUserId());
+        CrmPermissionDO permission = permissionService.getPermission(permissions.get(0).getBizId(), getLoginUserId());
         if (!CrmPermissionLevelEnum.isOwner(permission.getLevel())) {
             throw exception(CRM_PERMISSION_DELETE_DENIED);
         }
@@ -102,13 +105,15 @@ public class CrmPermissionController {
         return success(true);
     }
 
+    // TODO @puhui999:这个要不要放到 Service 实现,让 Controller 还轻一点;
+    // TODO @puhui999:delete-self 就可以啦。方法名叫 deleteSelfPermission
     @DeleteMapping("/deleteSelfPermission")
     @Operation(summary = "删除自己的数据权限")
     @Parameter(name = "id", description = "数据权限编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('crm:permission:delete')")
     public CommonResult<Boolean> deletePermission(@RequestParam("id") Long id) {
         // 校验数据存在且是自己
-        CrmPermissionDO permission = permissionService.getPermissionByIdAndUserId(id, getLoginUserId());
+        CrmPermissionDO permission = permissionService.getPermission(id, getLoginUserId());
         if (permission == null) {
             throw exception(CRM_PERMISSION_NOT_EXISTS);
         }
@@ -131,7 +136,7 @@ public class CrmPermissionController {
     @PreAuthorize("@ss.hasPermission('crm:permission:query')")
     public CommonResult<List<CrmPermissionRespVO>> getPermissionList(@RequestParam("bizType") Integer bizType,
                                                                      @RequestParam("bizId") Long bizId) {
-        List<CrmPermissionDO> permission = permissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
+        List<CrmPermissionDO> permission = permissionService.getPermissionListByBiz(bizType, bizId);
         if (CollUtil.isEmpty(permission)) {
             return success(Collections.emptyList());
         }

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

@@ -37,21 +37,17 @@ public interface CrmCustomerConvert {
     /**
      * 设置用户信息
      *
-     * @param respVO  CRM 客户 Response VO
+     * @param customer  CRM 客户 Response VO
      * @param userMap 用户信息 map
      * @param deptMap 用户部门信息 map
      */
-    static void setUserInfo(CrmCustomerRespVO respVO, Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
-        respVO.setAreaName(AreaUtils.format(respVO.getAreaId()));
-        findAndThen(userMap, respVO.getOwnerUserId(), user -> {
-            respVO.setOwnerUserName(user.getNickname());
-            findAndThen(deptMap, user.getDeptId(), dept -> {
-                respVO.setOwnerUserDeptName(dept.getName());
-            });
-        });
-        findAndThen(userMap, Long.parseLong(respVO.getCreator()), user -> {
-            respVO.setCreatorName(user.getNickname());
+    static void setUserInfo(CrmCustomerRespVO customer, Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
+        customer.setAreaName(AreaUtils.format(customer.getAreaId()));
+        findAndThen(userMap, customer.getOwnerUserId(), user -> {
+            customer.setOwnerUserName(user.getNickname());
+            findAndThen(deptMap, user.getDeptId(), dept -> customer.setOwnerUserDeptName(dept.getName()));
         });
+        findAndThen(userMap, Long.parseLong(customer.getCreator()), user -> customer.setCreatorName(user.getNickname()));
     }
 
     List<CrmCustomerExcelVO> convertList02(List<CrmCustomerDO> list);

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

@@ -24,7 +24,7 @@ import lombok.*;
 public class CrmPermissionDO extends BaseDO {
 
     /**
-     * ID
+     * 编号,主键自增
      */
     @TableId
     private Long id;

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

@@ -14,9 +14,6 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.apache.ibatis.annotations.Mapper;
 
-import java.util.Collection;
-import java.util.List;
-
 /**
  * 客户 Mapper
  *
@@ -40,6 +37,7 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
                 .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource()));
     }
 
+    // TODO @puhui999:这个方法还要哇?
     default PageResult<CrmCustomerDO> selectPage1(CrmCustomerPageReqVO pageReqVO, Long userId) {
         LambdaQueryWrapperX<CrmCustomerDO> queryWrapperX = new LambdaQueryWrapperX<>();
         //queryWrapperX.sql
@@ -94,7 +92,7 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
          */
         if (pageReqVO.getPool()) { // 情况一:公海
             mpjLambdaWrapperX.isNull(CrmCustomerDO::getOwnerUserId);
-        } else {// 情况一:不是公海
+        } else { // 情况二:不是公海
             mpjLambdaWrapperX.isNotNull(CrmCustomerDO::getOwnerUserId);
         }
         // TODO 场景数据过滤
@@ -117,9 +115,4 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
                 .isNull(CrmCustomerDO::getOwnerUserId));
     }
 
-    default List<CrmCustomerDO> selectList(Collection<Long> ids) {
-        return selectList(new LambdaQueryWrapperX<CrmCustomerDO>()
-                .inIfPresent(CrmCustomerDO::getId, ids));
-    }
-
 }

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

@@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
 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.CrmBizTypeEnum;
 import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import lombok.extern.slf4j.Slf4j;
@@ -38,24 +39,6 @@ public class CrmPermissionAspect {
     @Resource
     private CrmPermissionService crmPermissionService;
 
-    /**
-     * 获得用户编号
-     *
-     * @return 用户编号
-     */
-    private static Long getUserId() {
-        return WebFrameworkUtils.getLoginUserId();
-    }
-
-    private static Map<String, Object> getSpelValue(JoinPoint joinPoint, CrmPermission crmPermission) {
-        List<String> spelList = new ArrayList<>(); // 表达式列表
-        spelList.add(crmPermission.bizId());
-        if (StrUtil.isNotEmpty(crmPermission.bizTypeValue())) { // 为空则表示 bizType 有值
-            spelList.add(crmPermission.bizTypeValue());
-        }
-        return SpringExpressionUtils.parseExpressions(joinPoint, spelList);
-    }
-
     @Before("@annotation(crmPermission)")
     public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) {
         // TODO 芋艿:临时,方便大家调试
@@ -63,10 +46,10 @@ public class CrmPermissionAspect {
         //    return;
         //}
         // 获取相关属性值
-        Map<String, Object> spelValue = getSpelValue(joinPoint, crmPermission);
+        Map<String, Object> expressionValues = parseExpressions(joinPoint, crmPermission);
         Integer bizType = StrUtil.isEmpty(crmPermission.bizTypeValue()) ?
-                crmPermission.bizType()[0].getType() : (Integer) spelValue.get(crmPermission.bizTypeValue()); // 模块类型
-        Long bizId = (Long) spelValue.get(crmPermission.bizId()); // 模块数据编号
+                crmPermission.bizType()[0].getType() : (Integer) expressionValues.get(crmPermission.bizTypeValue()); // 模块类型
+        Long bizId = (Long) expressionValues.get(crmPermission.bizId()); // 模块数据编号
         Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别
 
         // TODO 如果是超级管理员则直接通过
@@ -75,35 +58,55 @@ public class CrmPermissionAspect {
         //}
 
         // 1. 获取数据权限
-        List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
+        List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionListByBiz(bizType, bizId);
         if (CollUtil.isEmpty(bizPermissions)) { // 数据权限不存存那么数据也不存在
-            throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, crmPermission.bizType()[0].getName());
+            throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, CrmBizTypeEnum.getNameByType(bizType));
         }
         // 2.1 情况一:如果自己是负责人,则默认有所有权限
-        CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, item -> ObjUtil.equal(item.getUserId(), getUserId()));
-        if (CrmPermissionLevelEnum.isOwner(userPermission.getLevel())) {
-            return;
-        }
-        // 2.2 情况二:校验自己是否有读权限
-        if (CrmPermissionLevelEnum.isRead(permissionLevel)) {
-            if (CrmPermissionLevelEnum.isRead(userPermission.getLevel())) { // 校验当前用户是否有读权限
+        CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, permission -> ObjUtil.equal(permission.getUserId(), getUserId()));
+        if (userPermission != null) {
+            if (CrmPermissionLevelEnum.isOwner(userPermission.getLevel())) {
                 return;
             }
-            // 如果查询数据的话拥有写权限的也能查询
-            if (CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限
-                return;
+            // 2.2 情况二:校验自己是否有读权限
+            if (CrmPermissionLevelEnum.isRead(permissionLevel)) {
+                if (CrmPermissionLevelEnum.isRead(userPermission.getLevel()) // 校验当前用户是否有读权限
+                        || CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限
+                    return;
+                }
             }
-        }
-        // 2.3 情况三:校验自己是否有写权限
-        if (CrmPermissionLevelEnum.isWrite(permissionLevel)) {
-            if (CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限
-                return;
+            // 2.3 情况三:校验自己是否有写权限
+            if (CrmPermissionLevelEnum.isWrite(permissionLevel)) {
+                if (CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限
+                    return;
+                }
             }
         }
+        // 2.4 没有权限!
+        // 打个 info 日志,方便后续排查问题、审计
+        log.info("[doBefore][userId({}) 要求权限({}) 实际权限({}) 数据校验错误]",
+                getUserId(), permissionLevel, toJsonString(userPermission));
+        throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.getNameByType(bizType));
+    }
+
+    /**
+     * 获得用户编号
+     *
+     * @return 用户编号
+     */
+    private static Long getUserId() {
+        return WebFrameworkUtils.getLoginUserId();
+    }
 
-        // 打个 info 日志,方便后续排查问题、审计;
-        log.info("[doBefore][crmPermission({}) 数据校验错误]", toJsonString(userPermission));
-        throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType()[0].getName());
+    private static Map<String, Object> parseExpressions(JoinPoint joinPoint, CrmPermission crmPermission) {
+        // 1. 需要解析的表达式
+        List<String> expressionStrings = new ArrayList<>(2);
+        expressionStrings.add(crmPermission.bizId());
+        if (StrUtil.isNotEmpty(crmPermission.bizTypeValue())) { // 为空则表示 bizType 有值
+            expressionStrings.add(crmPermission.bizTypeValue());
+        }
+        // 2. 执行解析
+        return SpringExpressionUtils.parseExpressions(joinPoint, expressionStrings);
     }
 
 }

+ 2 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmBizTypeEnum.java

@@ -9,7 +9,7 @@ import lombok.RequiredArgsConstructor;
 import java.util.Arrays;
 
 /**
- * Crm 类型枚举
+ * CRM 类型枚举
  *
  * @author HUIHUI
  */
@@ -24,6 +24,7 @@ public enum CrmBizTypeEnum implements IntArrayValuable {
     CRM_CONTRACT(5, "合同");
 
     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizTypeEnum::getType).toArray();
+
     /**
      * 类型
      */

+ 18 - 15
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java

@@ -46,6 +46,15 @@ public interface CrmCustomerService {
      */
     CrmCustomerDO getCustomer(Long id);
 
+    /**
+     * 获得客户列表
+     *
+     * @param ids 客户编号数组
+     * @author ljlleo
+     * @return 客户列表
+     */
+    List<CrmCustomerDO> getCustomerList(Collection<Long> ids);
+
     /**
      * 获得客户分页
      *
@@ -86,6 +95,15 @@ public interface CrmCustomerService {
      */
     void lockCustomer(@Valid CrmCustomerUpdateReqVO updateReqVO);
 
+    // ==================== 公海相关操作 ====================
+
+    /**
+     * 客户放入公海
+     *
+     * @param id 客户编号
+     */
+    void putCustomerPool(Long id);
+
     /**
      * 领取公海客户
      *
@@ -110,19 +128,4 @@ public interface CrmCustomerService {
      */
     void receive(Long id, Long userId);
 
-    /**
-     * 客户放入公海
-     *
-     * @param id 客户编号
-     */
-    void putPool(Long id);
-
-    /**
-     * 根据客户ID集合查询客户集合
-     * @param ids
-     * @author ljlleo
-     * @return
-     */
-    List<CrmCustomerDO> getCustomerList(Collection<Long> ids);
-
 }

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

@@ -15,6 +15,7 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
@@ -33,6 +34,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
 
     @Resource
     private CrmCustomerMapper customerMapper;
+
     @Resource
     private CrmPermissionService crmPermissionService;
 
@@ -46,8 +48,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
         // 创建数据权限
         crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
                 .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
-
-        // 返回
         return customer.getId();
     }
 
@@ -86,6 +86,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
         return customerMapper.selectById(id);
     }
 
+    @Override
+    public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) {
+        return customerMapper.selectBatchIds(ids);
+    }
+
     @Override
     public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId) {
         // 1.1. TODO 如果是超级管理员
@@ -204,6 +209,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
         }
     }
 
+    // TODO @puhui999:合并到 receiveCustomer 里
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void receive(Long id, Long userId) {
@@ -227,31 +233,28 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
-    public void putPool(Long id) {
+    public void putCustomerPool(Long id) {
         // 1. 校验存在
         CrmCustomerDO customer = customerMapper.selectById(id);
         if (customer == null) {
             throw exception(CUSTOMER_NOT_EXISTS);
         }
+        // TODO puhui999:校验合并到 validateCustomerOwnerExists、validateCustomerIsLocked
         // 1.2. 校验是否为公海数据
         if (customer.getOwnerUserId() == null) {
             throw exception(CUSTOMER_IN_POOL);
         }
-        // 1.3. 校验客户是否锁定
+        // 1.3. 校验客户是否锁定
         if (customer.getLockStatus()) {
             throw exception(CUSTOMER_LOCKED_PUT_POOL_FAIL);
         }
 
-        // 2. 公海数据-设置负责人 NULL
+        // 2. 设置负责人为 NULL
+        // TODO @puhui999:updateById 这么操作,是无法设置 null 的;
         customerMapper.updateById(new CrmCustomerDO().setId(customer.getId()).setOwnerUserId(null));
         // 3. 删除负责人数据权限
         crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(),
                 CrmPermissionLevelEnum.OWNER.getLevel());
     }
 
-    @Override
-    public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) {
-        return customerMapper.selectList(ids);
-    }
-
 }

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

@@ -64,7 +64,7 @@ public interface CrmPermissionService {
      * @param userId 用户编号
      * @return 数据权限
      */
-    CrmPermissionDO getPermissionByIdAndUserId(Long id, Long userId);
+    CrmPermissionDO getPermission(Long id, Long userId);
 
     /**
      * 获取数据权限列表,通过 数据类型 x 某个数据
@@ -73,7 +73,7 @@ public interface CrmPermissionService {
      * @param bizId   数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
      * @return Crm 数据权限列表
      */
-    List<CrmPermissionDO> getPermissionByBizTypeAndBizId(Integer bizType, Long bizId);
+    List<CrmPermissionDO> getPermissionListByBiz(Integer bizType, Long bizId);
 
     /**
      * 获得数据权限列表
@@ -81,7 +81,7 @@ public interface CrmPermissionService {
      * @param ids 数据权限编号列表
      * @return 数据权限列表
      */
-    List<CrmPermissionDO> getPermissionListByIds(Collection<Long> ids);
+    List<CrmPermissionDO> getPermissionList(Collection<Long> ids);
 
     /**
      * 获取用户参与的模块数据列表

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

@@ -55,27 +55,34 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void updatePermission(CrmPermissionUpdateReqVO updateReqVO) {
-        // 校验存在
+        // 1. 校验存在
         validateCrmPermissionExists(updateReqVO.getIds());
-
+        // 2. 更新
         List<CrmPermissionDO> updateDO = CrmPermissionConvert.INSTANCE.convertList(updateReqVO);
         crmPermissionMapper.updateBatch(updateDO);
     }
 
+    private void validateCrmPermissionExists(Collection<Long> ids) {
+        List<CrmPermissionDO> permissionList = crmPermissionMapper.selectBatchIds(ids);
+        if (ObjUtil.notEqual(permissionList.size(), ids.size())) {
+            throw exception(CRM_PERMISSION_NOT_EXISTS);
+        }
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void transferPermission(CrmPermissionTransferReqBO transferReqBO) {
-        // 1. 校验数据权限-是否是负责人,只有负责人才可以转移
-        CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId(transferReqBO.getBizType(),
-                transferReqBO.getBizId(), transferReqBO.getUserId());
-        String crmName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType());
+        // 1. 校验数据权限是否是负责人,只有负责人才可以转移
+        CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId(
+                transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId());
+        String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType());
         // TODO 校验是否为超级管理员 || 1
         if (oldPermission == null || !isOwner(oldPermission.getLevel())) {
-            throw exception(CRM_PERMISSION_DENIED, crmName);
+            throw exception(CRM_PERMISSION_DENIED, bizTypeName);
         }
         // 1.1 校验转移对象是否已经是该负责人
         if (ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) {
-            throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, crmName);
+            throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, bizTypeName);
         }
         // 1.2 校验新负责人是否存在
         adminUserApi.validateUserList(Collections.singletonList(transferReqBO.getNewOwnerUserId()));
@@ -84,23 +91,23 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
         List<CrmPermissionDO> permissions = crmPermissionMapper.selectByBizTypeAndBizId(
                 transferReqBO.getBizType(), transferReqBO.getBizId()); // 获得所有数据权限
         CrmPermissionDO permission = CollUtil.findOne(permissions,
-                item -> ObjUtil.equal(item.getUserId(), transferReqBO.getNewOwnerUserId())); // 校验新负责人是否存在于数据权限列表
-        if (permission == null) { // 不存在则以负责人的级别加入
+                item -> ObjUtil.equal(item.getUserId(), transferReqBO.getNewOwnerUserId()));
+        if (permission == null) {
             crmPermissionMapper.insert(new CrmPermissionDO().setBizType(transferReqBO.getBizType())
                     .setBizId(transferReqBO.getBizId()).setUserId(transferReqBO.getNewOwnerUserId())
                     .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
-        } else { // 存在则修改权限级别
+        } else {
             crmPermissionMapper.updateById(new CrmPermissionDO().setId(permission.getId())
                     .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
         }
 
         // 3. 修改老负责人的权限
-        if (transferReqBO.getOldOwnerPermissionLevel() != null) { // 加入数据权限列表
+        if (transferReqBO.getOldOwnerPermissionLevel() != null) {
             crmPermissionMapper.updateById(new CrmPermissionDO().setId(oldPermission.getId())
-                    .setLevel(transferReqBO.getOldOwnerPermissionLevel())); // 设置权限级别
-            return;
+                    .setLevel(transferReqBO.getOldOwnerPermissionLevel()));
+        } else {
+            crmPermissionMapper.deleteById(oldPermission.getId());
         }
-        crmPermissionMapper.deleteById(oldPermission.getId());
     }
 
     @Override
@@ -116,7 +123,8 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deletePermission(Integer bizType, Long bizId, Integer level) {
-        List<CrmPermissionDO> permissions = crmPermissionMapper.selectListByBizTypeAndBizIdAndLevel(bizType, bizId, level);
+        List<CrmPermissionDO> permissions = crmPermissionMapper.selectListByBizTypeAndBizIdAndLevel(
+                bizType, bizId, level);
         // 校验存在
         if (CollUtil.isEmpty(permissions)) {
             throw exception(CRM_PERMISSION_NOT_EXISTS);
@@ -127,31 +135,23 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
     }
 
     @Override
-    public CrmPermissionDO getPermissionByIdAndUserId(Long id, Long userId) {
+    public CrmPermissionDO getPermission(Long id, Long userId) {
         return crmPermissionMapper.selectByIdAndUserId(id, userId);
     }
 
     @Override
-    public List<CrmPermissionDO> getPermissionByBizTypeAndBizId(Integer bizType, Long bizId) {
+    public List<CrmPermissionDO> getPermissionListByBiz(Integer bizType, Long bizId) {
         return crmPermissionMapper.selectByBizTypeAndBizId(bizType, bizId);
     }
 
     @Override
-    public List<CrmPermissionDO> getPermissionListByIds(Collection<Long> ids) {
+    public List<CrmPermissionDO> getPermissionList(Collection<Long> ids) {
         if (CollUtil.isEmpty(ids)) {
             return Collections.emptyList();
         }
         return crmPermissionMapper.selectBatchIds(ids);
     }
 
-    private void validateCrmPermissionExists(Collection<Long> ids) {
-        List<CrmPermissionDO> permissionList = crmPermissionMapper.selectBatchIds(ids);
-        // 校验存在
-        if (ObjUtil.notEqual(permissionList.size(), ids.size())) {
-            throw exception(CRM_PERMISSION_NOT_EXISTS);
-        }
-    }
-
     @Override
     public List<CrmPermissionDO> getPermissionListByBizTypeAndUserId(Integer bizType, Long userId) {
         return crmPermissionMapper.selectListByBizTypeAndUserId(bizType, userId);

+ 1 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.util;
 import cn.hutool.core.util.StrUtil;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 
+// TODO @puhui999:这个类还要哇?
 /**
  * 数据权限工具类
  *