mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-01 02:38:43 +08:00 
			
		
		
		
	!859 feat: CRM-backlog-待进入公海的客户
Merge pull request !859 from dhb52/crm-msg
This commit is contained in:
		| @@ -26,8 +26,8 @@ public interface ErrorCodeConstants { | |||||||
|  |  | ||||||
|     // ========== 联系人管理 1-020-003-000 ========== |     // ========== 联系人管理 1-020-003-000 ========== | ||||||
|     ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); |     ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); | ||||||
|     ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode( 1_020_003_001, "联系人商机关联不存在"); |     ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在"); | ||||||
|     ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode( 1_020_003_002, "联系人已关联合同,不能删除"); |     ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode(1_020_003_002, "联系人已关联合同,不能删除"); | ||||||
|  |  | ||||||
|     // ========== 回款 1-020-004-000 ========== |     // ========== 回款 1-020-004-000 ========== | ||||||
|     ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); |     ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); | ||||||
| @@ -80,7 +80,8 @@ public interface ErrorCodeConstants { | |||||||
|     ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_011_000, "商机状态不存在"); |     ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_011_000, "商机状态不存在"); | ||||||
|  |  | ||||||
|     // ========== 客户公海规则设置 1_020_012_000 ========== |     // ========== 客户公海规则设置 1_020_012_000 ========== | ||||||
|     ErrorCode CUSTOMER_LIMIT_CONFIG_NOT_EXISTS = new ErrorCode(1_020_012_000, "客户限制配置不存在"); |     ErrorCode CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED = new ErrorCode(1_020_012_000, "客户公海配置不存在或未启用"); | ||||||
|  |     ErrorCode CUSTOMER_LIMIT_CONFIG_NOT_EXISTS = new ErrorCode(1_020_012_001, "客户限制配置不存在"); | ||||||
|  |  | ||||||
|     // ========== 跟进记录 1_020_013_000 ========== |     // ========== 跟进记录 1_020_013_000 ========== | ||||||
|     ErrorCode FOLLOW_UP_RECORD_NOT_EXISTS = new ErrorCode(1_020_013_000, "跟进记录不存在"); |     ErrorCode FOLLOW_UP_RECORD_NOT_EXISTS = new ErrorCode(1_020_013_000, "跟进记录不存在"); | ||||||
|   | |||||||
| @@ -36,11 +36,13 @@ import java.util.List; | |||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.stream.Stream; | import java.util.stream.Stream; | ||||||
|  |  | ||||||
|  | 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.pojo.CommonResult.success; | ||||||
| import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; | import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; | ||||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | ||||||
| import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | ||||||
| import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||||||
|  | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED; | ||||||
|  |  | ||||||
| @Tag(name = "管理后台 - CRM 客户") | @Tag(name = "管理后台 - CRM 客户") | ||||||
| @RestController | @RestController | ||||||
| @@ -118,6 +120,35 @@ public class CrmCustomerController { | |||||||
|         return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap)); |         return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @GetMapping("/put-in-pool-remind-page") | ||||||
|  |     @Operation(summary = "获得待进入公海客户分页") | ||||||
|  |     @PreAuthorize("@ss.hasPermission('crm:customer:query')") | ||||||
|  |     public CommonResult<PageResult<CrmCustomerRespVO>> getPutInPoolRemindCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { | ||||||
|  |         // 获取公海配置 | ||||||
|  |         CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig(); | ||||||
|  |         if (ObjUtil.isNull(poolConfigDO) | ||||||
|  |                 || Boolean.FALSE.equals(poolConfigDO.getEnabled()) | ||||||
|  |                 || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled()) | ||||||
|  |         ) { | ||||||
|  |             throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 1. 查询客户分页 | ||||||
|  |         PageResult<CrmCustomerDO> pageResult = customerService.getPutInPoolRemindCustomerPage(pageVO, poolConfigDO, getLoginUserId()); | ||||||
|  |         if (CollUtil.isEmpty(pageResult.getList())) { | ||||||
|  |             return success(PageResult.empty(pageResult.getTotal())); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 2. 拼接数据 | ||||||
|  |         Map<Long, Long> poolDayMap = getPoolDayMap(pageResult.getList()); // 客户界面,需要查看距离进入公海的时间 | ||||||
|  |         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||||||
|  |                 convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId()))); | ||||||
|  |         Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); | ||||||
|  |  | ||||||
|  |         return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 获取距离进入公海的时间 |      * 获取距离进入公海的时间 | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; | |||||||
| import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; | import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; | ||||||
| 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; | ||||||
|  | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; | ||||||
| import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 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.query.LambdaQueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
| @@ -107,4 +108,55 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | |||||||
|                 .isNotNull(CrmCustomerDO::getOwnerUserId)); |                 .isNotNull(CrmCustomerDO::getOwnerUserId)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     default PageResult<CrmCustomerDO> selectPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, | ||||||
|  |                                                                         CrmCustomerPoolConfigDO poolConfigDO, | ||||||
|  |                                                                         Long userId) { | ||||||
|  |         MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | ||||||
|  |         // 拼接数据权限的查询条件 | ||||||
|  |         CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), | ||||||
|  |                 CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); | ||||||
|  |  | ||||||
|  |         // 拼接自身的查询条件 | ||||||
|  |         query.selectAll(CrmCustomerDO.class); | ||||||
|  |  | ||||||
|  |         // 未跟进放入公海天数 | ||||||
|  |         final Integer contactExpireDays = poolConfigDO.getContactExpireDays(); | ||||||
|  |         // 未成交放入公海天数 | ||||||
|  |         final Integer dealExpireDays = poolConfigDO.getDealExpireDays(); | ||||||
|  |         // 提前提醒天数 | ||||||
|  |         final Integer notifyDays = poolConfigDO.getNotifyDays(); | ||||||
|  |  | ||||||
|  |         // 未成交提醒日期区间 | ||||||
|  |         // dealExpireDays 开始提醒 | ||||||
|  |         LocalDateTime startDealRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) | ||||||
|  |                 .minusDays(dealExpireDays); | ||||||
|  |         // dealExpireDays - notifyDays 结束提醒 | ||||||
|  |         LocalDateTime endDealRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) | ||||||
|  |                 .minusDays(Math.max(dealExpireDays - notifyDays, 0)); | ||||||
|  |  | ||||||
|  |         // 未跟进提醒日期区间 | ||||||
|  |         // contactExpireDays 开始提醒 | ||||||
|  |         LocalDateTime startContactRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) | ||||||
|  |                 .minusDays(contactExpireDays); | ||||||
|  |         // contactExpireDays - notifyDays 结束提醒 | ||||||
|  |         LocalDateTime endContactRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) | ||||||
|  |                 .minusDays(Math.max(contactExpireDays - notifyDays, 0)); | ||||||
|  |  | ||||||
|  |         query | ||||||
|  |                 // 1.1 未成交放入公海提醒 | ||||||
|  |                 .eq(CrmCustomerDO::getDealStatus, false) | ||||||
|  |                 .between(CrmCustomerDO::getCreateTime, startDealRemindDate, endDealRemindDate) | ||||||
|  |                 .or() | ||||||
|  |                 // 1.2 未跟进放入公海提醒 | ||||||
|  |                 // 1.2.1 ContactLastTime 为空 | ||||||
|  |                 .isNull(CrmCustomerDO::getContactLastTime) | ||||||
|  |                 .between(CrmCustomerDO::getCreateTime, startContactRemindDate, endContactRemindDate) | ||||||
|  |                 .or() | ||||||
|  |                 // 1.2.2 ContactLastTime 不为空 | ||||||
|  |                 .between(CrmCustomerDO::getContactLastTime, startContactRemindDate, endContactRemindDate) | ||||||
|  |         ; | ||||||
|  |  | ||||||
|  |         return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageR | |||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; | ||||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; | ||||||
| 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.CrmCustomerPoolConfigDO; | ||||||
| import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; | import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; | ||||||
| import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; | import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; | ||||||
| import jakarta.validation.Valid; | import jakarta.validation.Valid; | ||||||
| @@ -134,4 +135,7 @@ public interface CrmCustomerService { | |||||||
|      */ |      */ | ||||||
|     int customerAutoPutPoolBySystem(); |     int customerAutoPutPoolBySystem(); | ||||||
|  |  | ||||||
|  |     PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, | ||||||
|  |                                                              CrmCustomerPoolConfigDO poolConfigDO, | ||||||
|  |                                                              Long loginUserId); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -387,6 +387,12 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | |||||||
|         return customerMapper.selectPage(pageReqVO, userId); |         return customerMapper.selectPage(pageReqVO, userId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, | ||||||
|  |                                                                     CrmCustomerPoolConfigDO poolConfigDO, | ||||||
|  |                                                                     Long userId) { | ||||||
|  |         return customerMapper.selectPutInPoolRemindCustomerPage(pageReqVO, poolConfigDO, userId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // ======================= 校验相关 ======================= |     // ======================= 校验相关 ======================= | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 芋道源码
					芋道源码