From 899e40deb9baa950d83aeb823374a75af734a3e6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 25 Nov 2023 10:02:55 +0800 Subject: [PATCH] =?UTF-8?q?crm=EF=BC=9Acode=20review=20=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/collection/CollectionUtils.java | 68 +++++------ .../util/spring/SpringExpressionUtils.java | 2 +- .../admin/customer/CrmCustomerController.java | 60 +++++----- .../permission/CrmPermissionController.java | 15 ++- .../convert/customer/CrmCustomerConvert.java | 18 ++- .../permission/CrmPermissionDO.java | 2 +- .../dal/mysql/customer/CrmCustomerMapper.java | 11 +- .../core/aop/CrmPermissionAspect.java | 113 +++++++++--------- .../crm/framework/enums/CrmBizTypeEnum.java | 3 +- .../service/customer/CrmCustomerService.java | 33 ++--- .../customer/CrmCustomerServiceImpl.java | 23 ++-- .../permission/CrmPermissionService.java | 6 +- .../permission/CrmPermissionServiceImpl.java | 54 ++++----- .../module/crm/util/CrmPermissionUtils.java | 1 + 14 files changed, 205 insertions(+), 204 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java index 2d3232978..35ebc8ff3 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java +++ b/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 List convertListByFlatMap(Collection from, + Function> func) { + if (CollUtil.isEmpty(from)) { + return new ArrayList<>(); + } + return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toList()); + } + + public static List convertListByFlatMap(Collection from, + Function mapper, + Function> func) { + if (CollUtil.isEmpty(from)) { + return new ArrayList<>(); + } + return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toList()); + } + public static List mergeValuesFromMap(Map> 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 Set convertSetByFlatMap(Collection from, + Function> func) { + if (CollUtil.isEmpty(from)) { + return new HashSet<>(); + } + return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet()); + } + + public static Set convertSetByFlatMap(Collection from, + Function mapper, + Function> func) { + if (CollUtil.isEmpty(from)) { + return new HashSet<>(); + } + return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet()); + } + public static Map convertMap(Collection from, Function 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 List convertListByFlatMap(Collection from, - Function> func) { - if (CollUtil.isEmpty(from)) { - return new ArrayList<>(); - } - return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toList()); - } - - public static List convertListByFlatMap(Collection from, - Function mapper, - Function> func) { - if (CollUtil.isEmpty(from)) { - return new ArrayList<>(); - } - return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toList()); - } - - public static Set convertSetByFlatMap(Collection from, - Function> func) { - if (CollUtil.isEmpty(from)) { - return new HashSet<>(); - } - return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet()); - } - - public static Set convertSetByFlatMap(Collection from, - Function mapper, - Function> func) { - if (CollUtil.isEmpty(from)) { - return new HashSet<>(); - } - return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet()); - } - } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java index aa8b1d82b..9a7f8812b 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java +++ b/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(); /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index b09919b2f..976781f71 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/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 userIds = new HashSet<>(); - userIds.add(customer.getOwnerUserId()); // 负责人 - userIds.add(Long.parseLong(customer.getCreator())); // 加入创建者 - List userList = adminUserApi.getUserList(userIds); - Map userMap = convertMap(userList, AdminUserRespDTO::getId); - // 2.2 获取部门详情 - Map deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId)); + Map userMap = adminUserApi.getUserMap( + Collections.asSet(Long.valueOf(customer.getCreator()), customer.getOwnerUserId())); + Map 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 putPool(@RequestParam("id") Long id) { - customerService.putPool(id); - return success(true); - } - @GetMapping("/page") @Operation(summary = "获得客户分页") @PreAuthorize("@ss.hasPermission('crm:customer:query')") public CommonResult> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { + // 1. 查询客户分页 PageResult pageResult = customerService.getCustomerPage(pageVO, getLoginUserId()); if (CollUtil.isEmpty(pageResult.getList())) { return success(PageResult.empty(pageResult.getTotal())); } - // 1.1 获取负责人详情 - Set userIds = convertSet(pageResult.getList(), CrmCustomerDO::getOwnerUserId); - userIds.addAll(convertSet(pageResult.getList(), item -> Long.parseLong(item.getCreator()))); // 加入创建者 - List userList = adminUserApi.getUserList(userIds); - Map userMap = convertMap(userList, AdminUserRespDTO::getId); - // 1.2 获取部门详情 - Map deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId)); + + // 2. 拼接数据 + Map userMap = adminUserApi.getUserMap( + convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId()))); + Map 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 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 distributeCustomer(@RequestParam(value = "ownerUserId") Long ownerUserId, - @RequestParam(value = "ids") List ids){ + public CommonResult distributeCustomer(@RequestParam(value = "ids") List ids, + @RequestParam(value = "ownerUserId") Long ownerUserId){ customerService.distributeCustomer(ids, ownerUserId); return success(true); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java index fcae121f5..34a912a2e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java +++ b/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 deletePermission(@RequestParam("ids") Collection ids) { - List permissions = permissionService.getPermissionListByIds(ids); + List permissions = permissionService.getPermissionList(ids); if (CollUtil.isEmpty(permissions)) { throw exception(CRM_PERMISSION_NOT_EXISTS); } Set 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 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> getPermissionList(@RequestParam("bizType") Integer bizType, @RequestParam("bizId") Long bizId) { - List permission = permissionService.getPermissionByBizTypeAndBizId(bizType, bizId); + List permission = permissionService.getPermissionListByBiz(bizType, bizId); if (CollUtil.isEmpty(permission)) { return success(Collections.emptyList()); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java index 86808ec92..88971d4af 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java +++ b/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 userMap, Map 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 userMap, Map 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 convertList02(List list); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java index 3bdd575ee..bdfd8d38f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java +++ b/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; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index cb409fbda..bfd0c8dc0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/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 { .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource())); } + // TODO @puhui999:这个方法还要哇? default PageResult selectPage1(CrmCustomerPageReqVO pageReqVO, Long userId) { LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); //queryWrapperX.sql @@ -94,7 +92,7 @@ public interface CrmCustomerMapper extends BaseMapperX { */ if (pageReqVO.getPool()) { // 情况一:公海 mpjLambdaWrapperX.isNull(CrmCustomerDO::getOwnerUserId); - } else {// 情况一:不是公海 + } else { // 情况二:不是公海 mpjLambdaWrapperX.isNotNull(CrmCustomerDO::getOwnerUserId); } // TODO 场景数据过滤 @@ -117,9 +115,4 @@ public interface CrmCustomerMapper extends BaseMapperX { .isNull(CrmCustomerDO::getOwnerUserId)); } - default List selectList(Collection ids) { - return selectList(new LambdaQueryWrapperX() - .inIfPresent(CrmCustomerDO::getId, ids)); - } - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java index cfe28b435..f1a9075cd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java +++ b/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,6 +39,56 @@ public class CrmPermissionAspect { @Resource private CrmPermissionService crmPermissionService; + @Before("@annotation(crmPermission)") + public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) { + // TODO 芋艿:临时,方便大家调试 + //if (true) { + // return; + //} + // 获取相关属性值 + Map expressionValues = parseExpressions(joinPoint, crmPermission); + Integer bizType = StrUtil.isEmpty(crmPermission.bizTypeValue()) ? + crmPermission.bizType()[0].getType() : (Integer) expressionValues.get(crmPermission.bizTypeValue()); // 模块类型 + Long bizId = (Long) expressionValues.get(crmPermission.bizId()); // 模块数据编号 + Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别 + + // TODO 如果是超级管理员则直接通过 + //if (superAdmin){ + // return; + //} + + // 1. 获取数据权限 + List bizPermissions = crmPermissionService.getPermissionListByBiz(bizType, bizId); + if (CollUtil.isEmpty(bizPermissions)) { // 数据权限不存存那么数据也不存在 + throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, CrmBizTypeEnum.getNameByType(bizType)); + } + // 2.1 情况一:如果自己是负责人,则默认有所有权限 + CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, permission -> ObjUtil.equal(permission.getUserId(), getUserId())); + if (userPermission != null) { + if (CrmPermissionLevelEnum.isOwner(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.4 没有权限! + // 打个 info 日志,方便后续排查问题、审计 + log.info("[doBefore][userId({}) 要求权限({}) 实际权限({}) 数据校验错误]", + getUserId(), permissionLevel, toJsonString(userPermission)); + throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.getNameByType(bizType)); + } + /** * 获得用户编号 * @@ -47,63 +98,15 @@ public class CrmPermissionAspect { return WebFrameworkUtils.getLoginUserId(); } - private static Map getSpelValue(JoinPoint joinPoint, CrmPermission crmPermission) { - List spelList = new ArrayList<>(); // 表达式列表 - spelList.add(crmPermission.bizId()); + private static Map parseExpressions(JoinPoint joinPoint, CrmPermission crmPermission) { + // 1. 需要解析的表达式 + List expressionStrings = new ArrayList<>(2); + expressionStrings.add(crmPermission.bizId()); if (StrUtil.isNotEmpty(crmPermission.bizTypeValue())) { // 为空则表示 bizType 有值 - spelList.add(crmPermission.bizTypeValue()); + expressionStrings.add(crmPermission.bizTypeValue()); } - return SpringExpressionUtils.parseExpressions(joinPoint, spelList); - } - - @Before("@annotation(crmPermission)") - public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) { - // TODO 芋艿:临时,方便大家调试 - //if (true) { - // return; - //} - // 获取相关属性值 - Map spelValue = getSpelValue(joinPoint, crmPermission); - Integer bizType = StrUtil.isEmpty(crmPermission.bizTypeValue()) ? - crmPermission.bizType()[0].getType() : (Integer) spelValue.get(crmPermission.bizTypeValue()); // 模块类型 - Long bizId = (Long) spelValue.get(crmPermission.bizId()); // 模块数据编号 - Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别 - - // TODO 如果是超级管理员则直接通过 - //if (superAdmin){ - // return; - //} - - // 1. 获取数据权限 - List bizPermissions = crmPermissionService.getPermissionByBizTypeAndBizId(bizType, bizId); - if (CollUtil.isEmpty(bizPermissions)) { // 数据权限不存存那么数据也不存在 - throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, crmPermission.bizType()[0].getName()); - } - // 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())) { // 校验当前用户是否有读权限 - return; - } - // 如果查询数据的话拥有写权限的也能查询 - if (CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限 - return; - } - } - // 2.3 情况三:校验自己是否有写权限 - if (CrmPermissionLevelEnum.isWrite(permissionLevel)) { - if (CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限 - return; - } - } - - // 打个 info 日志,方便后续排查问题、审计; - log.info("[doBefore][crmPermission({}) 数据校验错误]", toJsonString(userPermission)); - throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType()[0].getName()); + // 2. 执行解析 + return SpringExpressionUtils.parseExpressions(joinPoint, expressionStrings); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmBizTypeEnum.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmBizTypeEnum.java index f381777ae..1e780df5c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmBizTypeEnum.java +++ b/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(); + /** * 类型 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 24605d55c..ae429c745 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/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 getCustomerList(Collection 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 getCustomerList(Collection ids); - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 1156a2c98..aa5ef9f5b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/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 getCustomerList(Collection ids) { + return customerMapper.selectBatchIds(ids); + } + @Override public PageResult 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 getCustomerList(Collection ids) { - return customerMapper.selectList(ids); - } - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java index 638388031..3067bf7c2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java +++ b/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 getPermissionByBizTypeAndBizId(Integer bizType, Long bizId); + List getPermissionListByBiz(Integer bizType, Long bizId); /** * 获得数据权限列表 @@ -81,7 +81,7 @@ public interface CrmPermissionService { * @param ids 数据权限编号列表 * @return 数据权限列表 */ - List getPermissionListByIds(Collection ids); + List getPermissionList(Collection ids); /** * 获取用户参与的模块数据列表 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index 5d85ebf80..935b6f0e0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/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 updateDO = CrmPermissionConvert.INSTANCE.convertList(updateReqVO); crmPermissionMapper.updateBatch(updateDO); } + private void validateCrmPermissionExists(Collection ids) { + List 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 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 permissions = crmPermissionMapper.selectListByBizTypeAndBizIdAndLevel(bizType, bizId, level); + List 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 getPermissionByBizTypeAndBizId(Integer bizType, Long bizId) { + public List getPermissionListByBiz(Integer bizType, Long bizId) { return crmPermissionMapper.selectByBizTypeAndBizId(bizType, bizId); } @Override - public List getPermissionListByIds(Collection ids) { + public List getPermissionList(Collection ids) { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } return crmPermissionMapper.selectBatchIds(ids); } - private void validateCrmPermissionExists(Collection ids) { - List permissionList = crmPermissionMapper.selectBatchIds(ids); - // 校验存在 - if (ObjUtil.notEqual(permissionList.size(), ids.size())) { - throw exception(CRM_PERMISSION_NOT_EXISTS); - } - } - @Override public List getPermissionListByBizTypeAndUserId(Integer bizType, Long userId) { return crmPermissionMapper.selectListByBizTypeAndUserId(bizType, userId); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java index 675c507be..7c15b5f1f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java +++ b/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:这个类还要哇? /** * 数据权限工具类 *