mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 18:49:06 +08:00 
			
		
		
		
	📖 CRM:【客户】优化锁定客户的逻辑实现
This commit is contained in:
		| @ -39,12 +39,10 @@ public interface ErrorCodeConstants { | |||||||
|     ErrorCode CUSTOMER_IN_POOL = new ErrorCode(1_020_006_004, "客户【{}】放入公海失败,原因:已经是公海客户"); |     ErrorCode CUSTOMER_IN_POOL = new ErrorCode(1_020_006_004, "客户【{}】放入公海失败,原因:已经是公海客户"); | ||||||
|     ErrorCode CUSTOMER_LOCKED_PUT_POOL_FAIL = new ErrorCode(1_020_006_005, "客户【{}】放入公海失败,原因:客户已锁定"); |     ErrorCode CUSTOMER_LOCKED_PUT_POOL_FAIL = new ErrorCode(1_020_006_005, "客户【{}】放入公海失败,原因:客户已锁定"); | ||||||
|     ErrorCode CUSTOMER_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_006_006, "更新客户【{}】负责人失败, 原因:系统异常"); |     ErrorCode CUSTOMER_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_006_006, "更新客户【{}】负责人失败, 原因:系统异常"); | ||||||
|  |     ErrorCode CUSTOMER_LOCK_FAIL_IS_LOCK = new ErrorCode(1_020_006_007, "锁定客户失败,它已经处于锁定状态"); | ||||||
|     ErrorCode CUSTOMER_UNLOCK_STATUS_NO_REPETITION = new ErrorCode(1_020_006_001, "无需重复操作锁定/解锁状态"); |     ErrorCode CUSTOMER_UNLOCK_FAIL_IS_UNLOCK = new ErrorCode(1_020_006_008, "锁定客户失败,它已经处于未锁定状态"); | ||||||
|  |     ErrorCode CUSTOMER_LOCK_EXCEED_LIMIT = new ErrorCode(1_020_006_009, "锁定客户失败,超出锁定规则上限"); | ||||||
|     ErrorCode CUSTOMER_NO_DEPARTMENT_FOUND = new ErrorCode(1_020_006_002, "操作失败,请先绑定部门再进行操作"); |     ErrorCode CUSTOMER_OWNER_EXCEED_LIMIT = new ErrorCode(1_020_006_010, "操作失败,超出客户数拥有上限"); | ||||||
|  |  | ||||||
|     ErrorCode CUSTOMER_EXCEED_LOCK_LIMIT = new ErrorCode(1_020_006_003, "操作失败,超出锁定规则上限"); |  | ||||||
|  |  | ||||||
|     // ========== 权限管理 1_020_007_000 ========== |     // ========== 权限管理 1_020_007_000 ========== | ||||||
|     ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在"); |     ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在"); | ||||||
|  | |||||||
| @ -18,19 +18,19 @@ public enum CrmCustomerLimitConfigTypeEnum implements IntArrayValuable { | |||||||
|     /** |     /** | ||||||
|      * 拥有客户数限制 |      * 拥有客户数限制 | ||||||
|      */ |      */ | ||||||
|     CUSTOMER_QUANTITY_LIMIT(1, "拥有客户数限制"), |     CUSTOMER_OWNER_LIMIT(1, "拥有客户数限制"), | ||||||
|     /** |     /** | ||||||
|      * 锁定客户数限制 |      * 锁定客户数限制 | ||||||
|      */ |      */ | ||||||
|     CUSTOMER_LOCK_LIMIT(2, "锁定客户数限制"), |     CUSTOMER_LOCK_LIMIT(2, "锁定客户数限制"), | ||||||
|     ; |     ; | ||||||
|  |  | ||||||
|     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLimitConfigTypeEnum::getCode).toArray(); |     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLimitConfigTypeEnum::getType).toArray(); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 状态 |      * 状态 | ||||||
|      */ |      */ | ||||||
|     private final Integer code; |     private final Integer type; | ||||||
|     /** |     /** | ||||||
|      * 状态名 |      * 状态名 | ||||||
|      */ |      */ | ||||||
|  | |||||||
| @ -154,13 +154,12 @@ public class CrmCustomerController { | |||||||
|         return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); |         return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; |  | ||||||
|     @PutMapping("/lock") |     @PutMapping("/lock") | ||||||
|     @Operation(summary = "锁定/解锁客户") |     @Operation(summary = "锁定/解锁客户") | ||||||
|     @OperateLog(enable = false) // TODO 关闭原有日志记录 |     @OperateLog(enable = false) // TODO 关闭原有日志记录 | ||||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:update')") |     @PreAuthorize("@ss.hasPermission('crm:customer:update')") | ||||||
|     public CommonResult<Boolean> lockCustomer(@Valid @RequestBody CrmCustomerLockReqVO lockReqVO) { |     public CommonResult<Boolean> lockCustomer(@Valid @RequestBody CrmCustomerLockReqVO lockReqVO) { | ||||||
|         customerService.lockCustomer(lockReqVO); |         customerService.lockCustomer(lockReqVO, getLoginUserId()); | ||||||
|         return success(true); |         return success(true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -13,6 +13,4 @@ public class CrmCustomerLockReqVO { | |||||||
|     @Schema(description = "客户锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") |     @Schema(description = "客户锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | ||||||
|     private Boolean lockStatus; |     private Boolean lockStatus; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,16 +5,10 @@ import lombok.Data; | |||||||
| import lombok.EqualsAndHashCode; | import lombok.EqualsAndHashCode; | ||||||
| import lombok.ToString; | import lombok.ToString; | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| @Schema(description = "管理后台 - 客户限制配置创建 Request VO") | @Schema(description = "管理后台 - 客户限制配置创建 Request VO") | ||||||
| @Data | @Data | ||||||
| @EqualsAndHashCode(callSuper = true) | @EqualsAndHashCode(callSuper = true) | ||||||
| @ToString(callSuper = true) | @ToString(callSuper = true) | ||||||
| public class CrmCustomerLimitConfigCreateReqVO extends CrmCustomerLimitConfigBaseVO { | public class CrmCustomerLimitConfigCreateReqVO extends CrmCustomerLimitConfigBaseVO { | ||||||
|  |  | ||||||
|  |  | ||||||
|     @Schema(description = "规则适用人群") |  | ||||||
|     private Long userId; |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -12,7 +12,6 @@ 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.system.api.user.dto.AdminUserRespDTO; | ||||||
| import org.mapstruct.Mapper; | import org.mapstruct.Mapper; | ||||||
| import org.mapstruct.Mapping; | import org.mapstruct.Mapping; | ||||||
| import org.mapstruct.Mappings; |  | ||||||
| import org.mapstruct.factory.Mappers; | import org.mapstruct.factory.Mappers; | ||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @ -79,6 +78,4 @@ public interface CrmCustomerConvert { | |||||||
|  |  | ||||||
|     List<CrmCustomerQueryAllRespVO> convertQueryAll(List<CrmCustomerDO> crmCustomerDO); |     List<CrmCustomerQueryAllRespVO> convertQueryAll(List<CrmCustomerDO> crmCustomerDO); | ||||||
|  |  | ||||||
|     CrmCustomerDO convert(CrmCustomerLockReqVO lockReqVO); |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,13 +3,11 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer; | |||||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||||
| import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; |  | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; | ||||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; | ||||||
| import org.apache.ibatis.annotations.Mapper; | import org.apache.ibatis.annotations.Mapper; | ||||||
|  |  | ||||||
| import java.util.Arrays; | import java.util.List; | ||||||
| import java.util.stream.Collectors; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 客户限制配置 Mapper |  * 客户限制配置 Mapper | ||||||
| @ -25,16 +23,15 @@ public interface CrmCustomerLimitConfigMapper extends BaseMapperX<CrmCustomerLim | |||||||
|                 .orderByDesc(CrmCustomerLimitConfigDO::getId)); |                 .orderByDesc(CrmCustomerLimitConfigDO::getId)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     default CrmCustomerLimitConfigDO selectByLimitConfig(CrmCustomerLimitConfigCreateReqVO reqVO){ |     default List<CrmCustomerLimitConfigDO> selectListByTypeAndUserIdAndDeptId( | ||||||
|         LambdaQueryWrapperX<CrmCustomerLimitConfigDO> queryWrapper = new LambdaQueryWrapperX<>(); |             Integer type, Long userId, Long deptId) { | ||||||
|         queryWrapper.apply("FIND_IN_SET({0}, user_ids) > 0", reqVO.getUserId()); |         LambdaQueryWrapperX<CrmCustomerLimitConfigDO> query = new LambdaQueryWrapperX<CrmCustomerLimitConfigDO>() | ||||||
|         queryWrapper.eq(CrmCustomerLimitConfigDO::getType, reqVO.getType()); |                 .eq(CrmCustomerLimitConfigDO::getType, type); | ||||||
|         // 将部门ID列表转换成逗号分隔的字符串 |         query.apply("FIND_IN_SET({0}, user_ids) > 0", userId); | ||||||
|         String deptIdsString = reqVO.getDeptIds().stream() |         if (deptId != null) { | ||||||
|                 .map(String::valueOf) |             query.apply("FIND_IN_SET({0}, dept_ids) > 0", deptId); | ||||||
|                 .collect(Collectors.joining(",")); |         } | ||||||
|         queryWrapper.apply("FIND_IN_SET({0}, dept_ids) > 0", deptIdsString); |         return selectList(query); | ||||||
|         return selectOne(queryWrapper); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer; | |||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||||
|  | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||||||
| import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; | ||||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||||||
| @ -9,6 +10,7 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | |||||||
| import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; | import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; | ||||||
| import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | ||||||
| import org.apache.ibatis.annotations.Mapper; | import org.apache.ibatis.annotations.Mapper; | ||||||
|  | import org.springframework.lang.Nullable; | ||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @ -21,6 +23,18 @@ import java.util.List; | |||||||
| @Mapper | @Mapper | ||||||
| public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||||||
|  |  | ||||||
|  |     default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) { | ||||||
|  |         return selectCount(new LambdaUpdateWrapper<CrmCustomerDO>() | ||||||
|  |                 .eq(CrmCustomerDO::getLockStatus, lockStatus) | ||||||
|  |                 .eq(CrmCustomerDO::getOwnerUserId, ownerUserId)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     default Long selectCountByDealStatusAndOwnerUserId(@Nullable Boolean dealStatus, Long ownerUserId) { | ||||||
|  |         return selectCount(new LambdaQueryWrapperX<CrmCustomerDO>() | ||||||
|  |                 .eqIfPresent(CrmCustomerDO::getDealStatus, dealStatus) | ||||||
|  |                 .eq(CrmCustomerDO::getOwnerUserId, ownerUserId)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     default int updateOwnerUserIdById(Long id, Long ownerUserId) { |     default int updateOwnerUserIdById(Long id, Long ownerUserId) { | ||||||
|         return update(new LambdaUpdateWrapper<CrmCustomerDO>() |         return update(new LambdaUpdateWrapper<CrmCustomerDO>() | ||||||
|                 .eq(CrmCustomerDO::getId, id) |                 .eq(CrmCustomerDO::getId, id) | ||||||
|  | |||||||
| @ -5,9 +5,10 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmC | |||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO; | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO; | ||||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; | ||||||
|  |  | ||||||
| import jakarta.validation.Valid; | import jakarta.validation.Valid; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 客户限制配置 Service 接口 |  * 客户限制配置 Service 接口 | ||||||
|  * |  * | ||||||
| @ -54,8 +55,11 @@ public interface CrmCustomerLimitConfigService { | |||||||
|     PageResult<CrmCustomerLimitConfigDO> getCustomerLimitConfigPage(CrmCustomerLimitConfigPageReqVO pageReqVO); |     PageResult<CrmCustomerLimitConfigDO> getCustomerLimitConfigPage(CrmCustomerLimitConfigPageReqVO pageReqVO); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询当前登录人客户限制配置 |      * 查询用户对应的配置列表 | ||||||
|  |      * | ||||||
|  |      * @param type 类型 | ||||||
|  |      * @param userId 用户类型 | ||||||
|      */ |      */ | ||||||
|     CrmCustomerLimitConfigDO selectByLimitConfig(CrmCustomerLimitConfigCreateReqVO configReqVO); |     List<CrmCustomerLimitConfigDO> getCustomerLimitConfigListByUserId(Integer type, Long userId); | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| package cn.iocoder.yudao.module.crm.service.customer; | package cn.iocoder.yudao.module.crm.service.customer; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.lang.Assert; | ||||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; | 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 | |||||||
| import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerLimitConfigMapper; | import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerLimitConfigMapper; | ||||||
| import cn.iocoder.yudao.module.system.api.dept.DeptApi; | import cn.iocoder.yudao.module.system.api.dept.DeptApi; | ||||||
| import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||||||
|  | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
|  |  | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
| import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||||
| import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_LIMIT_CONFIG_NOT_EXISTS; | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_LIMIT_CONFIG_NOT_EXISTS; | ||||||
| @ -30,6 +33,7 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig | |||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private CrmCustomerLimitConfigMapper customerLimitConfigMapper; |     private CrmCustomerLimitConfigMapper customerLimitConfigMapper; | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private DeptApi deptApi; |     private DeptApi deptApi; | ||||||
|     @Resource |     @Resource | ||||||
| @ -91,8 +95,10 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public CrmCustomerLimitConfigDO selectByLimitConfig(CrmCustomerLimitConfigCreateReqVO configReqVO) { |     public List<CrmCustomerLimitConfigDO> getCustomerLimitConfigListByUserId(Integer type, Long userId) { | ||||||
|         return customerLimitConfigMapper.selectByLimitConfig(configReqVO); |         AdminUserRespDTO user = adminUserApi.getUser(userId); | ||||||
|  |         Assert.notNull(user, "用户({})不存在", userId); | ||||||
|  |         return customerLimitConfigMapper.selectListByTypeAndUserIdAndDeptId(type, userId, user.getDeptId()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -83,8 +83,9 @@ public interface CrmCustomerService { | |||||||
|      * 锁定/解锁客户 |      * 锁定/解锁客户 | ||||||
|      * |      * | ||||||
|      * @param lockReqVO 更新信息 |      * @param lockReqVO 更新信息 | ||||||
|  |      * @param userId 用户编号 | ||||||
|      */ |      */ | ||||||
|     void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO); |     void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO, Long userId); | ||||||
|  |  | ||||||
|     // ==================== 公海相关操作 ==================== |     // ==================== 公海相关操作 ==================== | ||||||
|  |  | ||||||
|  | |||||||
| @ -2,13 +2,9 @@ package cn.iocoder.yudao.module.crm.service.customer; | |||||||
|  |  | ||||||
| import cn.hutool.core.collection.CollUtil; | import cn.hutool.core.collection.CollUtil; | ||||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||||
|  | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||||
| import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; |  | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; |  | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; |  | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO; |  | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; |  | ||||||
| import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; | 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.customer.CrmCustomerDO; | ||||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; | 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 | |||||||
| import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | ||||||
| import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | ||||||
| import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||||||
| import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |  | ||||||
| import com.mzt.logapi.context.LogRecordContext; | import com.mzt.logapi.context.LogRecordContext; | ||||||
| import com.mzt.logapi.service.impl.DiffParseFunction; | import com.mzt.logapi.service.impl.DiffParseFunction; | ||||||
| import com.mzt.logapi.starter.annotation.LogRecord; | import com.mzt.logapi.starter.annotation.LogRecord; | ||||||
| import com.mzt.logapi.starter.annotation.LogRecord; |  | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| import org.springframework.transaction.annotation.Transactional; | import org.springframework.transaction.annotation.Transactional; | ||||||
| @ -33,13 +27,11 @@ import java.time.LocalDateTime; | |||||||
| import java.util.*; | import java.util.*; | ||||||
|  |  | ||||||
| import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||||
| import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |  | ||||||
| import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; | ||||||
| import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; | import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; | ||||||
| import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.TRANSFER_CUSTOMER_LOG_SUCCESS; | import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.TRANSFER_CUSTOMER_LOG_SUCCESS; | ||||||
| import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_EXCEED_LOCK_LIMIT; |  | ||||||
| import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; | import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; | ||||||
| import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; | import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_OWNER_LIMIT; | ||||||
| import static java.util.Collections.singletonList; | import static java.util.Collections.singletonList; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @ -55,29 +47,32 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | |||||||
|     private CrmCustomerMapper customerMapper; |     private CrmCustomerMapper customerMapper; | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private CrmPermissionService crmPermissionService; |     private CrmPermissionService permissionService; | ||||||
|     @Resource |     @Resource | ||||||
|     private CrmCustomerLimitConfigService crmCustomerLimitConfigService; |     private CrmCustomerLimitConfigService customerLimitConfigService; | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private AdminUserApi adminUserApi; |     private AdminUserApi adminUserApi; | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(rollbackFor = Exception.class) |     @Transactional(rollbackFor = Exception.class) | ||||||
|     @LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户") // TODO @puhui999:客户名字,要记录进去;不然在展示操作日志的全列表,看不清楚是哪个客户哈; |     @LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户") // TODO @puhui999:创建了客户【客户名】,要记录进去;不然在展示操作日志的全列表,看不清楚是哪个客户哈; | ||||||
|     public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { |     public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { | ||||||
|         // 插入客户 |         // 1. 校验拥有客户是否到达上限 | ||||||
|  |         validateCustomerExceedOwnerLimit(createReqVO.getOwnerUserId(), 1); | ||||||
|  |  | ||||||
|  |         // 2. 插入客户 | ||||||
|         CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO) |         CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO) | ||||||
|                 .setLockStatus(false).setDealStatus(false) |                 .setLockStatus(false).setDealStatus(false) | ||||||
|                 .setContactLastTime(LocalDateTime.now()); |                 .setContactLastTime(LocalDateTime.now()); | ||||||
|         // TODO @puhui999:可能要加个 receiveTime 字段,记录最后接收时间 |         // TODO @puhui999:可能要加个 receiveTime 字段,记录最后接收时间 | ||||||
|         customerMapper.insert(customer); |         customerMapper.insert(customer); | ||||||
|  |  | ||||||
|         // 创建数据权限 |         // 3. 创建数据权限 | ||||||
|         crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) |         permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) | ||||||
|                 .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 |                 .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 | ||||||
|  |  | ||||||
|         // 记录操作日志 |         // 4. 记录操作日志 | ||||||
|         LogRecordContext.putVariable("customerId", customer.getId()); |         LogRecordContext.putVariable("customerId", customer.getId()); | ||||||
|         return customer.getId(); |         return customer.getId(); | ||||||
|     } |     } | ||||||
| @ -88,14 +83,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | |||||||
|     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) |     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) | ||||||
|     public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { |     public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { | ||||||
|         // TODO @puhui999:更新的时候,要把 updateReqVO 负责人设置为空,避免修改。 |         // TODO @puhui999:更新的时候,要把 updateReqVO 负责人设置为空,避免修改。 | ||||||
|         // 校验存在 |         // 1. 校验存在 | ||||||
|         CrmCustomerDO oldCustomer = validateCustomerExists(updateReqVO.getId()); |         CrmCustomerDO oldCustomer = validateCustomerExists(updateReqVO.getId()); | ||||||
|  |  | ||||||
|         // 更新 |         // 2. 更新客户 | ||||||
|         CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); |         CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); | ||||||
|         customerMapper.updateById(updateObj); |         customerMapper.updateById(updateObj); | ||||||
|  |  | ||||||
|         // 记录操作日志 |         // 3. 记录操作日志 | ||||||
|         LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerUpdateReqVO.class)); |         LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerUpdateReqVO.class)); | ||||||
|         // TODO 扩展信息测试 @puhui999:看着没啥问题,可以删除啦; |         // TODO 扩展信息测试 @puhui999:看着没啥问题,可以删除啦; | ||||||
|         HashMap<String, Object> extra = new HashMap<>(); |         HashMap<String, Object> extra = new HashMap<>(); | ||||||
| @ -114,7 +109,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | |||||||
|         // 删除 |         // 删除 | ||||||
|         customerMapper.deleteById(id); |         customerMapper.deleteById(id); | ||||||
|         // 删除数据权限 |         // 删除数据权限 | ||||||
|         crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); |         permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private CrmCustomerDO validateCustomerExists(Long id) { |     private CrmCustomerDO validateCustomerExists(Long id) { | ||||||
| @ -159,63 +154,83 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | |||||||
|     @LogRecord(type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) |     @LogRecord(type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) | ||||||
|     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) |     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) | ||||||
|     public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { |     public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { | ||||||
|         // 1. 校验客户是否存在 |         // 1.1 校验客户是否存在 | ||||||
|         CrmCustomerDO customerDO = validateCustomerExists(reqVO.getId()); |         CrmCustomerDO customer = validateCustomerExists(reqVO.getId()); | ||||||
|  |         // 1.2 校验拥有客户是否到达上限 | ||||||
|  |         validateCustomerExceedOwnerLimit(reqVO.getNewOwnerUserId(), 1); | ||||||
|  |  | ||||||
|         // 2.1 数据权限转移 |         // 2.1 数据权限转移 | ||||||
|         crmPermissionService.transferPermission( |         permissionService.transferPermission( | ||||||
|                 CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); |                 CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); | ||||||
|         // 2.2 转移后重新设置负责人 |         // 2.2 转移后重新设置负责人 | ||||||
|         customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); |         customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); | ||||||
|  |  | ||||||
|         // 3. TODO 记录转移日志 |         // 3. TODO 记录转移日志 | ||||||
|         LogRecordContext.putVariable("crmCustomer", customerDO); |         LogRecordContext.putVariable("crmCustomer", customer); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|  |     // TODO @puhui999:看看这个能不能根据条件,写操作日志; | ||||||
|  |     // TODO 如果是 锁定,则 subType 为 锁定客户;success 为 将客户【】锁定 | ||||||
|  |     // TODO 如果是 解锁,则 subType 为 解锁客户;success 为 将客户【】解锁 | ||||||
|     @LogRecord(type = CRM_CUSTOMER, subType = "锁定/解锁客户", bizNo = "{{#updateReqVO.id}}", success = "锁定了客户") |     @LogRecord(type = CRM_CUSTOMER, subType = "锁定/解锁客户", bizNo = "{{#updateReqVO.id}}", success = "锁定了客户") | ||||||
|     public void lockCustomer(CrmCustomerLockReqVO lockReqVO) { |     // TODO @puhui999:数据权限 | ||||||
|         // 校验当前客户是否存在 |     public void lockCustomer(CrmCustomerLockReqVO lockReqVO, Long userId) { | ||||||
|  |         // 1.1 校验当前客户是否存在 | ||||||
|         validateCustomerExists(lockReqVO.getId()); |         validateCustomerExists(lockReqVO.getId()); | ||||||
|  |         // 1.2 校验当前是否重复操作锁定/解锁状态 | ||||||
|         CrmCustomerDO customerDO = customerMapper.selectById(lockReqVO.getId()); |         CrmCustomerDO customer = customerMapper.selectById(lockReqVO.getId()); | ||||||
|  |         if (customer.getLockStatus().equals(lockReqVO.getLockStatus())) { | ||||||
|         // 校验当前是否重复操作锁定/解锁状态 |             throw exception(customer.getLockStatus() ? CUSTOMER_LOCK_FAIL_IS_LOCK : CUSTOMER_UNLOCK_FAIL_IS_UNLOCK); | ||||||
|         if (customerDO.getLockStatus().equals(lockReqVO.getLockStatus())) { |         } | ||||||
|             throw exception(CUSTOMER_UNLOCK_STATUS_NO_REPETITION); |         // 1.3 校验锁定上限。 | ||||||
|  |         if (lockReqVO.getLockStatus()) { | ||||||
|  |             validateCustomerExceedLockLimit(userId); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 获取当前登录信息,开始校验锁定上限 |         // 2. 更新锁定状态 | ||||||
|         AdminUserRespDTO userRespDTO = adminUserApi.getUser(getLoginUserId()); |         customerMapper.updateById(BeanUtils.toBean(lockReqVO, CrmCustomerDO.class)); | ||||||
|  |  | ||||||
|         if (userRespDTO.getDeptId() == null || userRespDTO.getId() == null) { |  | ||||||
|             // 如有入参为空,提示业务异常 |  | ||||||
|             throw exception(CUSTOMER_NO_DEPARTMENT_FOUND); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|         // 开始校验规则限制 |     /** | ||||||
|         List<Long> userDeptIds = Collections.singletonList(userRespDTO.getDeptId()); |      * 校验用户拥有的客户数量,是否到达上限 | ||||||
|  |      * | ||||||
|         CrmCustomerLimitConfigCreateReqVO configReqVO = new CrmCustomerLimitConfigCreateReqVO(); |      * @param userId 用户编号 | ||||||
|         configReqVO.setUserId(userRespDTO.getId()); |      * @param newCount 附加数量 | ||||||
|         configReqVO.setDeptIds(userDeptIds); |      */ | ||||||
|         configReqVO.setType(CUSTOMER_LOCK_LIMIT.getCode()); |     private void validateCustomerExceedOwnerLimit(Long userId, int newCount) { | ||||||
|  |         List<CrmCustomerLimitConfigDO> limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId( | ||||||
|         CrmCustomerLimitConfigDO crmCustomerLimitConfigDO = crmCustomerLimitConfigService.selectByLimitConfig(configReqVO); |                 CUSTOMER_OWNER_LIMIT.getType(), userId); | ||||||
|  |         if (CollUtil.isEmpty(limitConfigs)) { | ||||||
|         // 统计当前用户已锁定客户数量 |             return; | ||||||
|         List<CrmCustomerDO> crmCustomerDOS = customerMapper.selectList("owner_user_id", getLoginUserId()); |         } | ||||||
|         long customerLockCount = crmCustomerDOS.stream().filter(CrmCustomerDO::getLockStatus).count(); |         Long ownerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(null, userId); | ||||||
|  |         Long dealOwnerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(true, userId); | ||||||
|         // 锁定操作的时候校验当前用户可锁定客户的上限 |         limitConfigs.forEach(limitConfig -> { | ||||||
|         if (crmCustomerLimitConfigDO != null && lockReqVO.getLockStatus() && customerLockCount >= crmCustomerLimitConfigDO.getMaxCount()) { |             long nowCount = limitConfig.getDealCountEnabled() ? ownerCount : ownerCount - dealOwnerCount; | ||||||
|             // 超出锁定数量上限,提示业务异常 |             if (nowCount + newCount > limitConfig.getMaxCount()) { | ||||||
|             throw exception(CUSTOMER_EXCEED_LOCK_LIMIT); |                 throw exception(CUSTOMER_OWNER_EXCEED_LIMIT); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|         // 更新 |     /** | ||||||
|         CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(lockReqVO); |      * 校验用户锁定的客户数量,是否到达上限 | ||||||
|         customerMapper.updateById(updateObj); |      * | ||||||
|  |      * @param userId 用户编号 | ||||||
|  |      */ | ||||||
|  |     private void validateCustomerExceedLockLimit(Long userId) { | ||||||
|  |         List<CrmCustomerLimitConfigDO> limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId( | ||||||
|  |                 CUSTOMER_LOCK_LIMIT.getType(), userId); | ||||||
|  |         if (CollUtil.isEmpty(limitConfigs)) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         Long lockCount = customerMapper.selectCountByLockStatusAndOwnerUserId(true, userId); | ||||||
|  |         Integer maxCount = CollectionUtils.getMaxValue(limitConfigs, CrmCustomerLimitConfigDO::getMaxCount); | ||||||
|  |         assert maxCount != null; | ||||||
|  |         if (lockCount >= maxCount) { | ||||||
|  |             throw exception(CUSTOMER_LOCK_EXCEED_LIMIT); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
| @ -239,7 +254,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | |||||||
|             throw exception(CUSTOMER_UPDATE_OWNER_USER_FAIL); |             throw exception(CUSTOMER_UPDATE_OWNER_USER_FAIL); | ||||||
|         } |         } | ||||||
|         // 3. 删除负责人数据权限 |         // 3. 删除负责人数据权限 | ||||||
|         crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(), |         permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(), | ||||||
|                 CrmPermissionLevelEnum.OWNER.getLevel()); |                 CrmPermissionLevelEnum.OWNER.getLevel()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -262,6 +277,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | |||||||
|             // 校验成交状态 |             // 校验成交状态 | ||||||
|             validateCustomerDeal(customer); |             validateCustomerDeal(customer); | ||||||
|         }); |         }); | ||||||
|  |         // 1.4  校验负责人是否到达上限 | ||||||
|  |         validateCustomerExceedOwnerLimit(ownerUserId, customers.size()); | ||||||
|  |  | ||||||
|         // 2. 领取公海数据 |         // 2. 领取公海数据 | ||||||
|         List<CrmCustomerDO> updateCustomers = new ArrayList<>(); |         List<CrmCustomerDO> updateCustomers = new ArrayList<>(); | ||||||
| @ -277,7 +294,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | |||||||
|         // 3.1 更新客户负责人 |         // 3.1 更新客户负责人 | ||||||
|         customerMapper.updateBatch(updateCustomers); |         customerMapper.updateBatch(updateCustomers); | ||||||
|         // 3.2 创建负责人数据权限 |         // 3.2 创建负责人数据权限 | ||||||
|         crmPermissionService.createPermissionBatch(createPermissions); |         permissionService.createPermissionBatch(createPermissions); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void validateCustomerOwnerExists(CrmCustomerDO customer, Boolean pool) { |     private void validateCustomerOwnerExists(CrmCustomerDO customer, Boolean pool) { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV