| | |
| | | public class CrmPermissionUtils { |
| | | |
| | | /** |
| | | * 校验用户是否是 CRM 管理员 |
| | | * 校验用户是否是 CRM 管理员(CRM 管理员或系统超级管理员) |
| | | * |
| | | * 超级管理员(super_admin)不受 CRM 数据权限限制,可以查看全部数据 |
| | | * |
| | | * @return 是/否 |
| | | */ |
| | | public static boolean isCrmAdmin() { |
| | | PermissionCommonApi permissionApi = SpringUtil.getBean(PermissionCommonApi.class); |
| | | return permissionApi.hasAnyRoles(getLoginUserId(), RoleCodeEnum.CRM_ADMIN.getCode()); |
| | | return permissionApi.hasAnyRoles(getLoginUserId(), |
| | | RoleCodeEnum.CRM_ADMIN.getCode(), RoleCodeEnum.SUPER_ADMIN.getCode()); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public static <T extends MPJLambdaWrapper<?>, S> void appendPermissionCondition(T query, Integer bizType, SFunction<S, ?> bizId, |
| | | Long userId, Integer sceneType) { |
| | | // 特殊逻辑:CRM 管理员 / 超级管理员直接查询所有,不过滤数据权限 |
| | | if (isCrmAdmin()) { |
| | | return; |
| | | } |
| | | MybatisPlusJoinProperties mybatisPlusJoinProperties = SpringUtil.getBean(MybatisPlusJoinProperties.class); |
| | | final String ownerUserIdField = mybatisPlusJoinProperties.getTableAlias() + ".owner_user_id"; |
| | | // 场景一:我负责的数据 |
| | |
| | | } |
| | | // 场景二:我参与的数据(我有读或写权限,并且不是负责人) |
| | | if (CrmSceneTypeEnum.isInvolved(sceneType)) { |
| | | if (CrmPermissionUtils.isCrmAdmin()) { // 特殊逻辑:如果是超管,直接查询所有,不过滤数据权限 |
| | | return; |
| | | } |
| | | // 商机特殊处理:同时关联商机团队和客户团队的权限 |
| | | if (CrmBizTypeEnum.CRM_BUSINESS.getType().equals(bizType)) { |
| | | appendBusinessPermissionCondition(query, bizId, userId, ownerUserIdField); |
| | | // 需要继承客户团队的模块:数据自身团队 ∪ 客户负责人/客户团队 |
| | | String tableName = getInheritCustomerTeamTable(bizType); |
| | | if (tableName != null) { |
| | | appendCustomerInheritedPermissionCondition(query, bizType, tableName, userId, ownerUserIdField); |
| | | } else { |
| | | query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) |
| | | .eq(CrmPermissionDO::getBizId, bizId) |
| | |
| | | } |
| | | |
| | | /** |
| | | * 商机特殊权限条件:同时关联商机团队和客户团队的权限 |
| | | * 商机继承客户团队的权限,即客户团队成员也能看到该客户下的商机 |
| | | * 获得「继承客户团队」的业务表名;不需要继承的返回 null |
| | | * |
| | | * 目前统一为:联系人、商机、合同、销售报价、回款、回款计划、开票 |
| | | */ |
| | | private static <T extends MPJLambdaWrapper<?>, S> void appendBusinessPermissionCondition(T query, SFunction<S, ?> bizId, |
| | | Long userId, String ownerUserIdField) { |
| | | // 使用子查询方式:商机团队成员 OR 客户团队成员 |
| | | // 子查询1:商机团队成员权限 |
| | | private static String getInheritCustomerTeamTable(Integer bizType) { |
| | | if (CrmBizTypeEnum.CRM_CONTACT.getType().equals(bizType)) { |
| | | return "crm_contact"; |
| | | } |
| | | if (CrmBizTypeEnum.CRM_BUSINESS.getType().equals(bizType)) { |
| | | return "crm_business"; |
| | | } |
| | | if (CrmBizTypeEnum.CRM_CONTRACT.getType().equals(bizType)) { |
| | | return "crm_contract"; |
| | | } |
| | | if (CrmBizTypeEnum.CRM_SALE_QUOTATION.getType().equals(bizType)) { |
| | | return "crm_sale_quotation"; |
| | | } |
| | | if (CrmBizTypeEnum.CRM_RECEIVABLE.getType().equals(bizType)) { |
| | | return "crm_receivable"; |
| | | } |
| | | if (CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType().equals(bizType)) { |
| | | return "crm_receivable_plan"; |
| | | } |
| | | if (CrmBizTypeEnum.CRM_INVOICE.getType().equals(bizType)) { |
| | | return "crm_invoice"; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 继承客户团队的数据权限:数据自身团队 ∪ 客户负责人/客户团队 |
| | | * |
| | | * @param query 连表查询对象 |
| | | * @param bizType 数据类型 |
| | | * @param tableName 业务表名 |
| | | * @param userId 用户编号 |
| | | * @param ownerUserIdField 负责人字段 |
| | | */ |
| | | private static <T extends MPJLambdaWrapper<?>> void appendCustomerInheritedPermissionCondition( |
| | | T query, Integer bizType, String tableName, Long userId, String ownerUserIdField) { |
| | | // 子查询1:数据自身的团队成员权限 |
| | | String subQuery1 = "(SELECT p1.biz_id FROM crm_permission p1 " + |
| | | "WHERE p1.biz_type = " + CrmBizTypeEnum.CRM_BUSINESS.getType() + " " + |
| | | "AND p1.level IN (" + CrmPermissionLevelEnum.READ.getLevel() + "," + CrmPermissionLevelEnum.WRITE.getLevel() + ") " + |
| | | "AND p1.user_id = " + userId + ")"; |
| | | // 子查询2:客户团队成员权限(通过商机的 customer_id 关联) |
| | | String subQuery2 = "(SELECT b.id FROM crm_business b " + |
| | | "INNER JOIN crm_permission p2 ON p2.biz_type = " + CrmBizTypeEnum.CRM_CUSTOMER.getType() + " " + |
| | | "AND p2.biz_id = b.customer_id " + |
| | | "AND p2.level IN (" + CrmPermissionLevelEnum.READ.getLevel() + "," + CrmPermissionLevelEnum.WRITE.getLevel() + ") " + |
| | | "AND p2.user_id = " + userId + ")"; |
| | | "WHERE p1.biz_type = " + bizType + " " + |
| | | "AND p1.level IN (" + CrmPermissionLevelEnum.OWNER.getLevel() + "," + |
| | | CrmPermissionLevelEnum.READ.getLevel() + "," + CrmPermissionLevelEnum.WRITE.getLevel() + ") " + |
| | | "AND p1.user_id = " + userId + " AND p1.deleted = 0)"; |
| | | // 子查询2:所属客户的负责人 + 团队成员 |
| | | // 注意:以 crm_customer.owner_user_id 为准,兼容权限表中负责人记录缺失/不一致的历史数据 |
| | | String subQuery2 = "(SELECT x.id FROM " + tableName + " x " + |
| | | "INNER JOIN crm_customer cu ON cu.id = x.customer_id AND cu.deleted = 0 " + |
| | | "WHERE x.deleted = 0 AND (cu.owner_user_id = " + userId + |
| | | " OR EXISTS (SELECT 1 FROM crm_permission p2 " + |
| | | "WHERE p2.biz_type = " + CrmBizTypeEnum.CRM_CUSTOMER.getType() + " " + |
| | | "AND p2.biz_id = x.customer_id AND p2.user_id = " + userId + " AND p2.deleted = 0)))"; |
| | | // 使用 OR 连接两个子查询,并排除自己是负责人的情况 |
| | | query.apply("t.id IN (" + subQuery1 + " UNION " + subQuery2 + ")") |
| | | .ne(ownerUserIdField, userId); |