mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 10:18:42 +08:00 
			
		
		
		
	CRM:完善数据分页查询条件构造 CrmQueryWrapperUtils
This commit is contained in:
		| @@ -1,8 +1,8 @@ | ||||
| ### 请求 /transfer | ||||
| PUT {{baseUrl}}/crm/customer/transfer | ||||
| Content-Type: application/json | ||||
| Content-Type: application/-id: {{adminTenentId}}json | ||||
| Authorization: Bearer {{token}} | ||||
| tenant-id: {{adminTenentId}} | ||||
| tenant | ||||
|  | ||||
| { | ||||
|   "id": 10, | ||||
|   | ||||
| @@ -3,8 +3,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer; | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||||
| import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | ||||
| import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | ||||
| import cn.iocoder.yudao.framework.operatelogv2.core.vo.OperateLogV2PageReqVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; | ||||
| import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||||
| @@ -12,6 +14,7 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | ||||
| import cn.iocoder.yudao.module.system.api.dept.DeptApi; | ||||
| import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | ||||
| import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; | ||||
| import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; | ||||
| import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; | ||||
| import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||||
| import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||||
| @@ -135,23 +138,14 @@ public class CrmCustomerController { | ||||
|         return success(true); | ||||
|     } | ||||
|  | ||||
|     // TODO @puhui999:operate-log-list 或者 operate-log-page 如果分页 | ||||
|     @GetMapping("/operate-log") | ||||
|     @GetMapping("/operate-log-page") | ||||
|     @Operation(summary = "获得客户操作日志") | ||||
|     @Parameter(name = "id", description = "编号", required = true, example = "1024") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:query')") | ||||
|     // TODO @puhui999:最好有读权限;方法名改成 getCustomerOperateLog | ||||
|     public CommonResult<List<OperateLogV2RespDTO>> getOperateLog(@RequestParam("id") Long id) { | ||||
|         // 1. 获取客户 | ||||
|         // TODO @puhui999:这个校验可以去掉哈; | ||||
|         CrmCustomerDO customer = customerService.getCustomer(id); | ||||
|         if (customer == null) { | ||||
|             return success(null); | ||||
|         } | ||||
|  | ||||
|         // 2. 获取操作日志 | ||||
|         // TODO @puhui999:操作日志,返回可能要分页哈; | ||||
|         return success(operateLogApi.getOperateLogByModuleAndBizId(CRM_CUSTOMER, id)); | ||||
|     public CommonResult<PageResult<OperateLogV2RespDTO>> getCustomerOperateLog(OperateLogV2PageReqVO reqVO) { | ||||
|         reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 | ||||
|         reqVO.setBizType(CRM_CUSTOMER); | ||||
|         return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); | ||||
|     } | ||||
|  | ||||
|     // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; | ||||
|   | ||||
| @@ -38,11 +38,8 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> { | ||||
|     default PageResult<CrmBusinessDO> selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { | ||||
|         MPJLambdaWrapperX<CrmBusinessDO> query = new MPJLambdaWrapperX<>(); | ||||
|         // 拼接数据权限的查询条件 | ||||
|         boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), | ||||
|                 CrmBusinessDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | ||||
|         if (!condition) { | ||||
|             return PageResult.empty(); | ||||
|         } | ||||
|         // 拼接自身的查询条件 | ||||
|         query.selectAll(CrmBusinessDO.class) | ||||
|                 .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) | ||||
|   | ||||
| @@ -30,11 +30,8 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> { | ||||
|     default PageResult<CrmClueDO> selectPage(CrmCluePageReqVO pageReqVO, Long userId) { | ||||
|         MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>(); | ||||
|         // 拼接数据权限的查询条件 | ||||
|         boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), | ||||
|                 CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | ||||
|         if (!condition) { | ||||
|             return PageResult.empty(); | ||||
|         } | ||||
|         // 拼接自身的查询条件 | ||||
|         query.selectAll(CrmClueDO.class) | ||||
|                 .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) | ||||
|   | ||||
| @@ -43,11 +43,8 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> { | ||||
|     default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO pageReqVO, Long userId) { | ||||
|         MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>(); | ||||
|         // 拼接数据权限的查询条件 | ||||
|         boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), | ||||
|                 CrmContactDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | ||||
|         if (!condition) { | ||||
|             return PageResult.empty(); | ||||
|         } | ||||
|         // 拼接自身的查询条件 | ||||
|         query.selectAll(CrmContactDO.class) | ||||
|                 .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) | ||||
|   | ||||
| @@ -41,11 +41,8 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> { | ||||
|     default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) { | ||||
|         MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); | ||||
|         // 拼接数据权限的查询条件 | ||||
|         boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), | ||||
|                 CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | ||||
|         if (!condition) { | ||||
|             return PageResult.empty(); | ||||
|         } | ||||
|         // 拼接自身的查询条件 | ||||
|         mpjLambdaWrapperX.selectAll(CrmContractDO.class) | ||||
|                 .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) | ||||
|   | ||||
| @@ -30,11 +30,8 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||||
|     default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { | ||||
|         MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | ||||
|         // 拼接数据权限的查询条件 | ||||
|         boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), | ||||
|                 CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | ||||
|         if (!condition) { | ||||
|             return PageResult.empty(); | ||||
|         } | ||||
|         // 拼接自身的查询条件 | ||||
|         query.selectAll(CrmCustomerDO.class) | ||||
|                 .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) | ||||
|   | ||||
| @@ -39,11 +39,8 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { | ||||
|     default PageResult<CrmReceivableDO> selectPage(CrmReceivablePageReqVO pageReqVO, Long userId) { | ||||
|         MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>(); | ||||
|         // 拼接数据权限的查询条件 | ||||
|         boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), | ||||
|                 CrmReceivableDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | ||||
|         if (!condition) { | ||||
|             return PageResult.empty(); | ||||
|         } | ||||
|         // 拼接自身的查询条件 | ||||
|         query.selectAll(CrmReceivableDO.class) | ||||
|                 .eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo()) | ||||
|   | ||||
| @@ -38,11 +38,8 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO | ||||
|     default PageResult<CrmReceivablePlanDO> selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) { | ||||
|         MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>(); | ||||
|         // 拼接数据权限的查询条件 | ||||
|         boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), | ||||
|                 CrmReceivablePlanDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | ||||
|         if (!condition) { | ||||
|             return PageResult.empty(); | ||||
|         } | ||||
|         // 拼接自身的查询条件 | ||||
|         query.selectAll(CrmReceivablePlanDO.class) | ||||
|                 .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) | ||||
|   | ||||
| @@ -7,9 +7,12 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; | ||||
| import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | ||||
| import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; | ||||
| import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | ||||
| import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; | ||||
| import cn.iocoder.yudao.module.system.api.permission.PermissionApi; | ||||
| import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||||
| import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||||
| import com.baomidou.mybatisplus.core.toolkit.support.SFunction; | ||||
| import com.github.yulichang.autoconfigure.MybatisPlusJoinProperties; | ||||
| import com.github.yulichang.wrapper.MPJLambdaWrapper; | ||||
|  | ||||
| import java.util.Collection; | ||||
| @@ -33,46 +36,41 @@ public class CrmQueryWrapperUtils { | ||||
|      * @param userId    用户编号 | ||||
|      * @param sceneType 场景类型 | ||||
|      * @param pool      公海 | ||||
|      * @return 是否 (是:需要执行查询,否:不需要查询调用方法直接返回空) | ||||
|      */ | ||||
|     // TODO @puhui999:bizId 直接传递会不会简单点 回复:还是需要 SFunction 因为分页连表时不知道 bizId 是多少;是不是把 bizId 传入就好啦? | ||||
|     public static <T extends MPJLambdaWrapper<?>, S> boolean appendPermissionCondition(T query, Integer bizType, SFunction<S, ?> bizId, | ||||
|                                                                                        Long userId, Integer sceneType, Boolean pool) { | ||||
|     public static <T extends MPJLambdaWrapper<?>, S> void appendPermissionCondition(T query, Integer bizType, SFunction<S, ?> bizId, | ||||
|                                                                                     Long userId, Integer sceneType, Boolean pool) { | ||||
|         final String ownerUserIdField = SingletonManager.getMybatisPlusJoinProperties().getTableAlias() + ".owner_user_id"; | ||||
|         // 1. 构建数据权限连表条件 | ||||
|         if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 | ||||
|         if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 | ||||
|             query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) | ||||
|                     .eq(CrmPermissionDO::getBizId, bizId) | ||||
|                     .eq(CrmPermissionDO::getBizId, bizId) // 只能使用 SFunction 如果传 id 解析出来的 sql 不对 | ||||
|                     .eq(CrmPermissionDO::getUserId, userId)); | ||||
|         } | ||||
|         // 2.1 场景一:我负责的数据 | ||||
|         if (CrmSceneTypeEnum.isOwner(sceneType)) { | ||||
|             query.eq("owner_user_id", userId); | ||||
|             query.eq(ownerUserIdField, userId); | ||||
|         } | ||||
|         // 2.2 场景二:我参与的数据 | ||||
|         if (CrmSceneTypeEnum.isInvolved(sceneType)) { | ||||
|             query.ne("owner_user_id", userId) | ||||
|                     // TODO @puhui999:IN 是不是更合适哈; | ||||
|                     .and(q -> q.eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel()) | ||||
|                             .or() | ||||
|                             .eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.WRITE.getLevel())); | ||||
|             query.ne(ownerUserIdField, userId) | ||||
|                     .in(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel(), CrmPermissionLevelEnum.WRITE.getLevel()); | ||||
|         } | ||||
|         // 2.3 场景三:下属负责的数据 | ||||
|         if (CrmSceneTypeEnum.isSubordinate(sceneType)) { | ||||
|             // TODO @puhui999:要不如果没有下属,拼一个 owner_user_id in null,不返回结果就好啦; | ||||
|             List<AdminUserRespDTO> subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId); | ||||
|             List<AdminUserRespDTO> subordinateUsers = SingletonManager.getAdminUserApi().getUserListBySubordinate(userId); | ||||
|             if (CollUtil.isEmpty(subordinateUsers)) { | ||||
|                 return false; | ||||
|                 query.eq(ownerUserIdField, -1); // 不返回任何结果 | ||||
|             } else { | ||||
|                 query.in(ownerUserIdField, convertSet(subordinateUsers, AdminUserRespDTO::getId)); | ||||
|             } | ||||
|             query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId)); | ||||
|         } | ||||
|  | ||||
|         // 3. 拼接公海的查询条件 | ||||
|         if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海 | ||||
|             query.isNull("owner_user_id"); | ||||
|             query.isNull(ownerUserIdField); | ||||
|         } else { // 情况二:不是公海 | ||||
|             query.isNotNull("owner_user_id"); | ||||
|             query.isNotNull(ownerUserIdField); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -93,38 +91,38 @@ public class CrmQueryWrapperUtils { | ||||
|                         .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); | ||||
|     } | ||||
|  | ||||
|     private static AdminUserApi getAdminUserApi() { | ||||
|         return AdminUserApiHolder.ADMIN_USER_API; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 校验用户是否是管理员 | ||||
|      * 校验用户是否是 CRM 管理员 | ||||
|      * | ||||
|      * @param userId 用户编号 | ||||
|      * @return 是/否 | ||||
|      */ | ||||
|     private static boolean validateAdminUser(Long userId) { | ||||
|         // TODO 查询权限配置表用户的角色信息 | ||||
|         // TODO @puhui999:查询用户的角色;CRM_ADMIN("crm_admin", "CRM 管理员"), | ||||
|         //CrmPermissionConfig permissionConfig = crmPermissionConfigService.getPermissionConfigByUserId(userId); | ||||
|         //if (permissionConfig == null) { | ||||
|         //    return false; | ||||
|         //} | ||||
|         //// 校验是否为管理员 | ||||
|         //if (permissionConfig.getIsAdmin()){ | ||||
|         //    return true; | ||||
|         //} | ||||
|         return false; | ||||
|         return SingletonManager.getPermissionApi().hasAnyRoles(userId, CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 静态内部类实现 AdminUserApi 单例获取 | ||||
|      * 静态内部类实现单例获取 | ||||
|      * | ||||
|      * @author HUIHUI | ||||
|      */ | ||||
|     private static class AdminUserApiHolder { | ||||
|     private static class SingletonManager { | ||||
|  | ||||
|         private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); | ||||
|         private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); | ||||
|         private static final MybatisPlusJoinProperties MYBATIS_PLUS_JOIN_PROPERTIES = SpringUtil.getBean(MybatisPlusJoinProperties.class); | ||||
|  | ||||
|         public static AdminUserApi getAdminUserApi() { | ||||
|             return ADMIN_USER_API; | ||||
|         } | ||||
|  | ||||
|         public static PermissionApi getPermissionApi() { | ||||
|             return PERMISSION_API; | ||||
|         } | ||||
|  | ||||
|         public static MybatisPlusJoinProperties getMybatisPlusJoinProperties() { | ||||
|             return MYBATIS_PLUS_JOIN_PROPERTIES; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 puhui999
					puhui999