Commit 899e40deb9baa950d83aeb823374a75af734a3e6

Authored by YunaiV
1 parent d1579499

crm:code review 数据权限的实现

Showing 14 changed files with 191 additions and 190 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
... ... @@ -73,6 +73,23 @@ public class CollectionUtils {
73 73 return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toList());
74 74 }
75 75  
  76 + public static <T, U> List<U> convertListByFlatMap(Collection<T> from,
  77 + Function<T, ? extends Stream<? extends U>> func) {
  78 + if (CollUtil.isEmpty(from)) {
  79 + return new ArrayList<>();
  80 + }
  81 + return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
  82 + }
  83 +
  84 + public static <T, U, R> List<R> convertListByFlatMap(Collection<T> from,
  85 + Function<? super T, ? extends U> mapper,
  86 + Function<U, ? extends Stream<? extends R>> func) {
  87 + if (CollUtil.isEmpty(from)) {
  88 + return new ArrayList<>();
  89 + }
  90 + return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
  91 + }
  92 +
76 93 public static <K, V> List<V> mergeValuesFromMap(Map<K, List<V>> map) {
77 94 return map.values()
78 95 .stream()
... ... @@ -101,6 +118,23 @@ public class CollectionUtils {
101 118 return from.stream().filter(filter).collect(Collectors.toMap(keyFunc, v -> v));
102 119 }
103 120  
  121 + public static <T, U> Set<U> convertSetByFlatMap(Collection<T> from,
  122 + Function<T, ? extends Stream<? extends U>> func) {
  123 + if (CollUtil.isEmpty(from)) {
  124 + return new HashSet<>();
  125 + }
  126 + return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
  127 + }
  128 +
  129 + public static <T, U, R> Set<R> convertSetByFlatMap(Collection<T> from,
  130 + Function<? super T, ? extends U> mapper,
  131 + Function<U, ? extends Stream<? extends R>> func) {
  132 + if (CollUtil.isEmpty(from)) {
  133 + return new HashSet<>();
  134 + }
  135 + return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
  136 + }
  137 +
104 138 public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc) {
105 139 if (CollUtil.isEmpty(from)) {
106 140 return new HashMap<>();
... ... @@ -272,38 +306,4 @@ public class CollectionUtils {
272 306 return deptId == null ? Collections.emptyList() : Collections.singleton(deptId);
273 307 }
274 308  
275   - public static <T, U> List<U> convertListByFlatMap(Collection<T> from,
276   - Function<T, ? extends Stream<? extends U>> func) {
277   - if (CollUtil.isEmpty(from)) {
278   - return new ArrayList<>();
279   - }
280   - return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
281   - }
282   -
283   - public static <T, U, R> List<R> convertListByFlatMap(Collection<T> from,
284   - Function<? super T, ? extends U> mapper,
285   - Function<U, ? extends Stream<? extends R>> func) {
286   - if (CollUtil.isEmpty(from)) {
287   - return new ArrayList<>();
288   - }
289   - return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
290   - }
291   -
292   - public static <T, U> Set<U> convertSetByFlatMap(Collection<T> from,
293   - Function<T, ? extends Stream<? extends U>> func) {
294   - if (CollUtil.isEmpty(from)) {
295   - return new HashSet<>();
296   - }
297   - return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
298   - }
299   -
300   - public static <T, U, R> Set<R> convertSetByFlatMap(Collection<T> from,
301   - Function<? super T, ? extends U> mapper,
302   - Function<U, ? extends Stream<? extends R>> func) {
303   - if (CollUtil.isEmpty(from)) {
304   - return new HashSet<>();
305   - }
306   - return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
307   - }
308   -
309 309 }
... ...
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java
... ... @@ -25,7 +25,7 @@ import java.util.Map;
25 25 public class SpringExpressionUtils {
26 26  
27 27 /**
28   - * spel表达式解析器
  28 + * Spring EL 表达式解析器
29 29 */
30 30 private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
31 31 /**
... ...
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;
17 17 import io.swagger.v3.oas.annotations.Parameter;
18 18 import io.swagger.v3.oas.annotations.Parameters;
19 19 import io.swagger.v3.oas.annotations.tags.Tag;
  20 +import org.mapstruct.ap.internal.util.Collections;
20 21 import org.springframework.security.access.prepost.PreAuthorize;
21 22 import org.springframework.validation.annotation.Validated;
22 23 import org.springframework.web.bind.annotation.*;
... ... @@ -25,14 +26,13 @@ import javax.annotation.Resource;
25 26 import javax.servlet.http.HttpServletResponse;
26 27 import javax.validation.Valid;
27 28 import java.io.IOException;
28   -import java.util.HashSet;
29 29 import java.util.List;
30 30 import java.util.Map;
31   -import java.util.Set;
  31 +import java.util.stream.Stream;
32 32  
33 33 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
34   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
35 34 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  35 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
36 36 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
37 37 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
38 38  
... ... @@ -84,19 +84,14 @@ public class CrmCustomerController {
84 84 if (customer == null) {
85 85 return success(null);
86 86 }
87   -
88 87 // 2. 拼接数据
89   - // 2.1 获取负责人详情
90   - Set<Long> userIds = new HashSet<>();
91   - userIds.add(customer.getOwnerUserId()); // 负责人
92   - userIds.add(Long.parseLong(customer.getCreator())); // 加入创建者
93   - List<AdminUserRespDTO> userList = adminUserApi.getUserList(userIds);
94   - Map<Long, AdminUserRespDTO> userMap = convertMap(userList, AdminUserRespDTO::getId);
95   - // 2.2 获取部门详情
96   - Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
  88 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
  89 + Collections.asSet(Long.valueOf(customer.getCreator()), customer.getOwnerUserId()));
  90 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
97 91 return success(CrmCustomerConvert.INSTANCE.convert(customer, userMap, deptMap));
98 92 }
99 93  
  94 + // TODO @puhui999:合并到 receiveCustomer
100 95 @PutMapping("/receive")
101 96 @Operation(summary = "领取客户公海数据")
102 97 @Parameter(name = "id", description = "客户编号", required = true, example = "1024")
... ... @@ -106,30 +101,20 @@ public class CrmCustomerController {
106 101 return success(true);
107 102 }
108 103  
109   - @PutMapping("/put-pool")
110   - @Operation(summary = "数据放入公海")
111   - @Parameter(name = "id", description = "客户编号", required = true, example = "1024")
112   - @PreAuthorize("@ss.hasPermission('crm:customer:update')")
113   - public CommonResult<Boolean> putPool(@RequestParam("id") Long id) {
114   - customerService.putPool(id);
115   - return success(true);
116   - }
117   -
118 104 @GetMapping("/page")
119 105 @Operation(summary = "获得客户分页")
120 106 @PreAuthorize("@ss.hasPermission('crm:customer:query')")
121 107 public CommonResult<PageResult<CrmCustomerRespVO>> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) {
  108 + // 1. 查询客户分页
122 109 PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(pageVO, getLoginUserId());
123 110 if (CollUtil.isEmpty(pageResult.getList())) {
124 111 return success(PageResult.empty(pageResult.getTotal()));
125 112 }
126   - // 1.1 获取负责人详情
127   - Set<Long> userIds = convertSet(pageResult.getList(), CrmCustomerDO::getOwnerUserId);
128   - userIds.addAll(convertSet(pageResult.getList(), item -> Long.parseLong(item.getCreator()))); // 加入创建者
129   - List<AdminUserRespDTO> userList = adminUserApi.getUserList(userIds);
130   - Map<Long, AdminUserRespDTO> userMap = convertMap(userList, AdminUserRespDTO::getId);
131   - // 1.2 获取部门详情
132   - Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
  113 +
  114 + // 2. 拼接数据
  115 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
  116 + convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId())));
  117 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
133 118 return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap));
134 119 }
135 120  
... ... @@ -162,6 +147,17 @@ public class CrmCustomerController {
162 147 return success(true);
163 148 }
164 149  
  150 + // ==================== 公海相关操作 ====================
  151 +
  152 + @PutMapping("/put-pool")
  153 + @Operation(summary = "数据放入公海")
  154 + @Parameter(name = "id", description = "客户编号", required = true, example = "1024")
  155 + @PreAuthorize("@ss.hasPermission('crm:customer:update')")
  156 + public CommonResult<Boolean> putCustomerPool(@RequestParam("id") Long id) {
  157 + customerService.putCustomerPool(id);
  158 + return success(true);
  159 + }
  160 +
165 161 @PutMapping("/receive")
166 162 @Operation(summary = "领取公海客户")
167 163 @Parameter(name = "ids", description = "编号数组", required = true,example = "1,2,3")
... ... @@ -174,12 +170,12 @@ public class CrmCustomerController {
174 170 @PutMapping("/distribute")
175 171 @Operation(summary = "分配公海给对应负责人")
176 172 @Parameters({
177   - @Parameter(name = "ownerUserId", description = "分配的负责人编号", required = true, example = "12345"),
178   - @Parameter(name = "ids", description = "客户编号数组", required = true, example = "1,2,3")
  173 + @Parameter(name = "ids", description = "客户编号数组", required = true, example = "1,2,3"),
  174 + @Parameter(name = "ownerUserId", description = "分配的负责人编号", required = true, example = "12345")
179 175 })
180 176 @PreAuthorize("@ss.hasPermission('crm:customer:distribute')")
181   - public CommonResult<Boolean> distributeCustomer(@RequestParam(value = "ownerUserId") Long ownerUserId,
182   - @RequestParam(value = "ids") List<Long> ids){
  177 + public CommonResult<Boolean> distributeCustomer(@RequestParam(value = "ids") List<Long> ids,
  178 + @RequestParam(value = "ownerUserId") Long ownerUserId){
183 179 customerService.distributeCustomer(ids, ownerUserId);
184 180 return success(true);
185 181 }
... ...
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 {
71 71 return success(true);
72 72 }
73 73  
  74 + // TODO @puhui999:这个要不要放到 Service 实现,让 Controller 还轻一点;
74 75 @DeleteMapping("/delete")
75 76 @Operation(summary = "删除数据权限")
76 77 @Parameter(name = "ids", description = "数据权限编号", required = true, example = "1024")
77 78 @PreAuthorize("@ss.hasPermission('crm:permission:delete')")
78 79 public CommonResult<Boolean> deletePermission(@RequestParam("ids") Collection<Long> ids) {
79   - List<CrmPermissionDO> permissions = permissionService.getPermissionListByIds(ids);
  80 + List<CrmPermissionDO> permissions = permissionService.getPermissionList(ids);
80 81 if (CollUtil.isEmpty(permissions)) {
81 82 throw exception(CRM_PERMISSION_NOT_EXISTS);
82 83 }
83 84 Set<Long> bizIds = convertSet(permissions, CrmPermissionDO::getBizId);
84   - if (bizIds.size() > 1) { // 情况一:数据权限的模块数据编号是一致的不可能存在两个
  85 + if (bizIds.size() > 1) { // 情况一:数据权限的模块数据编号是一致的不可能存在两个 TODO @puhui999:这里可以额外说明下原因,就是批量删除权限的时候,只能属于同一个 bizId 下;
85 86 throw exception(CRM_PERMISSION_DELETE_FAIL);
86 87 }
  88 + // TODO @puhui999:下面 2 个,可以忽略。简单点哈;
87 89 if (permissions.size() != ids.size()) { // 情况二:期望数量和实际结果不一致
88 90 throw exception(CRM_PERMISSION_NOT_EXISTS);
89 91 }
90 92 // 情况三:不能包含负责人
  93 + // TODO @puhui999:isOwner 可以直接放到判断里,不用单独取个变量名
91 94 boolean isOwner = CollectionUtils.anyMatch(permissions, item -> ObjUtil.equal(item.getLevel(), CrmPermissionLevelEnum.OWNER.getLevel()));
92 95 if (isOwner) {
93 96 throw exception(CRM_PERMISSION_DELETE_FAIL_EXIST_OWNER);
94 97 }
95 98 // 校验操作人是否为负责人
96   - CrmPermissionDO permission = permissionService.getPermissionByIdAndUserId(permissions.get(0).getBizId(), getLoginUserId());
  99 + CrmPermissionDO permission = permissionService.getPermission(permissions.get(0).getBizId(), getLoginUserId());
97 100 if (!CrmPermissionLevelEnum.isOwner(permission.getLevel())) {
98 101 throw exception(CRM_PERMISSION_DELETE_DENIED);
99 102 }
... ... @@ -102,13 +105,15 @@ public class CrmPermissionController {
102 105 return success(true);
103 106 }
104 107  
  108 + // TODO @puhui999:这个要不要放到 Service 实现,让 Controller 还轻一点;
  109 + // TODO @puhui999:delete-self 就可以啦。方法名叫 deleteSelfPermission
105 110 @DeleteMapping("/deleteSelfPermission")
106 111 @Operation(summary = "删除自己的数据权限")
107 112 @Parameter(name = "id", description = "数据权限编号", required = true, example = "1024")
108 113 @PreAuthorize("@ss.hasPermission('crm:permission:delete')")
109 114 public CommonResult<Boolean> deletePermission(@RequestParam("id") Long id) {
110 115 // 校验数据存在且是自己
111   - CrmPermissionDO permission = permissionService.getPermissionByIdAndUserId(id, getLoginUserId());
  116 + CrmPermissionDO permission = permissionService.getPermission(id, getLoginUserId());
112 117 if (permission == null) {
113 118 throw exception(CRM_PERMISSION_NOT_EXISTS);
114 119 }
... ... @@ -131,7 +136,7 @@ public class CrmPermissionController {
131 136 @PreAuthorize("@ss.hasPermission('crm:permission:query')")
132 137 public CommonResult<List<CrmPermissionRespVO>> getPermissionList(@RequestParam("bizType") Integer bizType,
133 138 @RequestParam("bizId") Long bizId) {
134   - List<CrmPermissionDO> permission = permissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
  139 + List<CrmPermissionDO> permission = permissionService.getPermissionListByBiz(bizType, bizId);
135 140 if (CollUtil.isEmpty(permission)) {
136 141 return success(Collections.emptyList());
137 142 }
... ...
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 {
37 37 /**
38 38 * 设置用户信息
39 39 *
40   - * @param respVO CRM 客户 Response VO
  40 + * @param customer CRM 客户 Response VO
41 41 * @param userMap 用户信息 map
42 42 * @param deptMap 用户部门信息 map
43 43 */
44   - static void setUserInfo(CrmCustomerRespVO respVO, Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
45   - respVO.setAreaName(AreaUtils.format(respVO.getAreaId()));
46   - findAndThen(userMap, respVO.getOwnerUserId(), user -> {
47   - respVO.setOwnerUserName(user.getNickname());
48   - findAndThen(deptMap, user.getDeptId(), dept -> {
49   - respVO.setOwnerUserDeptName(dept.getName());
50   - });
51   - });
52   - findAndThen(userMap, Long.parseLong(respVO.getCreator()), user -> {
53   - respVO.setCreatorName(user.getNickname());
  44 + static void setUserInfo(CrmCustomerRespVO customer, Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
  45 + customer.setAreaName(AreaUtils.format(customer.getAreaId()));
  46 + findAndThen(userMap, customer.getOwnerUserId(), user -> {
  47 + customer.setOwnerUserName(user.getNickname());
  48 + findAndThen(deptMap, user.getDeptId(), dept -> customer.setOwnerUserDeptName(dept.getName()));
54 49 });
  50 + findAndThen(userMap, Long.parseLong(customer.getCreator()), user -> customer.setCreatorName(user.getNickname()));
55 51 }
56 52  
57 53 List<CrmCustomerExcelVO> convertList02(List<CrmCustomerDO> list);
... ...
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.*;
24 24 public class CrmPermissionDO extends BaseDO {
25 25  
26 26 /**
27   - * ID
  27 + * 编号,主键自增
28 28 */
29 29 @TableId
30 30 private Long id;
... ...
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;
14 14 import com.baomidou.mybatisplus.core.metadata.IPage;
15 15 import org.apache.ibatis.annotations.Mapper;
16 16  
17   -import java.util.Collection;
18   -import java.util.List;
19   -
20 17 /**
21 18 * 客户 Mapper
22 19 *
... ... @@ -40,6 +37,7 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
40 37 .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource()));
41 38 }
42 39  
  40 + // TODO @puhui999:这个方法还要哇?
43 41 default PageResult<CrmCustomerDO> selectPage1(CrmCustomerPageReqVO pageReqVO, Long userId) {
44 42 LambdaQueryWrapperX<CrmCustomerDO> queryWrapperX = new LambdaQueryWrapperX<>();
45 43 //queryWrapperX.sql
... ... @@ -94,7 +92,7 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
94 92 */
95 93 if (pageReqVO.getPool()) { // 情况一:公海
96 94 mpjLambdaWrapperX.isNull(CrmCustomerDO::getOwnerUserId);
97   - } else {// 情况一:不是公海
  95 + } else { // 情况二:不是公海
98 96 mpjLambdaWrapperX.isNotNull(CrmCustomerDO::getOwnerUserId);
99 97 }
100 98 // TODO 场景数据过滤
... ... @@ -117,9 +115,4 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
117 115 .isNull(CrmCustomerDO::getOwnerUserId));
118 116 }
119 117  
120   - default List<CrmCustomerDO> selectList(Collection<Long> ids) {
121   - return selectList(new LambdaQueryWrapperX<CrmCustomerDO>()
122   - .inIfPresent(CrmCustomerDO::getId, ids));
123   - }
124   -
125 118 }
... ...
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;
7 7 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
8 8 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
9 9 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
  10 +import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
10 11 import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
11 12 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
12 13 import lombok.extern.slf4j.Slf4j;
... ... @@ -38,24 +39,6 @@ public class CrmPermissionAspect {
38 39 @Resource
39 40 private CrmPermissionService crmPermissionService;
40 41  
41   - /**
42   - * 获得用户编号
43   - *
44   - * @return 用户编号
45   - */
46   - private static Long getUserId() {
47   - return WebFrameworkUtils.getLoginUserId();
48   - }
49   -
50   - private static Map<String, Object> getSpelValue(JoinPoint joinPoint, CrmPermission crmPermission) {
51   - List<String> spelList = new ArrayList<>(); // 表达式列表
52   - spelList.add(crmPermission.bizId());
53   - if (StrUtil.isNotEmpty(crmPermission.bizTypeValue())) { // 为空则表示 bizType 有值
54   - spelList.add(crmPermission.bizTypeValue());
55   - }
56   - return SpringExpressionUtils.parseExpressions(joinPoint, spelList);
57   - }
58   -
59 42 @Before("@annotation(crmPermission)")
60 43 public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) {
61 44 // TODO 芋艿:临时,方便大家调试
... ... @@ -63,10 +46,10 @@ public class CrmPermissionAspect {
63 46 // return;
64 47 //}
65 48 // 获取相关属性值
66   - Map<String, Object> spelValue = getSpelValue(joinPoint, crmPermission);
  49 + Map<String, Object> expressionValues = parseExpressions(joinPoint, crmPermission);
67 50 Integer bizType = StrUtil.isEmpty(crmPermission.bizTypeValue()) ?
68   - crmPermission.bizType()[0].getType() : (Integer) spelValue.get(crmPermission.bizTypeValue()); // 模块类型
69   - Long bizId = (Long) spelValue.get(crmPermission.bizId()); // 模块数据编号
  51 + crmPermission.bizType()[0].getType() : (Integer) expressionValues.get(crmPermission.bizTypeValue()); // 模块类型
  52 + Long bizId = (Long) expressionValues.get(crmPermission.bizId()); // 模块数据编号
70 53 Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别
71 54  
72 55 // TODO 如果是超级管理员则直接通过
... ... @@ -75,35 +58,55 @@ public class CrmPermissionAspect {
75 58 //}
76 59  
77 60 // 1. 获取数据权限
78   - List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
  61 + List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionListByBiz(bizType, bizId);
79 62 if (CollUtil.isEmpty(bizPermissions)) { // 数据权限不存存那么数据也不存在
80   - throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, crmPermission.bizType()[0].getName());
  63 + throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, CrmBizTypeEnum.getNameByType(bizType));
81 64 }
82 65 // 2.1 情况一:如果自己是负责人,则默认有所有权限
83   - CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, item -> ObjUtil.equal(item.getUserId(), getUserId()));
84   - if (CrmPermissionLevelEnum.isOwner(userPermission.getLevel())) {
85   - return;
86   - }
87   - // 2.2 情况二:校验自己是否有读权限
88   - if (CrmPermissionLevelEnum.isRead(permissionLevel)) {
89   - if (CrmPermissionLevelEnum.isRead(userPermission.getLevel())) { // 校验当前用户是否有读权限
  66 + CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, permission -> ObjUtil.equal(permission.getUserId(), getUserId()));
  67 + if (userPermission != null) {
  68 + if (CrmPermissionLevelEnum.isOwner(userPermission.getLevel())) {
90 69 return;
91 70 }
92   - // 如果查询数据的话拥有写权限的也能查询
93   - if (CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限
94   - return;
  71 + // 2.2 情况二:校验自己是否有读权限
  72 + if (CrmPermissionLevelEnum.isRead(permissionLevel)) {
  73 + if (CrmPermissionLevelEnum.isRead(userPermission.getLevel()) // 校验当前用户是否有读权限
  74 + || CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限
  75 + return;
  76 + }
95 77 }
96   - }
97   - // 2.3 情况三:校验自己是否有写权限
98   - if (CrmPermissionLevelEnum.isWrite(permissionLevel)) {
99   - if (CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限
100   - return;
  78 + // 2.3 情况三:校验自己是否有写权限
  79 + if (CrmPermissionLevelEnum.isWrite(permissionLevel)) {
  80 + if (CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限
  81 + return;
  82 + }
101 83 }
102 84 }
  85 + // 2.4 没有权限!
  86 + // 打个 info 日志,方便后续排查问题、审计
  87 + log.info("[doBefore][userId({}) 要求权限({}) 实际权限({}) 数据校验错误]",
  88 + getUserId(), permissionLevel, toJsonString(userPermission));
  89 + throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.getNameByType(bizType));
  90 + }
  91 +
  92 + /**
  93 + * 获得用户编号
  94 + *
  95 + * @return 用户编号
  96 + */
  97 + private static Long getUserId() {
  98 + return WebFrameworkUtils.getLoginUserId();
  99 + }
103 100  
104   - // 打个 info 日志,方便后续排查问题、审计;
105   - log.info("[doBefore][crmPermission({}) 数据校验错误]", toJsonString(userPermission));
106   - throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType()[0].getName());
  101 + private static Map<String, Object> parseExpressions(JoinPoint joinPoint, CrmPermission crmPermission) {
  102 + // 1. 需要解析的表达式
  103 + List<String> expressionStrings = new ArrayList<>(2);
  104 + expressionStrings.add(crmPermission.bizId());
  105 + if (StrUtil.isNotEmpty(crmPermission.bizTypeValue())) { // 为空则表示 bizType 有值
  106 + expressionStrings.add(crmPermission.bizTypeValue());
  107 + }
  108 + // 2. 执行解析
  109 + return SpringExpressionUtils.parseExpressions(joinPoint, expressionStrings);
107 110 }
108 111  
109 112 }
... ...
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;
9 9 import java.util.Arrays;
10 10  
11 11 /**
12   - * Crm 类型枚举
  12 + * CRM 类型枚举
13 13 *
14 14 * @author HUIHUI
15 15 */
... ... @@ -24,6 +24,7 @@ public enum CrmBizTypeEnum implements IntArrayValuable {
24 24 CRM_CONTRACT(5, "合同");
25 25  
26 26 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizTypeEnum::getType).toArray();
  27 +
27 28 /**
28 29 * 类型
29 30 */
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
... ... @@ -47,6 +47,15 @@ public interface CrmCustomerService {
47 47 CrmCustomerDO getCustomer(Long id);
48 48  
49 49 /**
  50 + * 获得客户列表
  51 + *
  52 + * @param ids 客户编号数组
  53 + * @author ljlleo
  54 + * @return 客户列表
  55 + */
  56 + List<CrmCustomerDO> getCustomerList(Collection<Long> ids);
  57 +
  58 + /**
50 59 * 获得客户分页
51 60 *
52 61 * @param pageReqVO 分页查询
... ... @@ -86,6 +95,15 @@ public interface CrmCustomerService {
86 95 */
87 96 void lockCustomer(@Valid CrmCustomerUpdateReqVO updateReqVO);
88 97  
  98 + // ==================== 公海相关操作 ====================
  99 +
  100 + /**
  101 + * 客户放入公海
  102 + *
  103 + * @param id 客户编号
  104 + */
  105 + void putCustomerPool(Long id);
  106 +
89 107 /**
90 108 * 领取公海客户
91 109 *
... ... @@ -110,19 +128,4 @@ public interface CrmCustomerService {
110 128 */
111 129 void receive(Long id, Long userId);
112 130  
113   - /**
114   - * 客户放入公海
115   - *
116   - * @param id 客户编号
117   - */
118   - void putPool(Long id);
119   -
120   - /**
121   - * 根据客户ID集合查询客户集合
122   - * @param ids
123   - * @author ljlleo
124   - * @return
125   - */
126   - List<CrmCustomerDO> getCustomerList(Collection<Long> ids);
127   -
128 131 }
... ...
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;
15 15 import org.springframework.validation.annotation.Validated;
16 16  
17 17 import javax.annotation.Resource;
  18 +import java.util.Collection;
18 19 import java.util.Collections;
19 20 import java.util.List;
20 21 import java.util.Objects;
... ... @@ -33,6 +34,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
33 34  
34 35 @Resource
35 36 private CrmCustomerMapper customerMapper;
  37 +
36 38 @Resource
37 39 private CrmPermissionService crmPermissionService;
38 40  
... ... @@ -46,8 +48,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
46 48 // 创建数据权限
47 49 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
48 50 .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
49   -
50   - // 返回
51 51 return customer.getId();
52 52 }
53 53  
... ... @@ -87,6 +87,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
87 87 }
88 88  
89 89 @Override
  90 + public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) {
  91 + return customerMapper.selectBatchIds(ids);
  92 + }
  93 +
  94 + @Override
90 95 public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId) {
91 96 // 1.1. TODO 如果是超级管理员
92 97 boolean admin = false;
... ... @@ -204,6 +209,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
204 209 }
205 210 }
206 211  
  212 + // TODO @puhui999:合并到 receiveCustomer 里
207 213 @Override
208 214 @Transactional(rollbackFor = Exception.class)
209 215 public void receive(Long id, Long userId) {
... ... @@ -227,31 +233,28 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
227 233 @Override
228 234 @Transactional(rollbackFor = Exception.class)
229 235 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
230   - public void putPool(Long id) {
  236 + public void putCustomerPool(Long id) {
231 237 // 1. 校验存在
232 238 CrmCustomerDO customer = customerMapper.selectById(id);
233 239 if (customer == null) {
234 240 throw exception(CUSTOMER_NOT_EXISTS);
235 241 }
  242 + // TODO puhui999:校验合并到 validateCustomerOwnerExists、validateCustomerIsLocked
236 243 // 1.2. 校验是否为公海数据
237 244 if (customer.getOwnerUserId() == null) {
238 245 throw exception(CUSTOMER_IN_POOL);
239 246 }
240   - // 1.3. 校验客户是否锁定、
  247 + // 1.3. 校验客户是否锁定
241 248 if (customer.getLockStatus()) {
242 249 throw exception(CUSTOMER_LOCKED_PUT_POOL_FAIL);
243 250 }
244 251  
245   - // 2. 公海数据-设置负责人 NULL
  252 + // 2. 设置负责人为 NULL
  253 + // TODO @puhui999:updateById 这么操作,是无法设置 null 的;
246 254 customerMapper.updateById(new CrmCustomerDO().setId(customer.getId()).setOwnerUserId(null));
247 255 // 3. 删除负责人数据权限
248 256 crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(),
249 257 CrmPermissionLevelEnum.OWNER.getLevel());
250 258 }
251 259  
252   - @Override
253   - public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) {
254   - return customerMapper.selectList(ids);
255   - }
256   -
257 260 }
... ...
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 {
64 64 * @param userId 用户编号
65 65 * @return 数据权限
66 66 */
67   - CrmPermissionDO getPermissionByIdAndUserId(Long id, Long userId);
  67 + CrmPermissionDO getPermission(Long id, Long userId);
68 68  
69 69 /**
70 70 * 获取数据权限列表,通过 数据类型 x 某个数据
... ... @@ -73,7 +73,7 @@ public interface CrmPermissionService {
73 73 * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
74 74 * @return Crm 数据权限列表
75 75 */
76   - List<CrmPermissionDO> getPermissionByBizTypeAndBizId(Integer bizType, Long bizId);
  76 + List<CrmPermissionDO> getPermissionListByBiz(Integer bizType, Long bizId);
77 77  
78 78 /**
79 79 * 获得数据权限列表
... ... @@ -81,7 +81,7 @@ public interface CrmPermissionService {
81 81 * @param ids 数据权限编号列表
82 82 * @return 数据权限列表
83 83 */
84   - List<CrmPermissionDO> getPermissionListByIds(Collection<Long> ids);
  84 + List<CrmPermissionDO> getPermissionList(Collection<Long> ids);
85 85  
86 86 /**
87 87 * 获取用户参与的模块数据列表
... ...
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 {
55 55 @Override
56 56 @Transactional(rollbackFor = Exception.class)
57 57 public void updatePermission(CrmPermissionUpdateReqVO updateReqVO) {
58   - // 校验存在
  58 + // 1. 校验存在
59 59 validateCrmPermissionExists(updateReqVO.getIds());
60   -
  60 + // 2. 更新
61 61 List<CrmPermissionDO> updateDO = CrmPermissionConvert.INSTANCE.convertList(updateReqVO);
62 62 crmPermissionMapper.updateBatch(updateDO);
63 63 }
64 64  
  65 + private void validateCrmPermissionExists(Collection<Long> ids) {
  66 + List<CrmPermissionDO> permissionList = crmPermissionMapper.selectBatchIds(ids);
  67 + if (ObjUtil.notEqual(permissionList.size(), ids.size())) {
  68 + throw exception(CRM_PERMISSION_NOT_EXISTS);
  69 + }
  70 + }
  71 +
65 72 @Override
66 73 @Transactional(rollbackFor = Exception.class)
67 74 public void transferPermission(CrmPermissionTransferReqBO transferReqBO) {
68   - // 1. 校验数据权限-是否是负责人,只有负责人才可以转移
69   - CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId(transferReqBO.getBizType(),
70   - transferReqBO.getBizId(), transferReqBO.getUserId());
71   - String crmName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType());
  75 + // 1. 校验数据权限:是否是负责人,只有负责人才可以转移
  76 + CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId(
  77 + transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId());
  78 + String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType());
72 79 // TODO 校验是否为超级管理员 || 1
73 80 if (oldPermission == null || !isOwner(oldPermission.getLevel())) {
74   - throw exception(CRM_PERMISSION_DENIED, crmName);
  81 + throw exception(CRM_PERMISSION_DENIED, bizTypeName);
75 82 }
76 83 // 1.1 校验转移对象是否已经是该负责人
77 84 if (ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) {
78   - throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, crmName);
  85 + throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, bizTypeName);
79 86 }
80 87 // 1.2 校验新负责人是否存在
81 88 adminUserApi.validateUserList(Collections.singletonList(transferReqBO.getNewOwnerUserId()));
... ... @@ -84,23 +91,23 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
84 91 List<CrmPermissionDO> permissions = crmPermissionMapper.selectByBizTypeAndBizId(
85 92 transferReqBO.getBizType(), transferReqBO.getBizId()); // 获得所有数据权限
86 93 CrmPermissionDO permission = CollUtil.findOne(permissions,
87   - item -> ObjUtil.equal(item.getUserId(), transferReqBO.getNewOwnerUserId())); // 校验新负责人是否存在于数据权限列表
88   - if (permission == null) { // 不存在则以负责人的级别加入
  94 + item -> ObjUtil.equal(item.getUserId(), transferReqBO.getNewOwnerUserId()));
  95 + if (permission == null) {
89 96 crmPermissionMapper.insert(new CrmPermissionDO().setBizType(transferReqBO.getBizType())
90 97 .setBizId(transferReqBO.getBizId()).setUserId(transferReqBO.getNewOwnerUserId())
91 98 .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
92   - } else { // 存在则修改权限级别
  99 + } else {
93 100 crmPermissionMapper.updateById(new CrmPermissionDO().setId(permission.getId())
94 101 .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
95 102 }
96 103  
97 104 // 3. 修改老负责人的权限
98   - if (transferReqBO.getOldOwnerPermissionLevel() != null) { // 加入数据权限列表
  105 + if (transferReqBO.getOldOwnerPermissionLevel() != null) {
99 106 crmPermissionMapper.updateById(new CrmPermissionDO().setId(oldPermission.getId())
100   - .setLevel(transferReqBO.getOldOwnerPermissionLevel())); // 设置权限级别
101   - return;
  107 + .setLevel(transferReqBO.getOldOwnerPermissionLevel()));
  108 + } else {
  109 + crmPermissionMapper.deleteById(oldPermission.getId());
102 110 }
103   - crmPermissionMapper.deleteById(oldPermission.getId());
104 111 }
105 112  
106 113 @Override
... ... @@ -116,7 +123,8 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
116 123 @Override
117 124 @Transactional(rollbackFor = Exception.class)
118 125 public void deletePermission(Integer bizType, Long bizId, Integer level) {
119   - List<CrmPermissionDO> permissions = crmPermissionMapper.selectListByBizTypeAndBizIdAndLevel(bizType, bizId, level);
  126 + List<CrmPermissionDO> permissions = crmPermissionMapper.selectListByBizTypeAndBizIdAndLevel(
  127 + bizType, bizId, level);
120 128 // 校验存在
121 129 if (CollUtil.isEmpty(permissions)) {
122 130 throw exception(CRM_PERMISSION_NOT_EXISTS);
... ... @@ -127,31 +135,23 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
127 135 }
128 136  
129 137 @Override
130   - public CrmPermissionDO getPermissionByIdAndUserId(Long id, Long userId) {
  138 + public CrmPermissionDO getPermission(Long id, Long userId) {
131 139 return crmPermissionMapper.selectByIdAndUserId(id, userId);
132 140 }
133 141  
134 142 @Override
135   - public List<CrmPermissionDO> getPermissionByBizTypeAndBizId(Integer bizType, Long bizId) {
  143 + public List<CrmPermissionDO> getPermissionListByBiz(Integer bizType, Long bizId) {
136 144 return crmPermissionMapper.selectByBizTypeAndBizId(bizType, bizId);
137 145 }
138 146  
139 147 @Override
140   - public List<CrmPermissionDO> getPermissionListByIds(Collection<Long> ids) {
  148 + public List<CrmPermissionDO> getPermissionList(Collection<Long> ids) {
141 149 if (CollUtil.isEmpty(ids)) {
142 150 return Collections.emptyList();
143 151 }
144 152 return crmPermissionMapper.selectBatchIds(ids);
145 153 }
146 154  
147   - private void validateCrmPermissionExists(Collection<Long> ids) {
148   - List<CrmPermissionDO> permissionList = crmPermissionMapper.selectBatchIds(ids);
149   - // 校验存在
150   - if (ObjUtil.notEqual(permissionList.size(), ids.size())) {
151   - throw exception(CRM_PERMISSION_NOT_EXISTS);
152   - }
153   - }
154   -
155 155 @Override
156 156 public List<CrmPermissionDO> getPermissionListByBizTypeAndUserId(Integer bizType, Long userId) {
157 157 return crmPermissionMapper.selectListByBizTypeAndUserId(bizType, userId);
... ...
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;
3 3 import cn.hutool.core.util.StrUtil;
4 4 import com.github.yulichang.wrapper.MPJLambdaWrapper;
5 5  
  6 +// TODO @puhui999:这个类还要哇?
6 7 /**
7 8 * 数据权限工具类
8 9 *
... ...