Commit d0df0e8e161ec9df00db23916181465daca83a25

Authored by YunaiV
1 parent 0253846f

📖 CRM:【客户】优化锁定客户的逻辑实现

Showing 12 changed files with 128 additions and 103 deletions
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
@@ -39,12 +39,10 @@ public interface ErrorCodeConstants { @@ -39,12 +39,10 @@ public interface ErrorCodeConstants {
39 ErrorCode CUSTOMER_IN_POOL = new ErrorCode(1_020_006_004, "客户【{}】放入公海失败,原因:已经是公海客户"); 39 ErrorCode CUSTOMER_IN_POOL = new ErrorCode(1_020_006_004, "客户【{}】放入公海失败,原因:已经是公海客户");
40 ErrorCode CUSTOMER_LOCKED_PUT_POOL_FAIL = new ErrorCode(1_020_006_005, "客户【{}】放入公海失败,原因:客户已锁定"); 40 ErrorCode CUSTOMER_LOCKED_PUT_POOL_FAIL = new ErrorCode(1_020_006_005, "客户【{}】放入公海失败,原因:客户已锁定");
41 ErrorCode CUSTOMER_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_006_006, "更新客户【{}】负责人失败, 原因:系统异常"); 41 ErrorCode CUSTOMER_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_006_006, "更新客户【{}】负责人失败, 原因:系统异常");
42 -  
43 - ErrorCode CUSTOMER_UNLOCK_STATUS_NO_REPETITION = new ErrorCode(1_020_006_001, "无需重复操作锁定/解锁状态");  
44 -  
45 - ErrorCode CUSTOMER_NO_DEPARTMENT_FOUND = new ErrorCode(1_020_006_002, "操作失败,请先绑定部门再进行操作");  
46 -  
47 - ErrorCode CUSTOMER_EXCEED_LOCK_LIMIT = new ErrorCode(1_020_006_003, "操作失败,超出锁定规则上限"); 42 + ErrorCode CUSTOMER_LOCK_FAIL_IS_LOCK = new ErrorCode(1_020_006_007, "锁定客户失败,它已经处于锁定状态");
  43 + ErrorCode CUSTOMER_UNLOCK_FAIL_IS_UNLOCK = new ErrorCode(1_020_006_008, "锁定客户失败,它已经处于未锁定状态");
  44 + ErrorCode CUSTOMER_LOCK_EXCEED_LIMIT = new ErrorCode(1_020_006_009, "锁定客户失败,超出锁定规则上限");
  45 + ErrorCode CUSTOMER_OWNER_EXCEED_LIMIT = new ErrorCode(1_020_006_010, "操作失败,超出客户数拥有上限");
48 46
49 // ========== 权限管理 1_020_007_000 ========== 47 // ========== 权限管理 1_020_007_000 ==========
50 ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在"); 48 ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在");
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java
@@ -18,19 +18,19 @@ public enum CrmCustomerLimitConfigTypeEnum implements IntArrayValuable { @@ -18,19 +18,19 @@ public enum CrmCustomerLimitConfigTypeEnum implements IntArrayValuable {
18 /** 18 /**
19 * 拥有客户数限制 19 * 拥有客户数限制
20 */ 20 */
21 - CUSTOMER_QUANTITY_LIMIT(1, "拥有客户数限制"), 21 + CUSTOMER_OWNER_LIMIT(1, "拥有客户数限制"),
22 /** 22 /**
23 * 锁定客户数限制 23 * 锁定客户数限制
24 */ 24 */
25 CUSTOMER_LOCK_LIMIT(2, "锁定客户数限制"), 25 CUSTOMER_LOCK_LIMIT(2, "锁定客户数限制"),
26 ; 26 ;
27 27
28 - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLimitConfigTypeEnum::getCode).toArray(); 28 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLimitConfigTypeEnum::getType).toArray();
29 29
30 /** 30 /**
31 * 状态 31 * 状态
32 */ 32 */
33 - private final Integer code; 33 + private final Integer type;
34 /** 34 /**
35 * 状态名 35 * 状态名
36 */ 36 */
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
@@ -154,13 +154,12 @@ public class CrmCustomerController { @@ -154,13 +154,12 @@ public class CrmCustomerController {
154 return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); 154 return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class)));
155 } 155 }
156 156
157 - // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了;  
158 @PutMapping("/lock") 157 @PutMapping("/lock")
159 @Operation(summary = "锁定/解锁客户") 158 @Operation(summary = "锁定/解锁客户")
160 @OperateLog(enable = false) // TODO 关闭原有日志记录 159 @OperateLog(enable = false) // TODO 关闭原有日志记录
161 @PreAuthorize("@ss.hasPermission('crm:customer:update')") 160 @PreAuthorize("@ss.hasPermission('crm:customer:update')")
162 public CommonResult<Boolean> lockCustomer(@Valid @RequestBody CrmCustomerLockReqVO lockReqVO) { 161 public CommonResult<Boolean> lockCustomer(@Valid @RequestBody CrmCustomerLockReqVO lockReqVO) {
163 - customerService.lockCustomer(lockReqVO); 162 + customerService.lockCustomer(lockReqVO, getLoginUserId());
164 return success(true); 163 return success(true);
165 } 164 }
166 165
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java
@@ -13,6 +13,4 @@ public class CrmCustomerLockReqVO { @@ -13,6 +13,4 @@ public class CrmCustomerLockReqVO {
13 @Schema(description = "客户锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") 13 @Schema(description = "客户锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
14 private Boolean lockStatus; 14 private Boolean lockStatus;
15 15
16 -  
17 -  
18 } 16 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java
@@ -5,16 +5,10 @@ import lombok.Data; @@ -5,16 +5,10 @@ import lombok.Data;
5 import lombok.EqualsAndHashCode; 5 import lombok.EqualsAndHashCode;
6 import lombok.ToString; 6 import lombok.ToString;
7 7
8 -import java.util.List;  
9 -  
10 @Schema(description = "管理后台 - 客户限制配置创建 Request VO") 8 @Schema(description = "管理后台 - 客户限制配置创建 Request VO")
11 @Data 9 @Data
12 @EqualsAndHashCode(callSuper = true) 10 @EqualsAndHashCode(callSuper = true)
13 @ToString(callSuper = true) 11 @ToString(callSuper = true)
14 public class CrmCustomerLimitConfigCreateReqVO extends CrmCustomerLimitConfigBaseVO { 12 public class CrmCustomerLimitConfigCreateReqVO extends CrmCustomerLimitConfigBaseVO {
15 13
16 -  
17 - @Schema(description = "规则适用人群")  
18 - private Long userId;  
19 -  
20 } 14 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java
@@ -12,7 +12,6 @@ import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; @@ -12,7 +12,6 @@ import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
12 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; 12 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
13 import org.mapstruct.Mapper; 13 import org.mapstruct.Mapper;
14 import org.mapstruct.Mapping; 14 import org.mapstruct.Mapping;
15 -import org.mapstruct.Mappings;  
16 import org.mapstruct.factory.Mappers; 15 import org.mapstruct.factory.Mappers;
17 16
18 import java.util.List; 17 import java.util.List;
@@ -79,6 +78,4 @@ public interface CrmCustomerConvert { @@ -79,6 +78,4 @@ public interface CrmCustomerConvert {
79 78
80 List<CrmCustomerQueryAllRespVO> convertQueryAll(List<CrmCustomerDO> crmCustomerDO); 79 List<CrmCustomerQueryAllRespVO> convertQueryAll(List<CrmCustomerDO> crmCustomerDO);
81 80
82 - CrmCustomerDO convert(CrmCustomerLockReqVO lockReqVO);  
83 -  
84 } 81 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java
@@ -3,13 +3,11 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer; @@ -3,13 +3,11 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO;  
7 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; 6 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO;
8 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; 7 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
9 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
10 9
11 -import java.util.Arrays;  
12 -import java.util.stream.Collectors; 10 +import java.util.List;
13 11
14 /** 12 /**
15 * 客户限制配置 Mapper 13 * 客户限制配置 Mapper
@@ -25,16 +23,15 @@ public interface CrmCustomerLimitConfigMapper extends BaseMapperX&lt;CrmCustomerLim @@ -25,16 +23,15 @@ public interface CrmCustomerLimitConfigMapper extends BaseMapperX&lt;CrmCustomerLim
25 .orderByDesc(CrmCustomerLimitConfigDO::getId)); 23 .orderByDesc(CrmCustomerLimitConfigDO::getId));
26 } 24 }
27 25
28 - default CrmCustomerLimitConfigDO selectByLimitConfig(CrmCustomerLimitConfigCreateReqVO reqVO){  
29 - LambdaQueryWrapperX<CrmCustomerLimitConfigDO> queryWrapper = new LambdaQueryWrapperX<>();  
30 - queryWrapper.apply("FIND_IN_SET({0}, user_ids) > 0", reqVO.getUserId());  
31 - queryWrapper.eq(CrmCustomerLimitConfigDO::getType, reqVO.getType());  
32 - // 将部门ID列表转换成逗号分隔的字符串  
33 - String deptIdsString = reqVO.getDeptIds().stream()  
34 - .map(String::valueOf)  
35 - .collect(Collectors.joining(","));  
36 - queryWrapper.apply("FIND_IN_SET({0}, dept_ids) > 0", deptIdsString);  
37 - return selectOne(queryWrapper); 26 + default List<CrmCustomerLimitConfigDO> selectListByTypeAndUserIdAndDeptId(
  27 + Integer type, Long userId, Long deptId) {
  28 + LambdaQueryWrapperX<CrmCustomerLimitConfigDO> query = new LambdaQueryWrapperX<CrmCustomerLimitConfigDO>()
  29 + .eq(CrmCustomerLimitConfigDO::getType, type);
  30 + query.apply("FIND_IN_SET({0}, user_ids) > 0", userId);
  31 + if (deptId != null) {
  32 + query.apply("FIND_IN_SET({0}, dept_ids) > 0", deptId);
  33 + }
  34 + return selectList(query);
38 } 35 }
39 36
40 } 37 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
6 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; 7 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;
7 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 8 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
@@ -9,6 +10,7 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; @@ -9,6 +10,7 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
9 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; 10 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
10 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 11 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
11 import org.apache.ibatis.annotations.Mapper; 12 import org.apache.ibatis.annotations.Mapper;
  13 +import org.springframework.lang.Nullable;
12 14
13 import java.util.Collection; 15 import java.util.Collection;
14 import java.util.List; 16 import java.util.List;
@@ -21,6 +23,18 @@ import java.util.List; @@ -21,6 +23,18 @@ import java.util.List;
21 @Mapper 23 @Mapper
22 public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { 24 public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
23 25
  26 + default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) {
  27 + return selectCount(new LambdaUpdateWrapper<CrmCustomerDO>()
  28 + .eq(CrmCustomerDO::getLockStatus, lockStatus)
  29 + .eq(CrmCustomerDO::getOwnerUserId, ownerUserId));
  30 + }
  31 +
  32 + default Long selectCountByDealStatusAndOwnerUserId(@Nullable Boolean dealStatus, Long ownerUserId) {
  33 + return selectCount(new LambdaQueryWrapperX<CrmCustomerDO>()
  34 + .eqIfPresent(CrmCustomerDO::getDealStatus, dealStatus)
  35 + .eq(CrmCustomerDO::getOwnerUserId, ownerUserId));
  36 + }
  37 +
24 default int updateOwnerUserIdById(Long id, Long ownerUserId) { 38 default int updateOwnerUserIdById(Long id, Long ownerUserId) {
25 return update(new LambdaUpdateWrapper<CrmCustomerDO>() 39 return update(new LambdaUpdateWrapper<CrmCustomerDO>()
26 .eq(CrmCustomerDO::getId, id) 40 .eq(CrmCustomerDO::getId, id)
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java
@@ -5,9 +5,10 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmC @@ -5,9 +5,10 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmC
5 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; 5 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO;
6 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO; 6 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO;
7 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; 7 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
8 -  
9 import jakarta.validation.Valid; 8 import jakarta.validation.Valid;
10 9
  10 +import java.util.List;
  11 +
11 /** 12 /**
12 * 客户限制配置 Service 接口 13 * 客户限制配置 Service 接口
13 * 14 *
@@ -54,8 +55,11 @@ public interface CrmCustomerLimitConfigService { @@ -54,8 +55,11 @@ public interface CrmCustomerLimitConfigService {
54 PageResult<CrmCustomerLimitConfigDO> getCustomerLimitConfigPage(CrmCustomerLimitConfigPageReqVO pageReqVO); 55 PageResult<CrmCustomerLimitConfigDO> getCustomerLimitConfigPage(CrmCustomerLimitConfigPageReqVO pageReqVO);
55 56
56 /** 57 /**
57 - * 查询当前登录人客户限制配置 58 + * 查询用户对应的配置列表
  59 + *
  60 + * @param type 类型
  61 + * @param userId 用户类型
58 */ 62 */
59 - CrmCustomerLimitConfigDO selectByLimitConfig(CrmCustomerLimitConfigCreateReqVO configReqVO); 63 + List<CrmCustomerLimitConfigDO> getCustomerLimitConfigListByUserId(Integer type, Long userId);
60 64
61 } 65 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java
1 package cn.iocoder.yudao.module.crm.service.customer; 1 package cn.iocoder.yudao.module.crm.service.customer;
2 2
  3 +import cn.hutool.core.lang.Assert;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; 5 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO;
5 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; 6 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO;
@@ -9,12 +10,14 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfi @@ -9,12 +10,14 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfi
9 import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerLimitConfigMapper; 10 import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerLimitConfigMapper;
10 import cn.iocoder.yudao.module.system.api.dept.DeptApi; 11 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
11 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 12 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  13 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
12 import org.springframework.stereotype.Service; 14 import org.springframework.stereotype.Service;
13 import org.springframework.validation.annotation.Validated; 15 import org.springframework.validation.annotation.Validated;
14 16
15 import jakarta.annotation.Resource; 17 import jakarta.annotation.Resource;
16 18
17 import java.util.Collection; 19 import java.util.Collection;
  20 +import java.util.List;
18 21
19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 22 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
20 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_LIMIT_CONFIG_NOT_EXISTS; 23 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_LIMIT_CONFIG_NOT_EXISTS;
@@ -30,6 +33,7 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig @@ -30,6 +33,7 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig
30 33
31 @Resource 34 @Resource
32 private CrmCustomerLimitConfigMapper customerLimitConfigMapper; 35 private CrmCustomerLimitConfigMapper customerLimitConfigMapper;
  36 +
33 @Resource 37 @Resource
34 private DeptApi deptApi; 38 private DeptApi deptApi;
35 @Resource 39 @Resource
@@ -91,8 +95,10 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig @@ -91,8 +95,10 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig
91 } 95 }
92 96
93 @Override 97 @Override
94 - public CrmCustomerLimitConfigDO selectByLimitConfig(CrmCustomerLimitConfigCreateReqVO configReqVO) {  
95 - return customerLimitConfigMapper.selectByLimitConfig(configReqVO); 98 + public List<CrmCustomerLimitConfigDO> getCustomerLimitConfigListByUserId(Integer type, Long userId) {
  99 + AdminUserRespDTO user = adminUserApi.getUser(userId);
  100 + Assert.notNull(user, "用户({})不存在", userId);
  101 + return customerLimitConfigMapper.selectListByTypeAndUserIdAndDeptId(type, userId, user.getDeptId());
96 } 102 }
97 103
98 } 104 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
@@ -83,8 +83,9 @@ public interface CrmCustomerService { @@ -83,8 +83,9 @@ public interface CrmCustomerService {
83 * 锁定/解锁客户 83 * 锁定/解锁客户
84 * 84 *
85 * @param lockReqVO 更新信息 85 * @param lockReqVO 更新信息
  86 + * @param userId 用户编号
86 */ 87 */
87 - void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO); 88 + void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO, Long userId);
88 89
89 // ==================== 公海相关操作 ==================== 90 // ==================== 公海相关操作 ====================
90 91
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
@@ -2,13 +2,9 @@ package cn.iocoder.yudao.module.crm.service.customer; @@ -2,13 +2,9 @@ package cn.iocoder.yudao.module.crm.service.customer;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO;  
7 -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;  
8 -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO;  
9 -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO;  
10 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; 7 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
11 -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO;  
12 import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; 8 import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
13 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 9 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
14 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; 10 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
@@ -19,11 +15,9 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm @@ -19,11 +15,9 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm
19 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; 15 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
20 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; 16 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
21 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 17 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
22 -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;  
23 import com.mzt.logapi.context.LogRecordContext; 18 import com.mzt.logapi.context.LogRecordContext;
24 import com.mzt.logapi.service.impl.DiffParseFunction; 19 import com.mzt.logapi.service.impl.DiffParseFunction;
25 import com.mzt.logapi.starter.annotation.LogRecord; 20 import com.mzt.logapi.starter.annotation.LogRecord;
26 -import com.mzt.logapi.starter.annotation.LogRecord;  
27 import jakarta.annotation.Resource; 21 import jakarta.annotation.Resource;
28 import org.springframework.stereotype.Service; 22 import org.springframework.stereotype.Service;
29 import org.springframework.transaction.annotation.Transactional; 23 import org.springframework.transaction.annotation.Transactional;
@@ -33,13 +27,11 @@ import java.time.LocalDateTime; @@ -33,13 +27,11 @@ import java.time.LocalDateTime;
33 import java.util.*; 27 import java.util.*;
34 28
35 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
36 -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;  
37 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; 30 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
38 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; 31 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER;
39 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.TRANSFER_CUSTOMER_LOG_SUCCESS; 32 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.TRANSFER_CUSTOMER_LOG_SUCCESS;
40 -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_EXCEED_LOCK_LIMIT;  
41 import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; 33 import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT;
42 -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; 34 +import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_OWNER_LIMIT;
43 import static java.util.Collections.singletonList; 35 import static java.util.Collections.singletonList;
44 36
45 /** 37 /**
@@ -55,29 +47,32 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -55,29 +47,32 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
55 private CrmCustomerMapper customerMapper; 47 private CrmCustomerMapper customerMapper;
56 48
57 @Resource 49 @Resource
58 - private CrmPermissionService crmPermissionService; 50 + private CrmPermissionService permissionService;
59 @Resource 51 @Resource
60 - private CrmCustomerLimitConfigService crmCustomerLimitConfigService; 52 + private CrmCustomerLimitConfigService customerLimitConfigService;
61 53
62 @Resource 54 @Resource
63 private AdminUserApi adminUserApi; 55 private AdminUserApi adminUserApi;
64 56
65 @Override 57 @Override
66 @Transactional(rollbackFor = Exception.class) 58 @Transactional(rollbackFor = Exception.class)
67 - @LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户") // TODO @puhui999:客户名字,要记录进去;不然在展示操作日志的全列表,看不清楚是哪个客户哈; 59 + @LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户") // TODO @puhui999:创建了客户【客户名】,要记录进去;不然在展示操作日志的全列表,看不清楚是哪个客户哈;
68 public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { 60 public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) {
69 - // 插入客户 61 + // 1. 校验拥有客户是否到达上限
  62 + validateCustomerExceedOwnerLimit(createReqVO.getOwnerUserId(), 1);
  63 +
  64 + // 2. 插入客户
70 CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO) 65 CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO)
71 .setLockStatus(false).setDealStatus(false) 66 .setLockStatus(false).setDealStatus(false)
72 .setContactLastTime(LocalDateTime.now()); 67 .setContactLastTime(LocalDateTime.now());
73 // TODO @puhui999:可能要加个 receiveTime 字段,记录最后接收时间 68 // TODO @puhui999:可能要加个 receiveTime 字段,记录最后接收时间
74 customerMapper.insert(customer); 69 customerMapper.insert(customer);
75 70
76 - // 创建数据权限  
77 - crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) 71 + // 3. 创建数据权限
  72 + permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
78 .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 73 .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
79 74
80 - // 记录操作日志 75 + // 4. 记录操作日志
81 LogRecordContext.putVariable("customerId", customer.getId()); 76 LogRecordContext.putVariable("customerId", customer.getId());
82 return customer.getId(); 77 return customer.getId();
83 } 78 }
@@ -88,14 +83,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -88,14 +83,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
88 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) 83 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
89 public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { 84 public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) {
90 // TODO @puhui999:更新的时候,要把 updateReqVO 负责人设置为空,避免修改。 85 // TODO @puhui999:更新的时候,要把 updateReqVO 负责人设置为空,避免修改。
91 - // 校验存在 86 + // 1. 校验存在
92 CrmCustomerDO oldCustomer = validateCustomerExists(updateReqVO.getId()); 87 CrmCustomerDO oldCustomer = validateCustomerExists(updateReqVO.getId());
93 88
94 - // 更新 89 + // 2. 更新客户
95 CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); 90 CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO);
96 customerMapper.updateById(updateObj); 91 customerMapper.updateById(updateObj);
97 92
98 - // 记录操作日志 93 + // 3. 记录操作日志
99 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerUpdateReqVO.class)); 94 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerUpdateReqVO.class));
100 // TODO 扩展信息测试 @puhui999:看着没啥问题,可以删除啦; 95 // TODO 扩展信息测试 @puhui999:看着没啥问题,可以删除啦;
101 HashMap<String, Object> extra = new HashMap<>(); 96 HashMap<String, Object> extra = new HashMap<>();
@@ -114,7 +109,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -114,7 +109,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
114 // 删除 109 // 删除
115 customerMapper.deleteById(id); 110 customerMapper.deleteById(id);
116 // 删除数据权限 111 // 删除数据权限
117 - crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); 112 + permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id);
118 } 113 }
119 114
120 private CrmCustomerDO validateCustomerExists(Long id) { 115 private CrmCustomerDO validateCustomerExists(Long id) {
@@ -159,63 +154,83 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -159,63 +154,83 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
159 @LogRecord(type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) 154 @LogRecord(type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS)
160 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) 155 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER)
161 public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { 156 public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) {
162 - // 1. 校验客户是否存在  
163 - CrmCustomerDO customerDO = validateCustomerExists(reqVO.getId()); 157 + // 1.1 校验客户是否存在
  158 + CrmCustomerDO customer = validateCustomerExists(reqVO.getId());
  159 + // 1.2 校验拥有客户是否到达上限
  160 + validateCustomerExceedOwnerLimit(reqVO.getNewOwnerUserId(), 1);
164 161
165 // 2.1 数据权限转移 162 // 2.1 数据权限转移
166 - crmPermissionService.transferPermission( 163 + permissionService.transferPermission(
167 CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); 164 CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()));
168 // 2.2 转移后重新设置负责人 165 // 2.2 转移后重新设置负责人
169 customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); 166 customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
170 167
171 // 3. TODO 记录转移日志 168 // 3. TODO 记录转移日志
172 - LogRecordContext.putVariable("crmCustomer", customerDO); 169 + LogRecordContext.putVariable("crmCustomer", customer);
173 } 170 }
174 171
175 @Override 172 @Override
  173 + // TODO @puhui999:看看这个能不能根据条件,写操作日志;
  174 + // TODO 如果是 锁定,则 subType 为 锁定客户;success 为 将客户【】锁定
  175 + // TODO 如果是 解锁,则 subType 为 解锁客户;success 为 将客户【】解锁
176 @LogRecord(type = CRM_CUSTOMER, subType = "锁定/解锁客户", bizNo = "{{#updateReqVO.id}}", success = "锁定了客户") 176 @LogRecord(type = CRM_CUSTOMER, subType = "锁定/解锁客户", bizNo = "{{#updateReqVO.id}}", success = "锁定了客户")
177 - public void lockCustomer(CrmCustomerLockReqVO lockReqVO) {  
178 - // 校验当前客户是否存在 177 + // TODO @puhui999:数据权限
  178 + public void lockCustomer(CrmCustomerLockReqVO lockReqVO, Long userId) {
  179 + // 1.1 校验当前客户是否存在
179 validateCustomerExists(lockReqVO.getId()); 180 validateCustomerExists(lockReqVO.getId());
180 -  
181 - CrmCustomerDO customerDO = customerMapper.selectById(lockReqVO.getId());  
182 -  
183 - // 校验当前是否重复操作锁定/解锁状态  
184 - if (customerDO.getLockStatus().equals(lockReqVO.getLockStatus())) {  
185 - throw exception(CUSTOMER_UNLOCK_STATUS_NO_REPETITION); 181 + // 1.2 校验当前是否重复操作锁定/解锁状态
  182 + CrmCustomerDO customer = customerMapper.selectById(lockReqVO.getId());
  183 + if (customer.getLockStatus().equals(lockReqVO.getLockStatus())) {
  184 + throw exception(customer.getLockStatus() ? CUSTOMER_LOCK_FAIL_IS_LOCK : CUSTOMER_UNLOCK_FAIL_IS_UNLOCK);
186 } 185 }
187 -  
188 - // 获取当前登录信息,开始校验锁定上限  
189 - AdminUserRespDTO userRespDTO = adminUserApi.getUser(getLoginUserId());  
190 -  
191 - if (userRespDTO.getDeptId() == null || userRespDTO.getId() == null) {  
192 - // 如有入参为空,提示业务异常  
193 - throw exception(CUSTOMER_NO_DEPARTMENT_FOUND); 186 + // 1.3 校验锁定上限。
  187 + if (lockReqVO.getLockStatus()) {
  188 + validateCustomerExceedLockLimit(userId);
194 } 189 }
195 190
196 - // 开始校验规则限制  
197 - List<Long> userDeptIds = Collections.singletonList(userRespDTO.getDeptId());  
198 -  
199 - CrmCustomerLimitConfigCreateReqVO configReqVO = new CrmCustomerLimitConfigCreateReqVO();  
200 - configReqVO.setUserId(userRespDTO.getId());  
201 - configReqVO.setDeptIds(userDeptIds);  
202 - configReqVO.setType(CUSTOMER_LOCK_LIMIT.getCode());  
203 -  
204 - CrmCustomerLimitConfigDO crmCustomerLimitConfigDO = crmCustomerLimitConfigService.selectByLimitConfig(configReqVO);  
205 -  
206 - // 统计当前用户已锁定客户数量  
207 - List<CrmCustomerDO> crmCustomerDOS = customerMapper.selectList("owner_user_id", getLoginUserId());  
208 - long customerLockCount = crmCustomerDOS.stream().filter(CrmCustomerDO::getLockStatus).count(); 191 + // 2. 更新锁定状态
  192 + customerMapper.updateById(BeanUtils.toBean(lockReqVO, CrmCustomerDO.class));
  193 + }
209 194
210 - // 锁定操作的时候校验当前用户可锁定客户的上限  
211 - if (crmCustomerLimitConfigDO != null && lockReqVO.getLockStatus() && customerLockCount >= crmCustomerLimitConfigDO.getMaxCount()) {  
212 - // 超出锁定数量上限,提示业务异常  
213 - throw exception(CUSTOMER_EXCEED_LOCK_LIMIT); 195 + /**
  196 + * 校验用户拥有的客户数量,是否到达上限
  197 + *
  198 + * @param userId 用户编号
  199 + * @param newCount 附加数量
  200 + */
  201 + private void validateCustomerExceedOwnerLimit(Long userId, int newCount) {
  202 + List<CrmCustomerLimitConfigDO> limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId(
  203 + CUSTOMER_OWNER_LIMIT.getType(), userId);
  204 + if (CollUtil.isEmpty(limitConfigs)) {
  205 + return;
214 } 206 }
  207 + Long ownerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(null, userId);
  208 + Long dealOwnerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(true, userId);
  209 + limitConfigs.forEach(limitConfig -> {
  210 + long nowCount = limitConfig.getDealCountEnabled() ? ownerCount : ownerCount - dealOwnerCount;
  211 + if (nowCount + newCount > limitConfig.getMaxCount()) {
  212 + throw exception(CUSTOMER_OWNER_EXCEED_LIMIT);
  213 + }
  214 + });
  215 + }
215 216
216 - // 更新  
217 - CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(lockReqVO);  
218 - customerMapper.updateById(updateObj); 217 + /**
  218 + * 校验用户锁定的客户数量,是否到达上限
  219 + *
  220 + * @param userId 用户编号
  221 + */
  222 + private void validateCustomerExceedLockLimit(Long userId) {
  223 + List<CrmCustomerLimitConfigDO> limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId(
  224 + CUSTOMER_LOCK_LIMIT.getType(), userId);
  225 + if (CollUtil.isEmpty(limitConfigs)) {
  226 + return;
  227 + }
  228 + Long lockCount = customerMapper.selectCountByLockStatusAndOwnerUserId(true, userId);
  229 + Integer maxCount = CollectionUtils.getMaxValue(limitConfigs, CrmCustomerLimitConfigDO::getMaxCount);
  230 + assert maxCount != null;
  231 + if (lockCount >= maxCount) {
  232 + throw exception(CUSTOMER_LOCK_EXCEED_LIMIT);
  233 + }
219 } 234 }
220 235
221 @Override 236 @Override
@@ -239,7 +254,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -239,7 +254,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
239 throw exception(CUSTOMER_UPDATE_OWNER_USER_FAIL); 254 throw exception(CUSTOMER_UPDATE_OWNER_USER_FAIL);
240 } 255 }
241 // 3. 删除负责人数据权限 256 // 3. 删除负责人数据权限
242 - crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(), 257 + permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(),
243 CrmPermissionLevelEnum.OWNER.getLevel()); 258 CrmPermissionLevelEnum.OWNER.getLevel());
244 } 259 }
245 260
@@ -262,6 +277,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -262,6 +277,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
262 // 校验成交状态 277 // 校验成交状态
263 validateCustomerDeal(customer); 278 validateCustomerDeal(customer);
264 }); 279 });
  280 + // 1.4 校验负责人是否到达上限
  281 + validateCustomerExceedOwnerLimit(ownerUserId, customers.size());
265 282
266 // 2. 领取公海数据 283 // 2. 领取公海数据
267 List<CrmCustomerDO> updateCustomers = new ArrayList<>(); 284 List<CrmCustomerDO> updateCustomers = new ArrayList<>();
@@ -277,7 +294,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -277,7 +294,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
277 // 3.1 更新客户负责人 294 // 3.1 更新客户负责人
278 customerMapper.updateBatch(updateCustomers); 295 customerMapper.updateBatch(updateCustomers);
279 // 3.2 创建负责人数据权限 296 // 3.2 创建负责人数据权限
280 - crmPermissionService.createPermissionBatch(createPermissions); 297 + permissionService.createPermissionBatch(createPermissions);
281 } 298 }
282 299
283 private void validateCustomerOwnerExists(CrmCustomerDO customer, Boolean pool) { 300 private void validateCustomerOwnerExists(CrmCustomerDO customer, Boolean pool) {