Merge branch 'feature/crm' of https://gitee.com/puhui999/ruoyi-vue-pro into feature/crm

# Conflicts:
#	yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
#	yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java
#	yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java
#	yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/ContactServiceImpl.java
#	yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dept/PostConvert.java
This commit is contained in:
YunaiV 2023-11-18 22:25:13 +08:00
commit 8c9873c425
45 changed files with 756 additions and 497 deletions

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.crm.enums.customer;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* CRM 客户等级
*
* @author Wanwan
*/
@Getter
@AllArgsConstructor
public enum CrmCustomerSceneEnum implements IntArrayValuable {
OWNER(1, "我负责的客户"),
FOLLOW(2, "我关注的客户");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerSceneEnum::getType).toArray();
/**
* 场景类型
*/
private final Integer type;
/**
* 场景名称
*/
private final String name;
public static boolean isOwner(Integer type) {
return ObjUtil.equal(OWNER.getType(), type);
}
public static boolean isFollow(Integer type) {
return ObjUtil.equal(FOLLOW.getType(), type);
}
@Override
public int[] array() {
return ARRAYS;
}
}

View File

@ -21,19 +21,11 @@ public class CrmBusinessTransferReqVO {
@Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
private Long newOwnerUserId;
// TODO @puhui999joinTeam 可以合并成 permissionLevel oldOwnerPermissionLevel这样 null 说明移除因为都换负责人啦
/**
* 老负责人是否加入团队/
*/
@Schema(description = "老负责人是否加入团队", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
@NotNull(message = "老负责人是否加入团队不能为空")
private Boolean joinTeam;
/**
* 老负责人加入团队后的权限级别如果 {@link #joinTeam} false, permissionLevel null
* 老负责人加入团队后的权限级别如果 null 说明移除
* 关联 {@link CrmPermissionLevelEnum}
*/
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer permissionLevel;
private Integer oldOwnerPermissionLevel;
}

View File

@ -21,18 +21,11 @@ public class CrmContactTransferReqVO {
@Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
private Long newOwnerUserId;
// TODO @puhui999joinTeam 可以合并成 permissionLevel oldOwnerPermissionLevel这样 null 说明移除因为都换负责人啦
/**
* 老负责人是否加入团队/
*/
@Schema(description = "老负责人是否加入团队", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
@NotNull(message = "老负责人是否加入团队不能为空")
private Boolean joinTeam;
/**
* 老负责人加入团队后的权限级别如果 {@link #joinTeam} false, permissionLevel null
* 老负责人加入团队后的权限级别如果 null 说明移除
* 关联 {@link CrmPermissionLevelEnum}
*/
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer permissionLevel;
private Integer oldOwnerPermissionLevel;
}

View File

@ -21,19 +21,11 @@ public class CrmContractTransferReqVO {
@Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
private Long newOwnerUserId;
// TODO @puhui999joinTeam 可以合并成 permissionLevel oldOwnerPermissionLevel这样 null 说明移除因为都换负责人啦
/**
* 老负责人是否加入团队/
*/
@Schema(description = "老负责人是否加入团队", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
@NotNull(message = "老负责人是否加入团队不能为空")
private Boolean joinTeam;
/**
* 老负责人加入团队后的权限级别如果 {@link #joinTeam} false, permissionLevel null
* 老负责人加入团队后的权限级别如果 null 说明移除
* 关联 {@link CrmPermissionLevelEnum}
*/
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer permissionLevel;
private Integer oldOwnerPermissionLevel;
}

View File

@ -1,22 +1,21 @@
package cn.iocoder.yudao.module.crm.controller.admin.customer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
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;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
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.customer.CrmCustomerService;
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
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.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.google.common.collect.Lists;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -28,13 +27,16 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
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.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@ -51,6 +53,8 @@ public class CrmCustomerController {
private DeptApi deptApi;
@Resource
private AdminUserApi adminUserApi;
@Resource
private CrmPermissionService permissionService;
@PostMapping("/create")
@Operation(summary = "创建客户")
@ -81,22 +85,26 @@ public class CrmCustomerController {
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('crm:customer:query')")
public CommonResult<CrmCustomerRespVO> getCustomer(@RequestParam("id") Long id) {
// 1. 获取客户
CrmCustomerDO customer = customerService.getCustomer(id);
CrmCustomerRespVO customerRespVO = CrmCustomerConvert.INSTANCE.convert(customer);
if (ObjectUtil.isAllNotEmpty(customer, customer.getAreaId())) {
customerRespVO.setAreaName(AreaUtils.format(customer.getAreaId()));
if (customer == null) {
return success(null);
}
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(CollUtil.removeNull(Lists.newArrayList(NumberUtil.parseLong(customerRespVO.getCreator()), customerRespVO.getOwnerUserId())));
customerRespVO.setCreatorName(Optional.ofNullable(userMap.get(NumberUtil.parseLong(customerRespVO.getCreator()))).map(AdminUserRespDTO::getNickname).orElse(null));
AdminUserRespDTO ownerUser = userMap.get(customer.getOwnerUserId());
if (Objects.nonNull(ownerUser)) {
customerRespVO.setOwnerUserName(ownerUser.getNickname());
DeptRespDTO dept = deptApi.getDept(ownerUser.getDeptId());
if (Objects.nonNull(dept)) {
customerRespVO.setOwnerUserDept(dept.getName());
}
}
return success(customerRespVO);
// 2. 拼接数据
// 2.1 获取负责人
List<CrmPermissionDO> ownerList = permissionService.getPermissionByBizTypeAndBizIdsAndLevel(
CrmBizTypeEnum.CRM_CUSTOMER.getType(), Collections.singletonList(customer.getId()),
CrmPermissionLevelEnum.OWNER.getLevel());
Map<Long, CrmPermissionDO> ownerMap = convertMap(ownerList, CrmPermissionDO::getBizId);
// 2.2 获取负责人详情
Set<Long> userIds = convertSet(ownerList, CrmPermissionDO::getUserId);
userIds.add(Long.parseLong(customer.getCreator())); // 加入创建者
List<AdminUserRespDTO> userList = adminUserApi.getUserList(userIds);
Map<Long, AdminUserRespDTO> userMap = convertMap(userList, AdminUserRespDTO::getId);
// 2.3 获取部门详情
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
return success(CrmCustomerConvert.INSTANCE.convert(customer, ownerMap, userMap, deptMap));
}
@GetMapping("/page")
@ -113,6 +121,31 @@ public class CrmCustomerController {
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(
convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap));
return convertPage(customerService.getCustomerPage(pageVO, getLoginUserId()));
}
@GetMapping("/pool-page")
@Operation(summary = "获得公海客户分页")
@PreAuthorize("@ss.hasPermission('crm:customer:query')")
public CommonResult<PageResult<CrmCustomerRespVO>> getPoolCustomerPage(@Valid CrmCustomerPageReqVO pageVO) {
return convertPage(customerService.getCustomerPage(pageVO, CrmPermissionDO.POOL_USER_ID));
}
private CommonResult<PageResult<CrmCustomerRespVO>> convertPage(PageResult<CrmCustomerDO> pageResult) {
// 2. 拼接数据
Set<Long> ids = convertSet(pageResult.getList(), CrmCustomerDO::getId);
// 2.1 获取负责人
List<CrmPermissionDO> ownerList = permissionService.getPermissionByBizTypeAndBizIdsAndLevel(
CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, CrmPermissionLevelEnum.OWNER.getLevel());
Map<Long, CrmPermissionDO> ownerMap = convertMap(ownerList, CrmPermissionDO::getBizId);
// 2.2 获取负责人详情
Set<Long> userIds = convertSet(ownerList, CrmPermissionDO::getUserId);
userIds.addAll(convertSet(pageResult.getList(), item -> Long.parseLong(item.getCreator()))); // 加入创建者
List<AdminUserRespDTO> userList = adminUserApi.getUserList(userIds);
Map<Long, AdminUserRespDTO> userMap = convertMap(userList, AdminUserRespDTO::getId);
// 2.3 获取部门详情
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, ownerMap, userMap, deptMap));
}
@GetMapping("/export-excel")

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerSceneEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -27,5 +28,10 @@ public class CrmCustomerPageReqVO extends PageParam {
@Schema(description = "客户来源", example = "1")
private Integer source;
// TODO @芋艿场景
/**
* 场景类型关联 {@link CrmCustomerSceneEnum}
*/
@Schema(description = "场景类型", example = "1")
private Integer sceneType;
}

View File

@ -33,7 +33,7 @@ public class CrmCustomerRespVO extends CrmCustomerBaseVO {
@Schema(description = "负责人名字", example = "25682")
private String ownerUserName;
@Schema(description = "负责人部门")
private String ownerUserDept;
private String ownerUserDeptName;
@Schema(description = "地区名称", example = "北京市")
private String areaName;

View File

@ -21,19 +21,11 @@ public class CrmCustomerTransferReqVO {
@Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
private Long newOwnerUserId;
// TODO @puhui999joinTeam 可以合并成 permissionLevel oldOwnerPermissionLevel这样 null 说明移除因为都换负责人啦
/**
* 老负责人是否加入团队/
*/
@Schema(description = "老负责人是否加入团队", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
@NotNull(message = "老负责人是否加入团队不能为空")
private Boolean joinTeam;
/**
* 老负责人加入团队后的权限级别如果 {@link #joinTeam} false, permissionLevel null
* 老负责人加入团队后的权限级别如果 null 说明移除
* 关联 {@link CrmPermissionLevelEnum}
*/
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer permissionLevel;
private Integer oldOwnerPermissionLevel;
}

View File

@ -0,0 +1,32 @@
### 请求 /add
PUT {{baseUrl}}/crm/permission/add
Content-Type: application/json
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
{
"userId": 1,
"bizType": 2,
"bizId": 2,
"level": 1
}
### 请求 /update
PUT {{baseUrl}}/crm/permission/update
Content-Type: application/json
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
{
"userId": 1,
"bizType": 2,
"bizId": 2,
"level": 1,
"id": 1
}
### 请求 /delete
DELETE {{baseUrl}}/crm/permission/delete?bizType=2&bizId=1&id=1
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}

View File

@ -8,8 +8,14 @@ import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionR
import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO;
import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.framework.core.service.CrmPermissionValidateService;
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 cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.PostApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import io.swagger.v3.oas.annotations.Operation;
@ -22,17 +28,16 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Collections;
import java.util.List;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_MODEL_NOT_EXISTS;
import static cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum.getNameByType;
import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum.isOwner;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_NOT_EXISTS;
@Tag(name = "管理后台 - CRM 数据权限(数据团队成员操作)")
@RestController
@ -41,92 +46,85 @@ import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum
public class CrmPermissionController {
@Resource
private CrmPermissionService crmPermissionService;
private CrmPermissionService permissionService;
@Resource
private AdminUserApi adminUserApi;
@Resource
private List<CrmPermissionValidateService> permissionValidateServices;
// TODO @puhui999这个能不能使用 CrmPermission 注解替代
private void validatePermission(Integer bizType, Long bizId) {
// 1. TODO 校验是否为超级管理员
// 2. 防御一手如果是超级管理员不校验权限还是得校验一下数据是否存在
// TODO @puhui999是不是不用校验每个业务方的数据是否存在其实不是很关键哈简单一点~ 说白了负责人只要在它的数据就是存在~
permissionValidateServices.forEach(item -> {
if (!item.validateBizIdExists(bizType, bizId)) {
throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, getNameByType(bizType));
}
});
// 3. 校验数据权限 如果存在则表示 bizId 也存在
CrmPermissionDO permission = crmPermissionService.getPermissionByBizTypeAndBizIdAndUserId(
bizType, bizId, getLoginUserId());
if (isOwner(permission.getPermissionLevel())) { // 只有负责人才可以操作团队成员
return;
}
throw exception(CRM_PERMISSION_DENIED, getNameByType(bizType));
}
private DeptApi deptApi;
@Resource
private PostApi postApi;
@PutMapping("/add")
@Operation(summary = "添加团队成员")
@PreAuthorize("@ss.hasPermission('crm:permission:create')")
@CrmPermission(bizType = CrmBizTypeEnum.CRM_PERMISSION, bizTypeValue = "#reqVO.bizType", bizId = "#reqVO.bizId"
, level = CrmPermissionLevelEnum.OWNER)
public CommonResult<Boolean> addPermission(@Valid @RequestBody CrmPermissionCreateReqVO reqVO) {
// 1. 前置校验
validatePermission(reqVO.getBizType(), reqVO.getBizId());
// 2. 加入成员
crmPermissionService.createPermission(CrmPermissionConvert.INSTANCE.convert(reqVO));
permissionService.createPermission(CrmPermissionConvert.INSTANCE.convert(reqVO));
return success(true);
}
@PutMapping("/receive")
@Operation(summary = "领取公海数据")
@PreAuthorize("@ss.hasPermission('crm:permission:update')")
public CommonResult<Boolean> receive(@RequestParam("bizType") Integer bizType, @RequestParam("bizId") Long bizId) {
permissionService.receiveBiz(bizType, bizId, getLoginUserId());
return success(true);
}
@PutMapping("/put-pool")
@Operation(summary = "数据放入公海")
@PreAuthorize("@ss.hasPermission('crm:permission:update')")
@CrmPermission(bizType = CrmBizTypeEnum.CRM_PERMISSION, bizTypeValue = "#bizType", bizId = "#bizId"
, level = CrmPermissionLevelEnum.OWNER)
public CommonResult<Boolean> putPool(@RequestParam(value = "bizType") Integer bizType, @RequestParam("bizId") Long bizId) {
permissionService.putPool(bizType, bizId, getLoginUserId());
return success(true);
}
@PutMapping("/update")
@Operation(summary = "编辑团队成员")
@Operation(summary = "编辑团队成员权限")
@PreAuthorize("@ss.hasPermission('crm:permission:update')")
@CrmPermission(bizType = CrmBizTypeEnum.CRM_PERMISSION, bizTypeValue = "#updateReqVO.bizType", bizId = "#updateReqVO.bizId"
, level = CrmPermissionLevelEnum.OWNER)
public CommonResult<Boolean> updatePermission(@Valid @RequestBody CrmPermissionUpdateReqVO updateReqVO) {
// 1. 前置校验
validatePermission(updateReqVO.getBizType(), updateReqVO.getBizId());
// 2. 编辑团队成员
crmPermissionService.updatePermission(CrmPermissionConvert.INSTANCE.convert(updateReqVO));
permissionService.updatePermission(updateReqVO);
return success(true);
}
// TODO @puhui999deletemapping
@GetMapping("/delete")
@DeleteMapping("/delete")
@Operation(summary = "移除团队成员")
@Parameter(name = "id", description = "团队成员编号", required = true)
// TODO @puhui999是不是 id 参数就够了
@PreAuthorize("@ss.hasPermission('crm:permission:delete')")
public CommonResult<Boolean> deletePermission(@RequestParam("bizType") Integer bizType,
@RequestParam("bizId") Long bizId,
@RequestParam("id") Long id) {
// 1. 前置校验
validatePermission(bizType, bizId);
// 2. 移除团队成员
crmPermissionService.deletePermission(id);
return success(true);
}
// TODO @puhui999这个是哪个地方使用到哈
// TODO @puhui999是不是 deletemapping
@GetMapping("/quit")
@Operation(summary = "退出团队")
@Parameters({
@Parameter(name = "bizType", description = "CRM 类型", required = true, example = "2"),
@Parameter(name = "bizId", description = "CRM 类型数据编号", required = true, example = "1024")
@Parameter(name = "bizId", description = "CRM 类型数据编号", required = true, example = "1024"),
@Parameter(name = "ids", description = "团队成员编号", required = true, example = "1024")
})
@PreAuthorize("@ss.hasPermission('crm:permission:delete')")
public CommonResult<Boolean> quitPermission(@RequestParam("bizType") Integer bizType,
@RequestParam("bizId") Long bizId) {
// 没有就不是团队成员
CrmPermissionDO permission = crmPermissionService.getPermissionByBizTypeAndBizIdAndUserId(
bizType, bizId, getLoginUserId());
@CrmPermission(bizType = CrmBizTypeEnum.CRM_PERMISSION, bizTypeValue = "#bizType", bizId = "#bizId"
, level = CrmPermissionLevelEnum.OWNER) // 为了校验权限请求必须带上 bizType bizId
public CommonResult<Boolean> deletePermission(@RequestParam("bizType") Integer bizType,
@RequestParam("bizId") Long bizId,
@RequestParam("ids") Collection<Long> ids) {
permissionService.deletePermission(ids);
return success(true);
}
@DeleteMapping("/quit-team")
@Operation(summary = "退出团队")
@Parameters({
@Parameter(name = "id", description = "团队成员编号", required = true, example = "1024")
})
@PreAuthorize("@ss.hasPermission('crm:permission:delete')")
public CommonResult<Boolean> deletePermission(@RequestParam("id") Long id) {
// 校验数据存在且是自己
CrmPermissionDO permission = permissionService.getPermissionByIdAndUserId(id, getLoginUserId());
if (permission == null) {
return success(false);
throw exception(CRM_PERMISSION_NOT_EXISTS);
}
crmPermissionService.deletePermission(permission.getId());
// 删除
permissionService.deletePermission(Collections.singletonList(id));
return success(true);
}
@ -139,16 +137,23 @@ public class CrmPermissionController {
@PreAuthorize("@ss.hasPermission('crm:permission:query')")
public CommonResult<List<CrmPermissionRespVO>> getPermissionList(@RequestParam("bizType") Integer bizType,
@RequestParam("bizId") Long bizId) {
List<CrmPermissionDO> permission = crmPermissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
List<CrmPermissionDO> permission = permissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
if (CollUtil.isEmpty(permission)) {
return success(Collections.emptyList());
}
// TODO @puhui999池子的逻辑
permission.removeIf(item -> ObjUtil.equal(item.getUserId(), CrmPermissionDO.POOL_USER_ID)); // 排除
// 判断是否是公海数据
Predicate<CrmPermissionDO> filter = item -> ObjUtil.equal(item.getUserId(), CrmPermissionDO.POOL_USER_ID);
if (anyMatch(permission, filter)) {
permission.removeIf(filter); // 排除
}
// 拼接数据
List<AdminUserRespDTO> userList = adminUserApi.getUserList(convertSet(permission, CrmPermissionDO::getUserId));
return success(CrmPermissionConvert.INSTANCE.convert(permission, userList));
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
Set<Long> postIds = userList.stream().flatMap(item -> item.getPostIds().stream()).collect(Collectors.toSet());
Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds);
return success(CrmPermissionConvert.INSTANCE.convert(permission, userList, deptMap, postMap));
}
}

View File

@ -30,10 +30,9 @@ public class CrmPermissionBaseVO {
@NotNull(message = "Crm 类型数据编号不能为空")
private Long bizId;
// TODO @puhui999level
@Schema(description = "权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@InEnum(CrmPermissionLevelEnum.class)
@NotNull(message = "权限级别不能为空")
private Integer permissionLevel;
private Integer level;
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.permission.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Set;
@Schema(description = "管理后台 - CRM 数据权限(团队成员) Response VO")
@ -12,18 +13,16 @@ public class CrmPermissionRespVO extends CrmPermissionBaseVO {
@Schema(description = "数据权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
private Long id;
// TODO @puhui999搞到字典里
@Schema(description = "团队级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "负责人")
private String permissionLevelName;
// TODO @puhui999deptIdpostIds 是不是要提供中文名哈
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long deptId;
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部")
private String deptName;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
private String nickname;
@Schema(description = "岗位编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,2,3]")
private Set<Long> postIds;
@Schema(description = "岗位名称数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[BOOS,经理]")
private Set<String> postNames;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-01-01 00:00:00")
private LocalDateTime createTime;
}

View File

@ -1,20 +1,34 @@
package cn.iocoder.yudao.module.crm.controller.admin.permission.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.List;
@Schema(description = "管理后台 - CRM 数据权限更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CrmPermissionUpdateReqVO extends CrmPermissionBaseVO {
public class CrmPermissionUpdateReqVO {
@Schema(description = "数据权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
// TODO @puhui999非空判断
private Long id;
@Schema(description = "数据权限编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,2]")
@NotNull(message = "数据权限编号列表不能为空")
private List<Long> ids;
// TODO @puhui999是不是只更新 permission
@Schema(description = "Crm 类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@InEnum(CrmBizTypeEnum.class)
@NotNull(message = "Crm 类型不能为空")
private Integer bizType;
@Schema(description = "Crm 类型数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "Crm 类型数据编号不能为空")
private Long bizId;
@Schema(description = "权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@InEnum(CrmPermissionLevelEnum.class)
@NotNull(message = "权限级别不能为空")
private Integer level;
}

View File

@ -3,8 +3,7 @@ package cn.iocoder.yudao.module.crm.convert.business;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionPageReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
@ -36,8 +35,6 @@ public interface CrmBusinessConvert {
@Mapping(target = "bizId", source = "reqVO.id"),
@Mapping(target = "newOwnerUserId", source = "reqVO.id")
})
CrmTransferPermissionReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId);
CrmPermissionPageReqBO convert(CrmBusinessPageReqVO pageReqVO);
CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId);
}

View File

@ -4,6 +4,9 @@ import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
@ -30,6 +33,13 @@ public interface ContactConvert {
PageResult<ContactRespVO> convertPage(PageResult<ContactDO> page);
List<ContactExcelVO> convertList02(List<ContactDO> list);
List<ContactSimpleRespVO> convertAllList(List<ContactDO> list);
@Mappings({
@Mapping(target = "bizId", source = "reqVO.id"),
@Mapping(target = "newOwnerUserId", source = "reqVO.id")
})
CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId);
}

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.crm.convert.contract;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
@ -37,6 +37,6 @@ public interface ContractConvert {
@Mapping(target = "bizId", source = "reqVO.id"),
@Mapping(target = "newOwnerUserId", source = "reqVO.id")
})
CrmTransferPermissionReqBO convert(CrmContractTransferReqVO reqVO, Long userId);
CrmPermissionTransferReqBO convert(CrmContractTransferReqVO reqVO, Long userId);
}

View File

@ -4,12 +4,17 @@ import cn.hutool.core.util.NumberUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
@ -18,6 +23,9 @@ import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
import java.util.Map;
/**
* 客户 Convert
*
@ -34,7 +42,24 @@ public interface CrmCustomerConvert {
CrmCustomerRespVO convert(CrmCustomerDO bean);
PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> page);
default CrmCustomerRespVO convert(CrmCustomerDO customer, Map<Long, CrmPermissionDO> ownerMap,
Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
CrmCustomerRespVO customerResp = convert(customer);
findAndThen(ownerMap, customerResp.getId(), owner -> {
customerResp.setOwnerUserId(owner.getUserId());
customerResp.setAreaName(AreaUtils.format(customerResp.getAreaId()));
findAndThen(userMap, owner.getUserId(), user -> {
customerResp.setOwnerUserName(user.getNickname());
});
findAndThen(userMap, Long.parseLong(customerResp.getCreator()), user -> {
customerResp.setCreatorName(user.getNickname());
});
findAndThen(deptMap, customerResp.getOwnerUserId(), dept -> {
customerResp.setOwnerUserDeptName(dept.getName());
});
});
return customerResp;
}
default PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> page, Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
PageResult<CrmCustomerRespVO> result = convertPage(page);
@ -57,7 +82,30 @@ public interface CrmCustomerConvert {
@Mapping(target = "bizId", source = "reqVO.id"),
@Mapping(target = "newOwnerUserId", source = "reqVO.id")
})
CrmTransferPermissionReqBO convert(CrmCustomerTransferReqVO reqVO, Long userId);
CrmPermissionTransferReqBO convert(CrmCustomerTransferReqVO reqVO, Long userId);
PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> page);
default PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> pageResult, Map<Long, CrmPermissionDO> ownerMap,
Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
PageResult<CrmCustomerRespVO> result = convertPage(pageResult);
result.getList().forEach(item -> {
findAndThen(ownerMap, item.getId(), owner -> {
item.setOwnerUserId(owner.getUserId());
item.setAreaName(AreaUtils.format(item.getAreaId()));
findAndThen(userMap, owner.getUserId(), user -> {
item.setOwnerUserName(user.getNickname());
});
findAndThen(userMap, Long.parseLong(item.getCreator()), user -> {
item.setCreatorName(user.getNickname());
});
findAndThen(deptMap, item.getOwnerUserId(), dept -> {
item.setOwnerUserDeptName(dept.getName());
});
});
});
return result;
}
CrmCustomerPoolConfigRespVO convert(CrmCustomerPoolConfigDO customerPoolConfig);

View File

@ -8,15 +8,17 @@ import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionU
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateReqBO;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.google.common.collect.Multimaps;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum.getNameByLevel;
/**
* Crm 数据权限 Convert
*
@ -37,15 +39,28 @@ public interface CrmPermissionConvert {
List<CrmPermissionRespVO> convert(List<CrmPermissionDO> permission);
default List<CrmPermissionRespVO> convert(List<CrmPermissionDO> permission, List<AdminUserRespDTO> userList) {
default List<CrmPermissionRespVO> convert(List<CrmPermissionDO> permission, List<AdminUserRespDTO> userList,
Map<Long, DeptRespDTO> deptMap, Map<Long, PostRespDTO> postMap) {
Map<Long, AdminUserRespDTO> userMap = CollectionUtils.convertMap(userList, AdminUserRespDTO::getId);
return CollectionUtils.convertList(convert(permission), item -> {
MapUtils.findAndThen(userMap, item.getId(), user -> {
item.setNickname(user.getNickname()).setDeptId(user.getDeptId()).setPostIds(user.getPostIds())
.setPermissionLevelName(getNameByLevel(item.getPermissionLevel()));
item.setNickname(user.getNickname());
MapUtils.findAndThen(deptMap, user.getDeptId(), deptRespDTO -> {
item.setDeptName(deptRespDTO.getName());
});
List<PostRespDTO> postRespList = MapUtils.getList(Multimaps.forMap(postMap), user.getPostIds());
item.setPostNames(CollectionUtils.convertSet(postRespList, PostRespDTO::getName));
});
return item;
});
}
default List<CrmPermissionDO> convertList(CrmPermissionUpdateReqVO updateReqVO) {
List<CrmPermissionDO> permissions = new ArrayList<>();
updateReqVO.getIds().forEach(id -> {
permissions.add(new CrmPermissionDO().setId(id).setLevel(updateReqVO.getLevel()));
});
return permissions;
}
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.crm.dal.dataobject.customer;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@ -49,19 +50,19 @@ public class CrmCustomerDO extends BaseDO {
/**
* 所属行业
*
* 对应字典 {@link cn.iocoder.yudao.module.crm.enums.DictTypeConstants#CRM_CUSTOMER_INDUSTRY}
* 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY}
*/
private Integer industryId;
/**
* 客户等级
*
* 对应字典 {@link cn.iocoder.yudao.module.crm.enums.DictTypeConstants#CRM_CUSTOMER_LEVEL}
* 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL}
*/
private Integer level;
/**
* 客户来源
*
* 对应字典 {@link cn.iocoder.yudao.module.crm.enums.DictTypeConstants#CRM_CUSTOMER_SOURCE}
* 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE}
*/
private Integer source;
/**
@ -96,21 +97,6 @@ public class CrmCustomerDO extends BaseDO {
* 备注
*/
private String remark;
/**
* 负责人的用户编号
*
* 关联 AdminUserDO id 字段
*/
private Long ownerUserId;
// TODO @puhui999这块抽到 permission
/**
* 只读权限的用户编号数组
*/
private String roUserIds;
/**
* 读写权限的用户编号数组
*/
private String rwUserIds;
/**
* 地区编号
*/

View File

@ -23,7 +23,7 @@ import lombok.*;
@AllArgsConstructor
public class CrmPermissionDO extends BaseDO {
// TODO puhui999是不是公海的数据就不插入了
// TODO puhui999是不是公海的数据就不插入了这样方便获取公海数据鸭
/**
* 当数据变为公海数据时也就是数据团队成员中没有负责人的时候将原本的负责人 userId 设置为 POOL_USER_ID 方便查询公海数据
* 也就是说每条数据到最后都有一个负责人如果有人领取则 userId 为领取人
@ -59,12 +59,11 @@ public class CrmPermissionDO extends BaseDO {
*/
private Long userId;
// TODO @puhui999是不是搞成 level 字段简洁一点主要表明已经 perssmion 实体里了
/**
* 权限级别
*
* 关联 {@link CrmPermissionLevelEnum}
*/
private Integer permissionLevel;
private Integer level;
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.crm.dal.mysql.business;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.CrmBusinessExportReqVO;
@ -18,14 +19,14 @@ import java.util.List;
@Mapper
public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> {
default List<CrmBusinessDO> selectList(CrmBusinessPageReqVO reqVO, Collection<Long> ids) {
return selectList(new LambdaQueryWrapperX<CrmBusinessDO>()
default PageResult<CrmBusinessDO> selectPage(CrmBusinessPageReqVO reqVO, Collection<Long> ids) {
return selectPage(reqVO, new LambdaQueryWrapperX<CrmBusinessDO>()
.in(CrmBusinessDO::getId, ids)
.likeIfPresent(CrmBusinessDO::getName, reqVO.getName())
.orderByDesc(CrmBusinessDO::getId));
}
default List<CrmBusinessDO> selectList(CrmBusinessExportReqVO reqVO) {
default List<CrmBusinessDO> selectPage(CrmBusinessExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<CrmBusinessDO>()
.likeIfPresent(CrmBusinessDO::getName, reqVO.getName())
.eqIfPresent(CrmBusinessDO::getStatusTypeId, reqVO.getStatusTypeId())

View File

@ -3,12 +3,11 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerExportReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Collection;
/**
* 客户 Mapper
@ -18,21 +17,14 @@ import java.util.List;
@Mapper
public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<CrmCustomerDO>()
.likeIfPresent(CrmCustomerDO::getName, reqVO.getName())
.eqIfPresent(CrmCustomerDO::getMobile, reqVO.getMobile())
.eqIfPresent(CrmCustomerDO::getIndustryId, reqVO.getIndustryId())
.eqIfPresent(CrmCustomerDO::getLevel, reqVO.getLevel())
.eqIfPresent(CrmCustomerDO::getSource, reqVO.getSource())
.orderByDesc(CrmCustomerDO::getId));
}
default List<CrmCustomerDO> selectList(CrmCustomerExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<CrmCustomerDO>()
.likeIfPresent(CrmCustomerDO::getName, reqVO.getName())
.eqIfPresent(CrmCustomerDO::getMobile, reqVO.getMobile())
.orderByDesc(CrmCustomerDO::getId));
default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Collection<Long> ids) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<CrmCustomerDO>()
.inIfPresent(CrmCustomerDO::getId, ids)
.likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName())
.eqIfPresent(CrmCustomerDO::getMobile, pageReqVO.getMobile())
.eqIfPresent(CrmCustomerDO::getIndustryId, pageReqVO.getIndustryId())
.eqIfPresent(CrmCustomerDO::getLevel, pageReqVO.getLevel())
.eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource()));
}
}

View File

@ -1,13 +1,11 @@
package cn.iocoder.yudao.module.crm.dal.mysql.permission;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionPageReqBO;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
/**
@ -18,15 +16,6 @@ import java.util.List;
@Mapper
public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> {
// TODO @puhui999是不是不用谢这个注释因为方法名可以自解释
/**
* 获取用户数据权限通过 数据类型 x 某个数据 x 用户编号
*
* @param bizType 数据类型关联 {@link CrmBizTypeEnum}
* @param bizId 数据编号关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
* @param userId 用户编号AdminUser#id
* @return Crm 数据权限
*/
default CrmPermissionDO selectByBizTypeAndBizIdByUserId(Integer bizType, Long bizId, Long userId) {
return selectOne(new LambdaQueryWrapperX<CrmPermissionDO>()
.eq(CrmPermissionDO::getBizType, bizType)
@ -34,24 +23,28 @@ public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> {
.eq(CrmPermissionDO::getUserId, userId));
}
// TODO @puhui999是不是不用谢这个注释因为方法名可以自解释
/**
* 获取数据权限列表通过 数据类型 x 某个数据
*
* @param bizType 数据类型关联 {@link CrmBizTypeEnum}
* @param bizId 数据编号关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
* @return Crm 数据权限列表
*/
default List<CrmPermissionDO> selectByBizTypeAndBizId(Integer bizType, Long bizId) {
return selectList(new LambdaQueryWrapperX<CrmPermissionDO>()
.eq(CrmPermissionDO::getBizType, bizType)
.eq(CrmPermissionDO::getBizId, bizId));
}
default PageResult<CrmPermissionDO> selectPage(CrmPermissionPageReqBO pageReqBO) {
return selectPage(pageReqBO, new LambdaQueryWrapperX<CrmPermissionDO>()
.eq(CrmPermissionDO::getBizType, pageReqBO.getBizType())
.eq(CrmPermissionDO::getUserId, pageReqBO.getUserId())); // 只要是团队成员都有读取的权限
default List<CrmPermissionDO> selectListByBizTypeAndUserId(Integer bizType, Long userId) {
return selectList(new LambdaQueryWrapperX<CrmPermissionDO>()
.eq(CrmPermissionDO::getBizType, bizType)
.eq(CrmPermissionDO::getUserId, userId));
}
default List<CrmPermissionDO> selectListByBizTypeAndBizIdsAndLevel(Integer bizType, Collection<Long> bizIds, Integer level) {
return selectList(new LambdaQueryWrapperX<CrmPermissionDO>()
.eq(CrmPermissionDO::getBizType, bizType)
.in(CrmPermissionDO::getBizId, bizIds)
.eq(CrmPermissionDO::getLevel, level));
}
default CrmPermissionDO selectByIdAndUserId(Long id, Long userId) {
return selectOne(new LambdaQueryWrapperX<CrmPermissionDO>()
.eq(CrmPermissionDO::getId, id).eq(CrmPermissionDO::getUserId, userId));
}
}

View File

@ -26,17 +26,21 @@ public @interface CrmPermission {
*/
CrmBizTypeEnum bizType();
// TODO @puhui999id通过 spring el 表达式获取
/**
* 数据编号获取来源类确保数据 id 编号在此类中不能在父类中
* 如果在 baseVO 中需要把 id 弄到 updateVO
* crm 类型扩展
* 用于 CrmPermissionController 团队权限校验
*/
Class<?>[] getIdFor() default {};
String bizTypeValue() default "";
// TODO @puhui999是不是搞成 level 字段简洁一点主要表明已经 perssmion 实体里了
/**
* 操作类型
* 数据编号通过 spring el 表达式获取
* TODO 数据权限完成后去除 default ""
*/
CrmPermissionLevelEnum permissionLevel();
String bizId() default "";
/**
* 操作所需权限级别
*/
CrmPermissionLevelEnum level();
}

View File

@ -2,24 +2,32 @@ package cn.iocoder.yudao.module.crm.framework.core.aop;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue;
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;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED;
import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum.*;
/**
* Crm 数据权限校验 AOP 切面
@ -31,6 +39,11 @@ import static cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum
@Slf4j
public class CrmPermissionAspect {
@Resource
private LocalVariableTableParameterNameDiscoverer discoverer;
@Resource
private SpelExpressionParser parser;
@Resource
private CrmPermissionService crmPermissionService;
@ -43,83 +56,109 @@ public class CrmPermissionAspect {
return WebFrameworkUtils.getLoginUserId();
}
// TODO @puhui999id通过 spring el 表达式获取
private Long getBizId(JoinPoint joinPoint, CrmPermission crmPermission) throws NoSuchFieldException, IllegalAccessException {
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
if (arg == null) {
continue;
}
if (ObjUtil.notEqual(arg.getClass().getName(), crmPermission.getIdFor()[0].getName())) {
continue;
}
// 使用反射获取id属性
Field idValue = arg.getClass().getDeclaredField("id");
// 设置字段为可访问
idValue.setAccessible(true);
return (Long) idValue.get(arg);
}
return null;
}
// TODO @puhui999一般核心的方法放到最前面private 放后面主要是主次要分出来哈
@Before("@annotation(crmPermission)")
public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) {
public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) throws NoSuchMethodException {
// TODO 芋艿临时方便大家调试
if (true) {
return;
}
try {
Long bizId = crmPermission.getIdFor().length > 0 ? getBizId(joinPoint, crmPermission) : (Long) joinPoint.getArgs()[0]; // 获取操作数据的编号
Integer bizType = crmPermission.bizType().getType(); // 模块类型
Integer permissionLevel = crmPermission.permissionLevel().getLevel(); // 需要的权限级别
KeyValue<Long, Integer> bizIdAndBizType = getBizIdAndBizType(joinPoint, crmPermission);
Integer bizType = bizIdAndBizType.getValue(); // 模块类型
Long bizId = bizIdAndBizType.getKey(); // 模块数据编号
Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别
// TODO 如果是超级管理员则直接通过
//if (superAdmin){
// return;
//}
// TODO 如果是超级管理员则直接通过
//if (superAdmin){
// return;
//}
// 1. 获取数据权限
List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
// TODO puhui999这种情况下最好是 CrmPermissionLevelEnum.isOwner
// 2.1 情况一如果自己是负责人则默认有所有权限
// TODO @puhui999会不会存在空指针的问题
CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, item -> ObjUtil.equal(item.getUserId(), getUserId()));
if (isOwner(userPermission.getPermissionLevel())) {
// 1. 获取数据权限
List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
// 2.1 情况一如果自己是负责人则默认有所有权限
// TODO @puhui999会不会存在空指针的问题
CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, item -> ObjUtil.equal(item.getUserId(), getUserId()));
if (CrmPermissionLevelEnum.isOwner(userPermission.getLevel())) {
return;
}
// 2.2 情况二校验自己是否有读权限
if (CrmPermissionLevelEnum.isRead(permissionLevel)) {
// 如果没有数据权限或没有负责人则表示此记录为公海数据所有人都有只读权限可以领取成为负责人团队成员领取的
// TODO @puhui99989 92 这块的逻辑感觉可以不用 @CrmPermission公海那自己 check 即可
if (CollUtil.isEmpty(bizPermissions) || CollUtil.anyMatch(bizPermissions,
item -> ObjUtil.equal(item.getUserId(), CrmPermissionDO.POOL_USER_ID))) { // 详见 CrmPermissionDO.POOL_USER_ID 注释
return;
}
// 2.2 情况二校验自己是否有读权限
if (isRead(permissionLevel)) {
// 如果没有数据权限或没有负责人则表示此记录为公海数据所有人都有只读权限可以领取成为负责人团队成员领取的
// TODO @puhui99989 92 这块的逻辑感觉可以不用 @CrmPermission公海那自己 check 即可
if (CollUtil.isEmpty(bizPermissions) || CollUtil.anyMatch(bizPermissions,
item -> ObjUtil.equal(item.getUserId(), CrmPermissionDO.POOL_USER_ID))) { // 详见 CrmPermissionDO.POOL_USER_ID 注释
return;
}
if (isRead(userPermission.getPermissionLevel())) { // 校验当前用户是否有读权限
return;
}
// 如果查询数据的话拥有写权限的也能查询
if (isWrite(userPermission.getPermissionLevel())) { // 校验当前用户是否有写权限
return;
}
if (CrmPermissionLevelEnum.isRead(userPermission.getLevel())) { // 校验当前用户是否有读权限
return;
}
// 2.3 情况三校验自己是否有写权限
if (isWrite(permissionLevel)) {
if (isWrite(userPermission.getPermissionLevel())) { // 校验当前用户是否有写权限
return;
}
// 如果查询数据的话拥有写权限的也能查询
if (CrmPermissionLevelEnum.isWrite(userPermission.getLevel())) { // 校验当前用户是否有写权限
return;
}
// 3. 没通过结束报错 {} 操作失败原因没有权限
// TODO @puhui999这里打个 info 日志方便后续排查问题审计
throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType().getName());
} catch (Exception ex) {
// TODO @puhui999不用 catch 就是系统异常
log.error("[doBefore][crmPermission({}) 数据校验错误]", toJsonString(crmPermission), ex);
// TODO 报错抛个什么异常好呢
throw exception(CRM_PERMISSION_DENIED, crmPermission.bizType().getName());
}
// 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().getName());
}
private KeyValue<Long, Integer> getBizIdAndBizType(JoinPoint joinPoint, CrmPermission crmPermission) throws NoSuchMethodException {
Method method = getMethod(joinPoint);
// 1. 获取方法的参数值
Object[] args = joinPoint.getArgs();
EvaluationContext context = bindParam(method, args);
// 2. 根据spel表达式获取值
KeyValue<Long, Integer> keyValue = new KeyValue<>();
// 2.1 获取模块数据编号
Expression expression = parser.parseExpression(crmPermission.bizId());
keyValue.setKey(expression.getValue(context, Long.class));
// 2.2 获取模块类型
if (ObjUtil.equal(crmPermission.bizType().getType(), CrmBizTypeEnum.CRM_PERMISSION.getType())) {
// 情况一用于 CrmPermissionController 中数据权限校验
Expression expression2 = parser.parseExpression(crmPermission.bizTypeValue());
keyValue.setValue(expression2.getValue(context, Integer.class));
return keyValue;
}
// 情况二正常数据权限校验
keyValue.setValue(crmPermission.bizType().getType());
return keyValue;
}
/**
* 获取当前执行的方法
*/
private Method getMethod(JoinPoint joinPoint) throws NoSuchMethodException {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
return joinPoint.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes());
}
/**
* 将方法的参数名和参数值绑定
*
* @param method 方法根据方法获取参数名
* @param args 方法的参数值
* @return 求值上下文
*/
private EvaluationContext bindParam(Method method, Object[] args) {
//获取方法的参数名
String[] params = discoverer.getParameterNames(method);
//将参数名与参数值对应起来
EvaluationContext context = new StandardEvaluationContext();
if (params != null) {
for (int len = 0; len < params.length; len++) {
context.setVariable(params[len], args[len]);
}
}
return context;
}
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.crm.framework.core.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
/**
* 注册 Spel 所需 Bean
*
* @author HUIHUI
*/
@Configuration
public class SpelConfig {
@Bean
public SpelExpressionParser spelExpressionParser() {
return new SpelExpressionParser();
}
}

View File

@ -1,20 +0,0 @@
package cn.iocoder.yudao.module.crm.framework.core.service;
/**
* 校验数据是否存在 service 接口
* TODO 需要使用团队成员相关操作的业务接口都需要继承此接口
*
* @author HUIHUI
*/
public interface CrmPermissionValidateService {
/**
* 校验数据是否存在
*
* @param bizType CRM 类型
* @param bizId 数据编号
* @return /
*/
boolean validateBizIdExists(Integer bizType, Long bizId);
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.crm.framework.enums;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.Getter;
@ -16,6 +17,7 @@ import java.util.Arrays;
@Getter
public enum CrmBizTypeEnum implements IntArrayValuable {
CRM_PERMISSION(0, "团队"), // CrmPermissionController 中使用
CRM_LEADS(1, "线索"),
CRM_CUSTOMER(2, "客户"),
CRM_CONTACTS(3, "联系人"),
@ -33,13 +35,9 @@ public enum CrmBizTypeEnum implements IntArrayValuable {
private final String name;
public static String getNameByType(Integer type) {
// TODO @puhui999可以 findone更简洁另外不存在返回 null 即可啦
for (CrmBizTypeEnum crmBizTypeEnum : CrmBizTypeEnum.values()) {
if (ObjUtil.equal(crmBizTypeEnum.type, type)) {
return crmBizTypeEnum.name;
}
}
return "";
CrmBizTypeEnum typeEnum = CollUtil.findOne(CollUtil.newArrayList(CrmBizTypeEnum.values()),
item -> ObjUtil.equal(item.type, type));
return typeEnum == null ? null : typeEnum.getName();
}
@Override

View File

@ -48,14 +48,4 @@ public enum CrmPermissionLevelEnum implements IntArrayValuable {
return ObjUtil.equal(WRITE.level, level);
}
public static String getNameByLevel(Integer level) {
// TODO @puhui999可以 findone更简洁另外不存在返回 null 即可啦
for (CrmPermissionLevelEnum levelEnum : CrmPermissionLevelEnum.values()) {
if (ObjUtil.equal(levelEnum.level, level)) {
return levelEnum.name;
}
}
return "";
}
}

View File

@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.crm.service.business;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
import cn.iocoder.yudao.module.crm.framework.core.service.CrmPermissionValidateService;
import javax.validation.Valid;
import java.util.Collection;
@ -14,7 +13,7 @@ import java.util.List;
*
* @author ljlleo
*/
public interface CrmBusinessService extends CrmPermissionValidateService {
public interface CrmBusinessService {
/**
* 创建商机

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.crm.service.business;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*;
import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
@ -51,7 +50,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
// 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
.setBizId(business.getId()).setUserId(userId).setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
.setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
// 返回
return business.getId();
@ -59,8 +58,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, getIdFor = CrmBusinessUpdateReqVO.class,
permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id",
level = CrmPermissionLevelEnum.WRITE)
public void updateBusiness(CrmBusinessUpdateReqVO updateReqVO) {
// 校验存在
validateBusinessExists(updateReqVO.getId());
@ -71,7 +70,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, level = CrmPermissionLevelEnum.WRITE)
public void deleteBusiness(Long id) {
// 校验存在
validateBusinessExists(id);
@ -88,7 +87,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, permissionLevel = CrmPermissionLevelEnum.READ)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, level = CrmPermissionLevelEnum.READ)
public CrmBusinessDO getBusiness(Long id) {
return businessMapper.selectById(id);
}
@ -104,21 +103,20 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
@Override
public PageResult<CrmBusinessDO> getBusinessPage(CrmBusinessPageReqVO pageReqVO, Long userId) {
// 1. 获取当前用户能看的分页数据
PageResult<CrmPermissionDO> permissionPage = crmPermissionService.getPermissionPage(
CrmBusinessConvert.INSTANCE.convert(pageReqVO).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()).setUserId(userId));
Set<Long> ids = convertSet(permissionPage.getList(), CrmPermissionDO::getBizId);
List<CrmPermissionDO> permissions = crmPermissionService.getPermissionListByBizTypeAndUserId(
CrmBizTypeEnum.CRM_BUSINESS.getType(), userId);
Set<Long> ids = convertSet(permissions, CrmPermissionDO::getBizId);
if (CollUtil.isEmpty(ids)) { // 没得说明没有什么给他看的
return PageResult.empty();
}
// 2. 获取商机分页数据
List<CrmBusinessDO> businessList = businessMapper.selectList(pageReqVO, ids);
return new PageResult<>(businessList, (long) businessList.size());
return businessMapper.selectPage(pageReqVO, ids);
}
@Override
public List<CrmBusinessDO> getBusinessList(CrmBusinessExportReqVO exportReqVO) {
return businessMapper.selectList(exportReqVO);
return businessMapper.selectPage(exportReqVO);
}
@Override
@ -134,14 +132,4 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
// 3. TODO 记录转移日志
}
@Override
public boolean validateBizIdExists(Integer bizType, Long bizId) {
// 1. 校验模块类型
if (!ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), bizId)) {
return false;
}
// 2. 校验是否存在
return businessMapper.selectById(bizId) != null;
}
}

View File

@ -37,11 +37,18 @@ public class ContactServiceImpl implements ContactService {
// 插入
ContactDO contact = ContactConvert.INSTANCE.convert(createReqVO);
contactMapper.insert(contact);
// 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CONTACTS.getType())
.setBizId(contact.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
// 返回
return contact.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, level = CrmPermissionLevelEnum.WRITE)
public void updateContact(ContactUpdateReqVO updateReqVO) {
// 校验存在
validateContactExists(updateReqVO.getId());
@ -51,6 +58,8 @@ public class ContactServiceImpl implements ContactService {
}
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, level = CrmPermissionLevelEnum.WRITE)
public void deleteContact(Long id) {
// 校验存在
validateContactExists(id);
@ -65,6 +74,7 @@ public class ContactServiceImpl implements ContactService {
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, level = CrmPermissionLevelEnum.READ)
public ContactDO getContact(Long id) {
return contactMapper.selectById(id);
}

View File

@ -46,7 +46,7 @@ public class ContractServiceImpl implements ContractService {
// 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType())
.setBizId(contract.getId()).setUserId(userId).setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
.setBizId(contract.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
// 返回
return contract.getId();
@ -54,8 +54,7 @@ public class ContractServiceImpl implements ContractService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, getIdFor = ContractUpdateReqVO.class,
permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, level = CrmPermissionLevelEnum.WRITE)
public void updateContract(ContractUpdateReqVO updateReqVO) {
// 校验存在
validateContractExists(updateReqVO.getId());
@ -66,7 +65,7 @@ public class ContractServiceImpl implements ContractService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, level = CrmPermissionLevelEnum.WRITE)
public void deleteContract(Long id) {
// 校验存在
validateContractExists(id);
@ -83,7 +82,7 @@ public class ContractServiceImpl implements ContractService {
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, permissionLevel = CrmPermissionLevelEnum.READ)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, level = CrmPermissionLevelEnum.READ)
public ContractDO getContract(Long id) {
return contractMapper.selectById(id);
}

View File

@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
@ -50,9 +49,10 @@ public interface CrmCustomerService {
* 获得客户分页
*
* @param pageReqVO 分页查询
* @param userId 用户编号
* @return 客户分页
*/
PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO);
PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId);
/**
* 获得客户列表, 用于 Excel 导出

View File

@ -1,10 +1,15 @@
package cn.iocoder.yudao.module.crm.service.customer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
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;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper;
import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerSceneEnum;
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;
@ -15,10 +20,13 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS;
/**
@ -43,7 +51,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
// 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
.setBizId(customer.getId()).setUserId(userId).setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
.setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
// 返回
return customer.getId();
@ -51,12 +59,10 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, getIdFor = CrmCustomerUpdateReqVO.class,
permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) {
// 校验存在
validateCustomerExists(updateReqVO.getId());
// TODO 芋艿数据权限校验是否可以操作
// 更新
CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO);
@ -65,11 +71,10 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
@Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, permissionLevel = CrmPermissionLevelEnum.WRITE)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
public void deleteCustomer(Long id) {
// 校验存在
validateCustomerExists(id);
// TODO 芋艿数据权限校验是否可以操作
// 删除
customerMapper.deleteById(id);
@ -82,20 +87,38 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, permissionLevel = CrmPermissionLevelEnum.READ)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.READ)
public CrmCustomerDO getCustomer(Long id) {
return customerMapper.selectById(id);
}
@Override
public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO) {
// TODO 芋艿数据权限是否可以查询到
return customerMapper.selectPage(pageReqVO);
public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId) {
// 1.1 TODO 如果是超级管理员
boolean admin = false;
if (admin && ObjUtil.notEqual(userId, CrmPermissionDO.POOL_USER_ID)) {
return customerMapper.selectPage(pageReqVO, Collections.emptyList());
}
// 1.2 获取当前用户能看的分页数据
List<CrmPermissionDO> permissions = crmPermissionService.getPermissionListByBizTypeAndUserId(
CrmBizTypeEnum.CRM_CUSTOMER.getType(), userId);
// 1.3 TODO 场景数据过滤
if (CrmCustomerSceneEnum.isOwner(pageReqVO.getSceneType())) { // 场景一我负责的数据
permissions = CollectionUtils.filterList(permissions, item -> CrmPermissionLevelEnum.isOwner(item.getLevel()));
}
Set<Long> ids = convertSet(permissions, CrmPermissionDO::getBizId);
if (CollUtil.isEmpty(ids)) { // 没得说明没有什么给他看的
return PageResult.empty();
}
// 2. 获取客户分页数据
return customerMapper.selectPage(pageReqVO, ids);
}
@Override
public List<CrmCustomerDO> getCustomerList(CrmCustomerExportReqVO exportReqVO) {
return customerMapper.selectList(exportReqVO);
//return customerMapper.selectList(exportReqVO);
return Collections.emptyList();
}
/**

View File

@ -1,15 +1,14 @@
package cn.iocoder.yudao.module.crm.service.permission;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionPageReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
@ -30,16 +29,16 @@ public interface CrmPermissionService {
/**
* 更新数据权限
*
* @param updateBO 更新信息
* @param updateReqVO 更新信息
*/
void updatePermission(@Valid CrmPermissionUpdateReqBO updateBO);
void updatePermission(CrmPermissionUpdateReqVO updateReqVO);
/**
* 删除数据权限
*
* @param id 编号
* @param ids 编号
*/
void deletePermission(Long id);
void deletePermission(Collection<Long> ids);
/**
* 获取用户数据权限通过 数据类型 x 某个数据 x 用户编号
@ -51,6 +50,15 @@ public interface CrmPermissionService {
*/
CrmPermissionDO getPermissionByBizTypeAndBizIdAndUserId(Integer bizType, Long bizId, Long userId);
/**
* 获取用户数据权限通过 权限编号 x 用户编号
*
* @param id 权限编号
* @param userId 用户编号
* @return 数据权限
*/
CrmPermissionDO getPermissionByIdAndUserId(Long id, Long userId);
/**
* 获取数据权限列表通过 数据类型 x 某个数据
*
@ -61,18 +69,47 @@ public interface CrmPermissionService {
List<CrmPermissionDO> getPermissionByBizTypeAndBizId(Integer bizType, Long bizId);
/**
* 数据权限转移
* 获取数据权限列表通过 数据类型 x 某个数据
*
* @param crmTransferPermissionReqBO 数据权限转移请求
* @param bizType 数据类型关联 {@link CrmBizTypeEnum}
* @param bizIds 数据编号关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
* @param level 权限级别
* @return Crm 数据权限列表
*/
void transferPermission(@Valid CrmTransferPermissionReqBO crmTransferPermissionReqBO);
List<CrmPermissionDO> getPermissionByBizTypeAndBizIdsAndLevel(Integer bizType, Collection<Long> bizIds, Integer level);
/**
* 获取数据权限分页数据
* 数据权限转移
*
* @param pageReqBO 分页请求
* @return 数据权限分页数据
* @param crmPermissionTransferReqBO 数据权限转移请求
*/
PageResult<CrmPermissionDO> getPermissionPage(CrmPermissionPageReqBO pageReqBO);
void transferPermission(@Valid CrmPermissionTransferReqBO crmPermissionTransferReqBO);
/**
* 获取用户参与的模块数据列表
*
* @param bizType 模块类型
* @param userId 用户编号
* @return 模块数据列表
*/
List<CrmPermissionDO> getPermissionListByBizTypeAndUserId(Integer bizType, Long userId);
/**
* 领取公海数据
*
* @param bizType 数据类型关联 {@link CrmBizTypeEnum}
* @param bizId 数据编号关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
* @param userId 用户编号AdminUser#id
*/
void receiveBiz(Integer bizType, Long bizId, Long userId);
/**
* 数据放入公海
*
* @param bizType 数据类型关联 {@link CrmBizTypeEnum}
* @param bizId 数据编号关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
* @param userId 用户编号AdminUser#id
*/
void putPool(Integer bizType, Long bizId, Long userId);
}

View File

@ -2,22 +2,21 @@ package cn.iocoder.yudao.module.crm.service.permission;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO;
import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.dal.mysql.permission.CrmPermissionMapper;
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.bo.CrmPermissionCreateReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionPageReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmTransferPermissionReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import org.springframework.stereotype.Service;
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;
@ -54,26 +53,22 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
@Override
@Transactional(rollbackFor = Exception.class)
public void updatePermission(CrmPermissionUpdateReqBO updateBO) {
// TODO @puhui999这里 1.1 1.2下面 2.这样更有序一点
// 1. 校验用户是否存在
adminUserApi.validateUserList(Collections.singletonList(updateBO.getUserId()));
// 2. 校验存在
validateCrmPermissionExists(updateBO.getId());
public void updatePermission(CrmPermissionUpdateReqVO updateReqVO) {
// 校验存在
validateCrmPermissionExists(updateReqVO.getIds());
// 更新操作
CrmPermissionDO updateDO = CrmPermissionConvert.INSTANCE.convert(updateBO);
crmPermissionMapper.updateById(updateDO);
List<CrmPermissionDO> updateDO = CrmPermissionConvert.INSTANCE.convertList(updateReqVO);
crmPermissionMapper.updateBatch(updateDO);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deletePermission(Long id) {
public void deletePermission(Collection<Long> ids) {
// 校验存在
validateCrmPermissionExists(id);
validateCrmPermissionExists(ids);
// 删除
crmPermissionMapper.deleteById(id);
crmPermissionMapper.deleteBatchIds(ids);
}
@Override
@ -81,63 +76,96 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
return crmPermissionMapper.selectByBizTypeAndBizIdByUserId(bizType, bizId, userId);
}
@Override
public CrmPermissionDO getPermissionByIdAndUserId(Long id, Long userId) {
return crmPermissionMapper.selectByIdAndUserId(id, userId);
}
@Override
public List<CrmPermissionDO> getPermissionByBizTypeAndBizId(Integer bizType, Long bizId) {
return crmPermissionMapper.selectByBizTypeAndBizId(bizType, bizId);
}
private void validateCrmPermissionExists(Long id) {
if (crmPermissionMapper.selectById(id) == null) {
@Override
public List<CrmPermissionDO> getPermissionByBizTypeAndBizIdsAndLevel(Integer bizType, Collection<Long> bizIds, Integer level) {
return crmPermissionMapper.selectListByBizTypeAndBizIdsAndLevel(bizType, bizIds, level);
}
private void validateCrmPermissionExists(Collection<Long> ids) {
List<CrmPermissionDO> permissionList = crmPermissionMapper.selectBatchIds(ids);
// 校验存在
if (ObjUtil.notEqual(permissionList.size(), ids.size())) {
throw exception(CRM_PERMISSION_NOT_EXISTS);
}
}
@Override
public void transferPermission(CrmTransferPermissionReqBO transferReqBO) {
@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());
// TODO 校验是否为超级管理员 || 1
if (oldPermission == null || !isOwner(oldPermission.getPermissionLevel())) {
if (oldPermission == null || !isOwner(oldPermission.getLevel())) {
throw exception(CRM_PERMISSION_DENIED, crmName);
}
// TODO @puhui999这个顺序编号看看调整下2. 后面是 2.1 结果没 2.2 有点怪
// 2. 校验转移对象是否已经是该负责人
// 1.1 校验转移对象是否已经是该负责人
if (ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) {
throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, crmName);
}
// 2.1 校验新负责人是否存在
// 1.2 校验新负责人是否存在
adminUserApi.validateUserList(Collections.singletonList(transferReqBO.getNewOwnerUserId()));
// 3. 权限转移
// 2. 权限转移
List<CrmPermissionDO> permissions = crmPermissionMapper.selectByBizTypeAndBizId(
transferReqBO.getBizType(), transferReqBO.getBizId()); // 获取所有团队成员
// 3.1 校验新负责人是否在团队成员中
// 2.1 校验新负责人是否在团队成员中
CrmPermissionDO permission = CollUtil.findOne(permissions,
item -> ObjUtil.equal(item.getUserId(), transferReqBO.getNewOwnerUserId()));
if (permission == null) { // 不存在则以负责人的级别加入这个团队
crmPermissionMapper.insert(new CrmPermissionDO().setBizType(transferReqBO.getBizType())
.setBizId(transferReqBO.getBizId()).setUserId(transferReqBO.getNewOwnerUserId())
.setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
.setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
} else { // 存在则修改权限级别
crmPermissionMapper.updateById(new CrmPermissionDO().setId(permission.getId())
.setPermissionLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
.setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
}
// 4. 老负责人处理
if (transferReqBO.getJoinTeam()) { // 加入团队
// 2.2. 老负责人处理
if (transferReqBO.getOldOwnerPermissionLevel() != null) { // 加入团队
crmPermissionMapper.updateById(new CrmPermissionDO().setId(oldPermission.getId())
.setPermissionLevel(transferReqBO.getPermissionLevel())); // 设置加入团队后的级别
.setLevel(transferReqBO.getOldOwnerPermissionLevel())); // 设置加入团队后的级别
return;
}
crmPermissionMapper.deleteById(oldPermission.getId()); // 移除
}
@Override
public PageResult<CrmPermissionDO> getPermissionPage(CrmPermissionPageReqBO pageReqBO) {
return crmPermissionMapper.selectPage(pageReqBO);
public List<CrmPermissionDO> getPermissionListByBizTypeAndUserId(Integer bizType, Long userId) {
return crmPermissionMapper.selectListByBizTypeAndUserId(bizType, userId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void receiveBiz(Integer bizType, Long bizId, Long userId) {
CrmPermissionDO permission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId(bizType, bizId, CrmPermissionDO.POOL_USER_ID);
if (permission == null) { // 不存在则模块数据也不存在
throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, CrmBizTypeEnum.getNameByType(bizType));
}
crmPermissionMapper.updateById(new CrmPermissionDO().setId(permission.getId()).setUserId(userId));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void putPool(Integer bizType, Long bizId, Long userId) {
CrmPermissionDO permission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId(bizType, bizId, userId);
if (permission == null) { // 不存在则模块数据也不存在
throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, CrmBizTypeEnum.getNameByType(bizType));
}
crmPermissionMapper.updateById(new CrmPermissionDO().setId(permission.getId()).setUserId(CrmPermissionDO.POOL_USER_ID));
}
}

View File

@ -33,12 +33,11 @@ public class CrmPermissionCreateReqBO {
@NotNull(message = "Crm 数据编号不能为空")
private Long bizId;
// TODO @puhui999简化成 level
/**
* 权限级别
*/
@NotNull(message = "权限级别不能为空")
@InEnum(CrmPermissionLevelEnum.class)
private Integer permissionLevel;
private Integer level;
}

View File

@ -1,32 +0,0 @@
package cn.iocoder.yudao.module.crm.service.permission.bo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - CRM 数据权限分页 Request BO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CrmPermissionPageReqBO extends PageParam {
/**
* 当前登录用户编号
*/
@NotNull(message = "用户编号不能为空")
private Long userId;
/**
* Crm 类型
*/
@NotNull(message = "Crm 类型不能为空")
@InEnum(CrmBizTypeEnum.class)
private Integer bizType;
}

View File

@ -7,14 +7,13 @@ import lombok.Data;
import javax.validation.constraints.NotNull;
// TODO @puhui999CrmPermissionTransferReqBO
/**
* 数据权限转移 Request BO
*
* @author HUIHUI
*/
@Data
public class CrmTransferPermissionReqBO {
public class CrmPermissionTransferReqBO {
/**
* 当前登录用户编号
@ -40,17 +39,10 @@ public class CrmTransferPermissionReqBO {
@NotNull(message = "新负责人的用户编号不能为空")
private Long newOwnerUserId;
// TODO @puhui999joinTeam 可以合并成 permissionLevel oldOwnerPermissionLevel这样 null 说明移除因为都换负责人啦
/**
* 老负责人是否加入团队/
*/
@NotNull(message = "老负责人是否加入团队不能为空")
private Boolean joinTeam;
/**
* 老负责人加入团队后的权限级别如果 {@link #joinTeam} false, permissionLevel null
* 老负责人加入团队后的权限级别如果 null 说明移除
* 关联 {@link CrmPermissionLevelEnum}
*/
private Integer permissionLevel;
private Integer oldOwnerPermissionLevel;
}

View File

@ -1,8 +1,6 @@
package cn.iocoder.yudao.module.crm.service.permission.bo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
import lombok.Data;
@ -28,25 +26,11 @@ public class CrmPermissionUpdateReqBO {
@NotNull(message = "用户编号不能为空")
private Long userId;
// TODO @puhui999id 字段 bizType + bizId 是否二选一
/**
* Crm 类型
*/
@NotNull(message = "Crm 类型不能为空")
@InEnum(CrmBizTypeEnum.class)
private Integer bizType;
/**
* 数据编号
*/
@NotNull(message = "Crm 数据编号不能为空")
private Long bizId;
// TODO @puhui999简化成 level
/**
* 权限级别
*/
@NotNull(message = "权限级别不能为空")
@InEnum(CrmPermissionLevelEnum.class)
private Integer permissionLevel;
private Integer level;
}

View File

@ -130,7 +130,7 @@ public class CrmCustomerServiceImplTest extends BaseDbUnitTest {
//reqVO.setWebsite(null);
// 调用
PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(reqVO);
PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(reqVO, 1L);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());

View File

@ -1,6 +1,11 @@
package cn.iocoder.yudao.module.system.api.dept;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 岗位 API 接口
@ -18,4 +23,11 @@ public interface PostApi {
*/
void validPostList(Collection<Long> ids);
List<PostRespDTO> getPostList(Collection<Long> ids);
default Map<Long, PostRespDTO> getPostMap(Collection<Long> ids) {
List<PostRespDTO> list = getPostList(ids);
return CollectionUtils.convertMap(list, PostRespDTO::getId);
}
}

View File

@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.system.api.dept.dto;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import lombok.Data;
/**
* 岗位 Response DTO
*
* @author 芋道源码
*/
@Data
public class PostRespDTO {
/**
* 岗位序号
*/
private Long id;
/**
* 岗位名称
*/
private String name;
/**
* 岗位编码
*/
private String code;
/**
* 岗位排序
*/
private Integer sort;
/**
* 状态
*
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
}

View File

@ -1,10 +1,13 @@
package cn.iocoder.yudao.module.system.api.dept;
import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
import cn.iocoder.yudao.module.system.convert.dept.PostConvert;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
/**
* 岗位 API 实现类
@ -22,4 +25,9 @@ public class PostApiImpl implements PostApi {
postService.validatePostList(ids);
}
@Override
public List<PostRespDTO> getPostList(Collection<Long> ids) {
return PostConvert.INSTANCE.convert(postService.getPostList(ids));
}
}