mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-01 02:38:43 +08:00 
			
		
		
		
	✨ CRM:优化客户的 backlog 逻辑
This commit is contained in:
		| @@ -174,15 +174,15 @@ public class CrmCustomerController { | ||||
|         return success(customerService.getPutPoolRemindCustomerCount(getLoginUserId())); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/today-customer-count") | ||||
|     @GetMapping("/today-contact-count") | ||||
|     @Operation(summary = "获得今日需联系客户数量") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:query')") | ||||
|     public CommonResult<Long> getTodayCustomerCount() { | ||||
|         return success(customerService.getTodayCustomerCount(getLoginUserId())); | ||||
|     public CommonResult<Long> getTodayContactCustomerCount() { | ||||
|         return success(customerService.getTodayContactCustomerCount(getLoginUserId())); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/follow-customer-count") | ||||
|     @Operation(summary = "获得分配给我的客户数量") | ||||
|     @GetMapping("/follow-count") | ||||
|     @Operation(summary = "获得分配给我、待跟进的线索数量的客户数量") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:query')") | ||||
|     public CommonResult<Long> getFollowCustomerCount() { | ||||
|         return success(customerService.getFollowCustomerCount(getLoginUserId())); | ||||
| @@ -222,9 +222,9 @@ public class CrmCustomerController { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @GetMapping(value = "/list-all-simple") | ||||
|     @GetMapping(value = "/simple-list") | ||||
|     @Operation(summary = "获取客户精简信息列表", description = "只包含有读权限的客户,主要用于前端的下拉选项") | ||||
|     public CommonResult<List<CrmCustomerRespVO>> getSimpleDeptList() { | ||||
|     public CommonResult<List<CrmCustomerRespVO>> getCustomerSimpleList() { | ||||
|         CrmCustomerPageReqVO reqVO = new CrmCustomerPageReqVO(); | ||||
|         reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 | ||||
|         List<CrmCustomerDO> list = customerService.getCustomerPage(reqVO, getLoginUserId()).getList(); | ||||
| @@ -232,7 +232,6 @@ public class CrmCustomerController { | ||||
|                 new CrmCustomerRespVO().setId(customer.getId()).setName(customer.getName()))); | ||||
|     } | ||||
|  | ||||
|     // TODO @puhui999:公海的导出,前端可以接下 | ||||
|     @GetMapping("/export-excel") | ||||
|     @Operation(summary = "导出客户 Excel") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:export')") | ||||
|   | ||||
| @@ -49,11 +49,11 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||||
|                 .set(CrmCustomerDO::getOwnerUserId, ownerUserId)); | ||||
|     } | ||||
|  | ||||
|     default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { | ||||
|     default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long ownerUserId) { | ||||
|         MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | ||||
|         // 拼接数据权限的查询条件 | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), | ||||
|                 CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | ||||
|                 CrmCustomerDO::getId, ownerUserId, pageReqVO.getSceneType(), pageReqVO.getPool()); | ||||
|         // 拼接自身的查询条件 | ||||
|         query.selectAll(CrmCustomerDO.class) | ||||
|                 .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) | ||||
| @@ -81,10 +81,10 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||||
|         return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); | ||||
|     } | ||||
|  | ||||
|     default List<CrmCustomerDO> selectBatchIds(Collection<Long> ids, Long userId) { | ||||
|     default List<CrmCustomerDO> selectBatchIds(Collection<Long> ids, Long ownerUserId) { | ||||
|         MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | ||||
|         // 拼接数据权限的查询条件 | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId); | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, ownerUserId); | ||||
|         // 拼接自身的查询条件 | ||||
|         query.selectAll(CrmCustomerDO.class).in(CrmCustomerDO::getId, ids).orderByDesc(CrmCustomerDO::getId); | ||||
|         return selectJoinList(CrmCustomerDO.class, query); | ||||
| @@ -96,8 +96,8 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||||
|  | ||||
|     default PageResult<CrmCustomerDO> selectPutPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, | ||||
|                                                                       CrmCustomerPoolConfigDO poolConfig, | ||||
|                                                                       Long userId) { | ||||
|         final MPJLambdaWrapperX<CrmCustomerDO> query = buildPutPoolRemindCustomerQuery(pageReqVO, poolConfig, userId); | ||||
|                                                                       Long ownerUserId) { | ||||
|         final MPJLambdaWrapperX<CrmCustomerDO> query = buildPutPoolRemindCustomerQuery(pageReqVO, poolConfig, ownerUserId); | ||||
|         return selectJoinPage(pageReqVO, CrmCustomerDO.class, query.selectAll(CrmCustomerDO.class)); | ||||
|     } | ||||
|  | ||||
| @@ -110,11 +110,11 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||||
|  | ||||
|     private static MPJLambdaWrapperX<CrmCustomerDO> buildPutPoolRemindCustomerQuery(CrmCustomerPageReqVO pageReqVO, | ||||
|                                                                                     CrmCustomerPoolConfigDO poolConfig, | ||||
|                                                                                     Long userId) { | ||||
|                                                                                     Long ownerUserId) { | ||||
|         MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | ||||
|         // 拼接数据权限的查询条件 | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), | ||||
|                 CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); | ||||
|                 CrmCustomerDO::getId, ownerUserId, pageReqVO.getSceneType(), null); | ||||
|  | ||||
|         // 未锁定 + 未成交 | ||||
|         query.eq(CrmCustomerDO::getLockStatus, false).eq(CrmCustomerDO::getDealStatus, false); | ||||
| @@ -164,11 +164,11 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||||
|         return selectList(query); | ||||
|     } | ||||
|  | ||||
|     default Long selectTodayCustomerCount(Long userId) { | ||||
|     default Long selectCountByTodayContact(Long ownerUserId) { | ||||
|         MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | ||||
|         // 我负责的 + 非公海 | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), | ||||
|                 CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); | ||||
|                 CrmCustomerDO::getId, ownerUserId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); | ||||
|         // 今天需联系 | ||||
|         LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); | ||||
|         LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); | ||||
| @@ -176,11 +176,11 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||||
|         return selectCount(query); | ||||
|     } | ||||
|  | ||||
|     default Long selectFollowCustomerCount(Long userId) { | ||||
|     default Long selectCountByFollow(Long ownerUserId) { | ||||
|         MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | ||||
|         // 我负责的 + 非公海 | ||||
|         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), | ||||
|                 CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); | ||||
|                 CrmCustomerDO::getId, ownerUserId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); | ||||
|         // 未跟进 | ||||
|         query.eq(CrmClueDO::getFollowUpStatus, false); | ||||
|         return selectCount(query); | ||||
|   | ||||
| @@ -113,6 +113,22 @@ public interface CrmCustomerService { | ||||
|      */ | ||||
|     Long getPutPoolRemindCustomerCount(Long userId); | ||||
|  | ||||
|     /** | ||||
|      * 获得今日需联系客户数量 | ||||
|      * | ||||
|      * @param userId 用户编号 | ||||
|      * @return 提醒数量 | ||||
|      */ | ||||
|     Long getTodayContactCustomerCount(Long userId); | ||||
|  | ||||
|     /** | ||||
|      * 获得分配给我的客户数量 | ||||
|      * | ||||
|      * @param userId 用户编号 | ||||
|      * @return 提醒数量 | ||||
|      */ | ||||
|     Long getFollowCustomerCount(Long userId); | ||||
|  | ||||
|     /** | ||||
|      * 校验客户是否存在 | ||||
|      * | ||||
| @@ -168,7 +184,7 @@ public interface CrmCustomerService { | ||||
|      * | ||||
|      * @param ids         要领取的客户编号数组 | ||||
|      * @param ownerUserId 负责人 | ||||
|      * @param isReceive   是/否领取 | ||||
|      * @param isReceive   是/否领取;true - 领取;false - 分配 | ||||
|      */ | ||||
|     void receiveCustomer(List<Long> ids, Long ownerUserId, Boolean isReceive); | ||||
|  | ||||
| @@ -179,20 +195,4 @@ public interface CrmCustomerService { | ||||
|      */ | ||||
|     int autoPutCustomerPool(); | ||||
|  | ||||
|     /** | ||||
|      * 获得今日需联系客户数量 | ||||
|      * | ||||
|      * @param userId 用户编号 | ||||
|      * @return 提醒数量 | ||||
|      */ | ||||
|     Long getTodayCustomerCount(Long userId); | ||||
|  | ||||
|     /** | ||||
|      * 获得分配给我的客户数量 | ||||
|      * | ||||
|      * @param userId 用户编号 | ||||
|      * @return 提醒数量 | ||||
|      */ | ||||
|     Long getFollowCustomerCount(Long userId); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -18,7 +18,6 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | ||||
| import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; | ||||
| import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | ||||
| import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; | ||||
| import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; | ||||
| import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; | ||||
| import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; | ||||
| import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; | ||||
| @@ -191,23 +190,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|         LogRecordContext.putVariable("customerName", customer.getName()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 校验客户是否被引用 | ||||
|      * | ||||
|      * @param id 客户编号 | ||||
|      */ | ||||
|     private void validateCustomerReference(Long id) { | ||||
|         if (contactService.getContactCountByCustomerId(id) > 0) { | ||||
|             throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_CONTACT.getName()); | ||||
|         } | ||||
|         if (businessService.getBusinessCountByCustomerId(id) > 0) { | ||||
|             throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_BUSINESS.getName()); | ||||
|         } | ||||
|         if (contractService.getContractCountByCustomerId(id) > 0) { | ||||
|             throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_CONTRACT.getName()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}", | ||||
| @@ -336,13 +318,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|         LogRecordContext.putVariable("isUpdate", isUpdate); | ||||
|     } | ||||
|  | ||||
|     private void validateCustomerForCreate(CrmCustomerImportExcelVO importCustomer) { | ||||
|         // 校验客户名称不能为空 | ||||
|         if (StrUtil.isEmptyIfStr(importCustomer.getName())) { | ||||
|             throw exception(CUSTOMER_CREATE_NAME_NOT_NULL); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // ==================== 公海相关操作 ==================== | ||||
|  | ||||
|     @Override | ||||
| @@ -371,18 +346,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public void receiveCustomer(List<Long> ids, Long ownerUserId, Boolean isReceive) { | ||||
|         if (!isReceive && !CrmPermissionUtils.isCrmAdmin()) { // 只有管理员可以分配 | ||||
|             throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.CRM_CUSTOMER.getName()); | ||||
|         } | ||||
|  | ||||
|         // 1.1 校验存在 | ||||
|         List<CrmCustomerDO> customers = customerMapper.selectBatchIds(ids); | ||||
|         if (customers.size() != ids.size()) { | ||||
|             throw exception(CUSTOMER_NOT_EXISTS); | ||||
|         } | ||||
|         // 1.2. 校验负责人是否存在 | ||||
|         // 1.2 校验负责人是否存在 | ||||
|         adminUserApi.validateUserList(singletonList(ownerUserId)); | ||||
|         // 1.3. 校验状态 | ||||
|         // 1.3 校验状态 | ||||
|         customers.forEach(customer -> { | ||||
|             // 校验是否已有负责人 | ||||
|             validateCustomerOwnerExists(customer, false); | ||||
| @@ -513,17 +484,41 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Long getTodayCustomerCount(Long userId) { | ||||
|         return customerMapper.selectTodayCustomerCount(userId); | ||||
|     public Long getTodayContactCustomerCount(Long userId) { | ||||
|         return customerMapper.selectCountByTodayContact(userId); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Long getFollowCustomerCount(Long userId) { | ||||
|         return customerMapper.selectFollowCustomerCount(userId); | ||||
|         return customerMapper.selectCountByFollow(userId); | ||||
|     } | ||||
|  | ||||
|     // ======================= 校验相关 ======================= | ||||
|  | ||||
|     private void validateCustomerForCreate(CrmCustomerImportExcelVO importCustomer) { | ||||
|         // 校验客户名称不能为空 | ||||
|         if (StrUtil.isEmptyIfStr(importCustomer.getName())) { | ||||
|             throw exception(CUSTOMER_CREATE_NAME_NOT_NULL); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 校验客户是否被引用 | ||||
|      * | ||||
|      * @param id 客户编号 | ||||
|      */ | ||||
|     private void validateCustomerReference(Long id) { | ||||
|         if (contactService.getContactCountByCustomerId(id) > 0) { | ||||
|             throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_CONTACT.getName()); | ||||
|         } | ||||
|         if (businessService.getBusinessCountByCustomerId(id) > 0) { | ||||
|             throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_BUSINESS.getName()); | ||||
|         } | ||||
|         if (contractService.getContractCountByCustomerId(id) > 0) { | ||||
|             throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_CONTRACT.getName()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 校验客户是否存在 | ||||
|      * | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV