Commit b444312ea888baa950a829c1105445ab463a9eaf
1 parent
3e652493
✨ CRM:优化客户的过期到公海的逻辑
Showing
9 changed files
with
187 additions
and
183 deletions
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
| ... | ... | @@ -45,6 +45,8 @@ public interface LogRecordConstants { |
| 45 | 45 | String CRM_CUSTOMER_IMPORT_SUCCESS = "{{#isUpdate ? '导入并更新了客户【'+ #customer.name +'】' : '导入了客户【'+ #customer.name +'】'}}"; |
| 46 | 46 | String CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUB_TYPE = "更新客户成交状态"; |
| 47 | 47 | String CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUCCESS = "更新了客户【{{#customerName}}】的成交状态为【{{#dealStatus ? '已成交' : '未成交'}}】"; |
| 48 | + String CRM_CUSTOMER_FOLLOW_UP_SUB_TYPE = "客户跟进"; | |
| 49 | + String CRM_CUSTOMER_FOLLOW_UP_SUCCESS = "客户跟进【{{#customerName}}】"; | |
| 48 | 50 | |
| 49 | 51 | // ======================= CRM_CUSTOMER_LIMIT_CONFIG 客户限制配置 ======================= |
| 50 | 52 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java
| ... | ... | @@ -43,6 +43,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. |
| 43 | 43 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 44 | 44 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 45 | 45 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 46 | +import static java.util.Collections.singletonList; | |
| 46 | 47 | |
| 47 | 48 | @Tag(name = "管理后台 - 线索") |
| 48 | 49 | @RestController |
| ... | ... | @@ -93,11 +94,11 @@ public class CrmClueController { |
| 93 | 94 | return success(buildClueDetail(clue)); |
| 94 | 95 | } |
| 95 | 96 | |
| 96 | - public CrmClueRespVO buildClueDetail(CrmClueDO clue) { | |
| 97 | + private CrmClueRespVO buildClueDetail(CrmClueDO clue) { | |
| 97 | 98 | if (clue == null) { |
| 98 | 99 | return null; |
| 99 | 100 | } |
| 100 | - return buildClueDetailList(Collections.singletonList(clue)).get(0); | |
| 101 | + return buildClueDetailList(singletonList(clue)).get(0); | |
| 101 | 102 | } |
| 102 | 103 | |
| 103 | 104 | @GetMapping("/page") | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
| ... | ... | @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.map.MapUtil; |
| 5 | -import cn.hutool.core.util.ObjUtil; | |
| 6 | 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 7 | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 8 | 8 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| 9 | 9 | import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; |
| 10 | 10 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| ... | ... | @@ -15,7 +15,6 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 15 | 15 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*; |
| 16 | 16 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 17 | 17 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; |
| 18 | -import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; | |
| 19 | 18 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerPoolConfigService; |
| 20 | 19 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 21 | 20 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| ... | ... | @@ -40,13 +39,11 @@ import java.util.List; |
| 40 | 39 | import java.util.Map; |
| 41 | 40 | import java.util.stream.Stream; |
| 42 | 41 | |
| 43 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 44 | 42 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 45 | 43 | import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; |
| 46 | 44 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 47 | 45 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 48 | 46 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 49 | -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED; | |
| 50 | 47 | import static java.util.Collections.singletonList; |
| 51 | 48 | |
| 52 | 49 | @Tag(name = "管理后台 - CRM 客户") |
| ... | ... | @@ -123,6 +120,7 @@ public class CrmCustomerController { |
| 123 | 120 | @Operation(summary = "获得客户分页") |
| 124 | 121 | @PreAuthorize("@ss.hasPermission('crm:customer:query')") |
| 125 | 122 | public CommonResult<PageResult<CrmCustomerRespVO>> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { |
| 123 | + customerService.autoPutCustomerPool(); | |
| 126 | 124 | // 1. 查询客户分页 |
| 127 | 125 | PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(pageVO, getLoginUserId()); |
| 128 | 126 | if (CollUtil.isEmpty(pageResult.getList())) { |
| ... | ... | @@ -159,45 +157,21 @@ public class CrmCustomerController { |
| 159 | 157 | }); |
| 160 | 158 | } |
| 161 | 159 | |
| 162 | - // TODO @芋艿:需要 review 下 | |
| 163 | - @GetMapping("/put-in-pool-remind-page") | |
| 160 | + @GetMapping("/put-pool-remind-page") | |
| 164 | 161 | @Operation(summary = "获得待进入公海客户分页") |
| 165 | 162 | @PreAuthorize("@ss.hasPermission('crm:customer:query')") |
| 166 | - public CommonResult<PageResult<CrmCustomerRespVO>> getPutInPoolRemindCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { | |
| 167 | - // 获取公海配置 TODO @dbh52:合并到 getPutInPoolRemindCustomerPage 会更合适哈; | |
| 168 | - CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig(); | |
| 169 | - if (ObjUtil.isNull(poolConfigDO) | |
| 170 | - || Boolean.FALSE.equals(poolConfigDO.getEnabled()) | |
| 171 | - || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) { | |
| 172 | - throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED); | |
| 173 | - } | |
| 174 | - | |
| 163 | + public CommonResult<PageResult<CrmCustomerRespVO>> getPutPoolRemindCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { | |
| 175 | 164 | // 1. 查询客户分页 |
| 176 | - PageResult<CrmCustomerDO> pageResult = customerService.getPutInPoolRemindCustomerPage(pageVO, poolConfigDO, getLoginUserId()); | |
| 177 | - if (CollUtil.isEmpty(pageResult.getList())) { | |
| 178 | - return success(PageResult.empty(pageResult.getTotal())); | |
| 179 | - } | |
| 180 | - | |
| 165 | + PageResult<CrmCustomerDO> pageResult = customerService.getPutPoolRemindCustomerPage(pageVO, getLoginUserId()); | |
| 181 | 166 | // 2. 拼接数据 |
| 182 | 167 | return success(new PageResult<>(buildCustomerDetailList(pageResult.getList()), pageResult.getTotal())); |
| 183 | 168 | } |
| 184 | 169 | |
| 185 | - @GetMapping("/put-in-pool-remind-count") | |
| 170 | + @GetMapping("/put-pool-remind-count") | |
| 186 | 171 | @Operation(summary = "获得待进入公海客户数量") |
| 187 | 172 | @PreAuthorize("@ss.hasPermission('crm:customer:query')") |
| 188 | - public CommonResult<Long> getPutInPoolRemindCustomerCount() { | |
| 189 | - // 获取公海配置 | |
| 190 | - CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig(); | |
| 191 | - if (ObjUtil.isNull(poolConfigDO) | |
| 192 | - || Boolean.FALSE.equals(poolConfigDO.getEnabled()) | |
| 193 | - || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) { | |
| 194 | - throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED); | |
| 195 | - } | |
| 196 | - CrmCustomerPageReqVO pageVO = new CrmCustomerPageReqVO() | |
| 197 | - .setPool(null) | |
| 198 | - .setContactStatus(CrmCustomerPageReqVO.CONTACT_TODAY) | |
| 199 | - .setSceneType(CrmSceneTypeEnum.OWNER.getType()); | |
| 200 | - return success(customerService.getPutInPoolRemindCustomerCount(pageVO, poolConfigDO, getLoginUserId())); | |
| 173 | + public CommonResult<Long> getPutPoolRemindCustomerCount() { | |
| 174 | + return success(customerService.getPutPoolRemindCustomerCount(getLoginUserId())); | |
| 201 | 175 | } |
| 202 | 176 | |
| 203 | 177 | @GetMapping("/today-customer-count") |
| ... | ... | @@ -225,24 +199,26 @@ public class CrmCustomerController { |
| 225 | 199 | if (poolConfig == null || !poolConfig.getEnabled()) { |
| 226 | 200 | return MapUtil.empty(); |
| 227 | 201 | } |
| 202 | + list = CollectionUtils.filterList(list, customer -> { | |
| 203 | + // 特殊:如果没负责人,则说明已经在公海,不用计算 | |
| 204 | + if (customer.getOwnerUserId() == null) { | |
| 205 | + return false; | |
| 206 | + } | |
| 207 | + // 已成交 or 已锁定,不进入公海 | |
| 208 | + return !customer.getDealStatus() && !customer.getLockStatus(); | |
| 209 | + }); | |
| 228 | 210 | return convertMap(list, CrmCustomerDO::getId, customer -> { |
| 229 | - // TODO 芋艿:这样计算,貌似有点问题 | |
| 230 | 211 | // 1.1 未成交放入公海天数 |
| 231 | - long dealExpireDay = 0; | |
| 232 | - if (!customer.getDealStatus()) { | |
| 233 | - dealExpireDay = poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime()); | |
| 234 | - } | |
| 235 | - if (dealExpireDay < 0) { | |
| 236 | - dealExpireDay = 0; | |
| 237 | - } | |
| 212 | + long dealExpireDay = poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getOwnerTime()); | |
| 238 | 213 | // 1.2 未跟进放入公海天数 |
| 239 | - LocalDateTime lastTime = ObjUtil.defaultIfNull(customer.getContactLastTime(), customer.getCreateTime()); | |
| 240 | - long contactExpireDay = poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime); | |
| 241 | - if (contactExpireDay < 0) { | |
| 242 | - contactExpireDay = 0; | |
| 214 | + LocalDateTime lastTime = customer.getOwnerTime(); | |
| 215 | + if (customer.getContactLastTime() != null && customer.getContactLastTime().isAfter(lastTime)) { | |
| 216 | + lastTime = customer.getContactLastTime(); | |
| 243 | 217 | } |
| 218 | + long contactExpireDay = poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime); | |
| 244 | 219 | // 2. 返回最小的天数 |
| 245 | - return Math.min(dealExpireDay, contactExpireDay); | |
| 220 | + long poolDay = Math.min(dealExpireDay, contactExpireDay); | |
| 221 | + return poolDay > 0 ? poolDay : 0; | |
| 246 | 222 | }); |
| 247 | 223 | } |
| 248 | 224 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
| ... | ... | @@ -31,40 +31,6 @@ import java.util.List; |
| 31 | 31 | @Mapper |
| 32 | 32 | public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { |
| 33 | 33 | |
| 34 | - private static MPJLambdaWrapperX<CrmCustomerDO> buildPutInPoolRemindCustomerWrapper(CrmCustomerPageReqVO pageReqVO, CrmCustomerPoolConfigDO poolConfigDO, Long userId) { | |
| 35 | - MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | |
| 36 | - // 拼接数据权限的查询条件 | |
| 37 | - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), | |
| 38 | - CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); | |
| 39 | - | |
| 40 | - // 锁定状态不需要提醒 | |
| 41 | - query.ne(CrmCustomerDO::getLockStatus, true); | |
| 42 | - | |
| 43 | - // 情况一:未成交提醒日期区间 | |
| 44 | - Integer dealExpireDays = poolConfigDO.getDealExpireDays(); | |
| 45 | - LocalDateTime startDealRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) | |
| 46 | - .minusDays(dealExpireDays); | |
| 47 | - LocalDateTime endDealRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) | |
| 48 | - .minusDays(Math.max(dealExpireDays - poolConfigDO.getNotifyDays(), 0)); | |
| 49 | - // 情况二:未跟进提醒日期区间 | |
| 50 | - Integer contactExpireDays = poolConfigDO.getContactExpireDays(); | |
| 51 | - LocalDateTime startContactRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) | |
| 52 | - .minusDays(contactExpireDays); | |
| 53 | - LocalDateTime endContactRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) | |
| 54 | - .minusDays(Math.max(contactExpireDays - poolConfigDO.getNotifyDays(), 0)); | |
| 55 | - query | |
| 56 | - // 情况一:1. 未成交放入公海提醒 | |
| 57 | - .eq(CrmCustomerDO::getDealStatus, false) | |
| 58 | - .between(CrmCustomerDO::getCreateTime, startDealRemindDate, endDealRemindDate) | |
| 59 | - // 情况二:未跟进放入公海提醒 | |
| 60 | - .or() // 2.1 contactLastTime 为空 TODO 芋艿:这个要不要搞个默认值; | |
| 61 | - .isNull(CrmCustomerDO::getContactLastTime) | |
| 62 | - .between(CrmCustomerDO::getCreateTime, startContactRemindDate, endContactRemindDate) | |
| 63 | - .or() // 2.2 ContactLastTime 不为空 | |
| 64 | - .between(CrmCustomerDO::getContactLastTime, startContactRemindDate, endContactRemindDate); | |
| 65 | - return query; | |
| 66 | - } | |
| 67 | - | |
| 68 | 34 | default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) { |
| 69 | 35 | return selectCount(new LambdaUpdateWrapper<CrmCustomerDO>() |
| 70 | 36 | .eq(CrmCustomerDO::getLockStatus, lockStatus) |
| ... | ... | @@ -124,30 +90,80 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { |
| 124 | 90 | return selectJoinList(CrmCustomerDO.class, query); |
| 125 | 91 | } |
| 126 | 92 | |
| 127 | - default List<CrmCustomerDO> selectListByLockAndNotPool(Boolean lockStatus) { | |
| 128 | - return selectList(new LambdaQueryWrapper<CrmCustomerDO>() | |
| 129 | - .eq(CrmCustomerDO::getLockStatus, lockStatus) | |
| 130 | - .gt(CrmCustomerDO::getOwnerUserId, 0)); | |
| 131 | - } | |
| 132 | - | |
| 133 | 93 | default CrmCustomerDO selectByCustomerName(String name) { |
| 134 | 94 | return selectOne(CrmCustomerDO::getName, name); |
| 135 | 95 | } |
| 136 | 96 | |
| 137 | - default PageResult<CrmCustomerDO> selectPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, | |
| 138 | - CrmCustomerPoolConfigDO poolConfigDO, | |
| 139 | - Long userId) { | |
| 140 | - final MPJLambdaWrapperX<CrmCustomerDO> query = buildPutInPoolRemindCustomerWrapper(pageReqVO, poolConfigDO, userId); | |
| 97 | + default PageResult<CrmCustomerDO> selectPutPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, | |
| 98 | + CrmCustomerPoolConfigDO poolConfig, | |
| 99 | + Long userId) { | |
| 100 | + final MPJLambdaWrapperX<CrmCustomerDO> query = buildPutPoolRemindCustomerQuery(pageReqVO, poolConfig, userId); | |
| 141 | 101 | return selectJoinPage(pageReqVO, CrmCustomerDO.class, query.selectAll(CrmCustomerDO.class)); |
| 142 | 102 | } |
| 143 | 103 | |
| 144 | - default Long selectPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO, | |
| 145 | - CrmCustomerPoolConfigDO poolConfigDO, | |
| 146 | - Long userId) { | |
| 147 | - final MPJLambdaWrapperX<CrmCustomerDO> query = buildPutInPoolRemindCustomerWrapper(pageReqVO, poolConfigDO, userId); | |
| 104 | + default Long selectPutPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO, | |
| 105 | + CrmCustomerPoolConfigDO poolConfigDO, | |
| 106 | + Long userId) { | |
| 107 | + final MPJLambdaWrapperX<CrmCustomerDO> query = buildPutPoolRemindCustomerQuery(pageReqVO, poolConfigDO, userId); | |
| 148 | 108 | return selectCount(query); |
| 149 | 109 | } |
| 150 | 110 | |
| 111 | + private static MPJLambdaWrapperX<CrmCustomerDO> buildPutPoolRemindCustomerQuery(CrmCustomerPageReqVO pageReqVO, | |
| 112 | + CrmCustomerPoolConfigDO poolConfig, | |
| 113 | + Long userId) { | |
| 114 | + MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | |
| 115 | + // 拼接数据权限的查询条件 | |
| 116 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), | |
| 117 | + CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); | |
| 118 | + | |
| 119 | + // 未锁定 + 未成交 | |
| 120 | + query.eq(CrmCustomerDO::getLockStatus, false).eq(CrmCustomerDO::getDealStatus, false); | |
| 121 | + | |
| 122 | + // 情况一:未成交提醒日期区间 | |
| 123 | + Integer dealExpireDays = poolConfig.getDealExpireDays(); | |
| 124 | + LocalDateTime startDealRemindTime = LocalDateTime.now().minusDays(dealExpireDays); | |
| 125 | + LocalDateTime endDealRemindTime = LocalDateTime.now() | |
| 126 | + .minusDays(Math.max(dealExpireDays - poolConfig.getNotifyDays(), 0)); | |
| 127 | + // 情况二:未跟进提醒日期区间 | |
| 128 | + Integer contactExpireDays = poolConfig.getContactExpireDays(); | |
| 129 | + LocalDateTime startContactRemindTime = LocalDateTime.now().minusDays(contactExpireDays); | |
| 130 | + LocalDateTime endContactRemindTime = LocalDateTime.now() | |
| 131 | + .minusDays(Math.max(contactExpireDays - poolConfig.getNotifyDays(), 0)); | |
| 132 | + query.and(q -> { | |
| 133 | + // 情况一:成交超时提醒 | |
| 134 | + q.between(CrmCustomerDO::getOwnerTime, startDealRemindTime, endDealRemindTime) | |
| 135 | + // 情况二:跟进超时提醒 | |
| 136 | + .or(w -> w.between(CrmCustomerDO::getOwnerTime, startContactRemindTime, endContactRemindTime) | |
| 137 | + .and(p -> p.between(CrmCustomerDO::getContactLastTime, startContactRemindTime, endContactRemindTime) | |
| 138 | + .or().isNull(CrmCustomerDO::getContactLastTime))); | |
| 139 | + }); | |
| 140 | + return query; | |
| 141 | + } | |
| 142 | + | |
| 143 | + /** | |
| 144 | + * 获得需要过期到公海的客户列表 | |
| 145 | + * | |
| 146 | + * @return 客户列表 | |
| 147 | + */ | |
| 148 | + default List<CrmCustomerDO> selectListByAutoPool(CrmCustomerPoolConfigDO poolConfig) { | |
| 149 | + LambdaQueryWrapper<CrmCustomerDO> query = new LambdaQueryWrapper<>(); | |
| 150 | + query.gt(CrmCustomerDO::getOwnerUserId, 0); | |
| 151 | + // 未锁定 + 未成交 | |
| 152 | + query.eq(CrmCustomerDO::getLockStatus, false).eq(CrmCustomerDO::getDealStatus, false); | |
| 153 | + // 已经超时 | |
| 154 | + LocalDateTime dealExpireTime = LocalDateTime.now().minusDays(poolConfig.getDealExpireDays()); | |
| 155 | + LocalDateTime contactExpireTime = LocalDateTime.now().minusDays(poolConfig.getContactExpireDays()); | |
| 156 | + query.and(q -> { | |
| 157 | + // 情况一:成交超时 | |
| 158 | + q.lt(CrmCustomerDO::getOwnerTime, dealExpireTime) | |
| 159 | + // 情况二:跟进超时 | |
| 160 | + .or(w -> w.lt(CrmCustomerDO::getOwnerTime, contactExpireTime) | |
| 161 | + .and(p -> p.lt(CrmCustomerDO::getContactLastTime, contactExpireTime) | |
| 162 | + .or().isNull(CrmCustomerDO::getContactLastTime))); | |
| 163 | + }); | |
| 164 | + return selectList(query); | |
| 165 | + } | |
| 166 | + | |
| 151 | 167 | default Long selectTodayCustomerCount(Long userId) { |
| 152 | 168 | MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); |
| 153 | 169 | // 我负责的 + 非公海 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
| ... | ... | @@ -78,8 +78,7 @@ public class CrmClueServiceImpl implements CrmClueService { |
| 78 | 78 | adminUserApi.validateUser(createReqVO.getOwnerUserId()); |
| 79 | 79 | |
| 80 | 80 | // 2. 插入线索 |
| 81 | - CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class) | |
| 82 | - .setContactLastTime(LocalDateTime.now()); | |
| 81 | + CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class); | |
| 83 | 82 | clueMapper.insert(clue); |
| 84 | 83 | |
| 85 | 84 | // 3. 创建数据权限 |
| ... | ... | @@ -129,7 +128,7 @@ public class CrmClueServiceImpl implements CrmClueService { |
| 129 | 128 | // 校验线索是否存在 |
| 130 | 129 | CrmClueDO oldClue = validateClueExists(id); |
| 131 | 130 | |
| 132 | - // 更新 | |
| 131 | + // 更新线索 | |
| 133 | 132 | clueMapper.updateById(new CrmClueDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime) |
| 134 | 133 | .setContactLastTime(LocalDateTime.now()).setContactLastContent(contactLastContent)); |
| 135 | 134 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
| ... | ... | @@ -3,11 +3,10 @@ package cn.iocoder.yudao.module.crm.service.customer; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*; |
| 5 | 5 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 6 | -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; | |
| 7 | 6 | import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; |
| 8 | -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; | |
| 9 | 7 | import jakarta.validation.Valid; |
| 10 | 8 | |
| 9 | +import java.time.LocalDateTime; | |
| 11 | 10 | import java.util.Collection; |
| 12 | 11 | import java.util.List; |
| 13 | 12 | import java.util.Map; |
| ... | ... | @@ -46,6 +45,15 @@ public interface CrmCustomerService { |
| 46 | 45 | void updateCustomerDealStatus(Long id, Boolean dealStatus); |
| 47 | 46 | |
| 48 | 47 | /** |
| 48 | + * 更新客户相关的跟进信息 | |
| 49 | + * | |
| 50 | + * @param id 编号 | |
| 51 | + * @param contactNextTime 下次联系时间 | |
| 52 | + * @param contactLastContent 最后联系内容 | |
| 53 | + */ | |
| 54 | + void updateCustomerFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent); | |
| 55 | + | |
| 56 | + /** | |
| 49 | 57 | * 删除客户 |
| 50 | 58 | * |
| 51 | 59 | * @param id 编号 |
| ... | ... | @@ -89,6 +97,23 @@ public interface CrmCustomerService { |
| 89 | 97 | PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId); |
| 90 | 98 | |
| 91 | 99 | /** |
| 100 | + * 获得放入公海提醒的客户分页 | |
| 101 | + * | |
| 102 | + * @param pageVO 分页查询 | |
| 103 | + * @param userId 用户编号 | |
| 104 | + * @return 客户分页 | |
| 105 | + */ | |
| 106 | + PageResult<CrmCustomerDO> getPutPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, Long userId); | |
| 107 | + | |
| 108 | + /** | |
| 109 | + * 获得待进入公海的客户数量 | |
| 110 | + * | |
| 111 | + * @param userId 用户编号 | |
| 112 | + * @return 提醒数量 | |
| 113 | + */ | |
| 114 | + Long getPutPoolRemindCustomerCount(Long userId); | |
| 115 | + | |
| 116 | + /** | |
| 92 | 117 | * 校验客户是否存在 |
| 93 | 118 | * |
| 94 | 119 | * @param customerId 客户 id |
| ... | ... | @@ -112,13 +137,6 @@ public interface CrmCustomerService { |
| 112 | 137 | void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO, Long userId); |
| 113 | 138 | |
| 114 | 139 | /** |
| 115 | - * 更新客户相关更进信息 | |
| 116 | - * | |
| 117 | - * @param customerUpdateFollowUpReqBO 请求 | |
| 118 | - */ | |
| 119 | - void updateCustomerFollowUp(CrmUpdateFollowUpReqBO customerUpdateFollowUpReqBO); | |
| 120 | - | |
| 121 | - /** | |
| 122 | 140 | * 创建客户 |
| 123 | 141 | * |
| 124 | 142 | * @param customerCreateReq 请求信息 |
| ... | ... | @@ -162,18 +180,6 @@ public interface CrmCustomerService { |
| 162 | 180 | int autoPutCustomerPool(); |
| 163 | 181 | |
| 164 | 182 | /** |
| 165 | - * 获得放入公海提醒的客户分页数据 | |
| 166 | - * | |
| 167 | - * @param pageVO 分页查询 | |
| 168 | - * @param poolConfigDO 公海配置 | |
| 169 | - * @param userId 用户编号 | |
| 170 | - * @return 客户分页 | |
| 171 | - */ | |
| 172 | - PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, | |
| 173 | - CrmCustomerPoolConfigDO poolConfigDO, | |
| 174 | - Long userId); | |
| 175 | - | |
| 176 | - /** | |
| 177 | 183 | * 获得今日需联系客户数量 |
| 178 | 184 | * |
| 179 | 185 | * @param userId 用户编号 |
| ... | ... | @@ -182,18 +188,6 @@ public interface CrmCustomerService { |
| 182 | 188 | Long getTodayCustomerCount(Long userId); |
| 183 | 189 | |
| 184 | 190 | /** |
| 185 | - * 获得待进入公海的客户数量 | |
| 186 | - * | |
| 187 | - * @param pageVO 分页查询 | |
| 188 | - * @param poolConfigDO 公海配置 | |
| 189 | - * @param userId 用户编号 | |
| 190 | - * @return 提醒数量 | |
| 191 | - */ | |
| 192 | - Long getPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageVO, | |
| 193 | - CrmCustomerPoolConfigDO poolConfigDO, | |
| 194 | - Long userId); | |
| 195 | - | |
| 196 | - /** | |
| 197 | 191 | * 获得分配给我的客户数量 |
| 198 | 192 | * |
| 199 | 193 | * @param userId 用户编号 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
| ... | ... | @@ -8,7 +8,6 @@ import cn.hutool.extra.spring.SpringUtil; |
| 8 | 8 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| 9 | 9 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 10 | 10 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 11 | -import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | |
| 12 | 11 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 13 | 12 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*; |
| 14 | 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| ... | ... | @@ -16,6 +15,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfi |
| 16 | 15 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; |
| 17 | 16 | import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; |
| 18 | 17 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 18 | +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; | |
| 19 | 19 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 20 | 20 | import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 21 | 21 | import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; |
| ... | ... | @@ -23,7 +23,6 @@ import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; |
| 23 | 23 | import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; |
| 24 | 24 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| 25 | 25 | import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; |
| 26 | -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; | |
| 27 | 26 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 28 | 27 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 29 | 28 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; |
| ... | ... | @@ -43,7 +42,6 @@ import java.time.LocalDateTime; |
| 43 | 42 | import java.util.*; |
| 44 | 43 | |
| 45 | 44 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 46 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; | |
| 47 | 45 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; |
| 48 | 46 | import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; |
| 49 | 47 | import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; |
| ... | ... | @@ -114,7 +112,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 114 | 112 | */ |
| 115 | 113 | private static CrmCustomerDO initCustomer(Object customer, Long ownerUserId) { |
| 116 | 114 | return BeanUtils.toBean(customer, CrmCustomerDO.class).setOwnerUserId(ownerUserId) |
| 117 | - .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); | |
| 115 | + .setOwnerTime(LocalDateTime.now()); | |
| 118 | 116 | } |
| 119 | 117 | |
| 120 | 118 | @Override |
| ... | ... | @@ -158,6 +156,22 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 158 | 156 | } |
| 159 | 157 | |
| 160 | 158 | @Override |
| 159 | + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}", | |
| 160 | + success = CRM_CUSTOMER_FOLLOW_UP_SUCCESS) | |
| 161 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) | |
| 162 | + public void updateCustomerFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) { | |
| 163 | + // 1.1 校验存在 | |
| 164 | + CrmCustomerDO customer = validateCustomerExists(id); | |
| 165 | + | |
| 166 | + // 2. 更新客户的跟进信息 | |
| 167 | + customerMapper.updateById(new CrmCustomerDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime) | |
| 168 | + .setContactLastTime(LocalDateTime.now())); | |
| 169 | + | |
| 170 | + // 3. 记录操作日志上下文 | |
| 171 | + LogRecordContext.putVariable("customerName", customer.getName()); | |
| 172 | + } | |
| 173 | + | |
| 174 | + @Override | |
| 161 | 175 | @Transactional(rollbackFor = Exception.class) |
| 162 | 176 | @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_DELETE_SUB_TYPE, bizNo = "{{#id}}", |
| 163 | 177 | success = CRM_CUSTOMER_DELETE_SUCCESS) |
| ... | ... | @@ -168,7 +182,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 168 | 182 | // 1.2 检查引用 |
| 169 | 183 | validateCustomerReference(id); |
| 170 | 184 | |
| 171 | - // 2. 删除 | |
| 185 | + // 2. 删除客户 | |
| 172 | 186 | customerMapper.deleteById(id); |
| 173 | 187 | // 3. 删除数据权限 |
| 174 | 188 | permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); |
| ... | ... | @@ -209,7 +223,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 209 | 223 | permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CUSTOMER.getType(), |
| 210 | 224 | reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); |
| 211 | 225 | // 2.2 转移后重新设置负责人 |
| 212 | - customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); | |
| 226 | + customerMapper.updateById(new CrmCustomerDO().setId(reqVO.getId()) | |
| 227 | + .setOwnerUserId(reqVO.getNewOwnerUserId()).setOwnerTime(LocalDateTime.now())); | |
| 213 | 228 | |
| 214 | 229 | // 3. 记录转移日志 |
| 215 | 230 | LogRecordContext.putVariable("customer", customer); |
| ... | ... | @@ -226,7 +241,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 226 | 241 | if (customer.getLockStatus().equals(lockReqVO.getLockStatus())) { |
| 227 | 242 | throw exception(customer.getLockStatus() ? CUSTOMER_LOCK_FAIL_IS_LOCK : CUSTOMER_UNLOCK_FAIL_IS_UNLOCK); |
| 228 | 243 | } |
| 229 | - // 1.3 校验锁定上限。 | |
| 244 | + // 1.3 校验锁定上限 | |
| 230 | 245 | if (lockReqVO.getLockStatus()) { |
| 231 | 246 | validateCustomerExceedLockLimit(userId); |
| 232 | 247 | } |
| ... | ... | @@ -240,11 +255,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 240 | 255 | } |
| 241 | 256 | |
| 242 | 257 | @Override |
| 243 | - public void updateCustomerFollowUp(CrmUpdateFollowUpReqBO customerUpdateFollowUpReqBO) { | |
| 244 | - customerMapper.updateById(BeanUtils.toBean(customerUpdateFollowUpReqBO, CrmCustomerDO.class).setId(customerUpdateFollowUpReqBO.getBizId())); | |
| 245 | - } | |
| 246 | - | |
| 247 | - @Override | |
| 248 | 258 | @Transactional(rollbackFor = Exception.class) |
| 249 | 259 | @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_CREATE_SUB_TYPE, bizNo = "{{#customer.id}}", |
| 250 | 260 | success = CRM_CUSTOMER_CREATE_SUCCESS) |
| ... | ... | @@ -263,7 +273,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 263 | 273 | } |
| 264 | 274 | |
| 265 | 275 | @Override |
| 266 | - public CrmCustomerImportRespVO importCustomerList(List<CrmCustomerImportExcelVO> importCustomers, CrmCustomerImportReqVO importReqVO) { | |
| 276 | + public CrmCustomerImportRespVO importCustomerList(List<CrmCustomerImportExcelVO> importCustomers, | |
| 277 | + CrmCustomerImportReqVO importReqVO) { | |
| 267 | 278 | if (CollUtil.isEmpty(importCustomers)) { |
| 268 | 279 | throw exception(CUSTOMER_IMPORT_LIST_IS_EMPTY); |
| 269 | 280 | } |
| ... | ... | @@ -383,12 +394,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 383 | 394 | // 1.4 校验负责人是否到达上限 |
| 384 | 395 | validateCustomerExceedOwnerLimit(ownerUserId, customers.size()); |
| 385 | 396 | |
| 386 | - // 2.1 领取公海数据 | |
| 397 | + // 2. 领取公海数据 | |
| 387 | 398 | List<CrmCustomerDO> updateCustomers = new ArrayList<>(); |
| 388 | 399 | List<CrmPermissionCreateReqBO> createPermissions = new ArrayList<>(); |
| 389 | 400 | customers.forEach(customer -> { |
| 390 | 401 | // 2.1. 设置负责人 |
| 391 | - updateCustomers.add(new CrmCustomerDO().setId(customer.getId()).setOwnerUserId(ownerUserId)); | |
| 402 | + updateCustomers.add(new CrmCustomerDO().setId(customer.getId()) | |
| 403 | + .setOwnerUserId(ownerUserId).setOwnerTime(LocalDateTime.now())); | |
| 392 | 404 | // 2.2. 创建负责人数据权限 |
| 393 | 405 | createPermissions.add(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) |
| 394 | 406 | .setBizId(customer.getId()).setUserId(ownerUserId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); |
| ... | ... | @@ -415,34 +427,23 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 415 | 427 | if (poolConfig == null || !poolConfig.getEnabled()) { |
| 416 | 428 | return 0; |
| 417 | 429 | } |
| 418 | - // 1.1 获取没有锁定的不在公海的客户 | |
| 419 | - List<CrmCustomerDO> customerList = customerMapper.selectListByLockAndNotPool(Boolean.FALSE); | |
| 420 | - // TODO @puhui999:下面也搞到 sql 里去哈;写 or 查询,问题不大的;低 393 到 402;原因是,避免无用的太多数据查询到 java 进程里; | |
| 421 | - List<CrmCustomerDO> poolCustomerList = new ArrayList<>(); | |
| 422 | - poolCustomerList.addAll(filterList(customerList, customer -> | |
| 423 | - !customer.getDealStatus() && (poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime())) <= 0)); | |
| 424 | - poolCustomerList.addAll(filterList(customerList, customer -> { | |
| 425 | - if (!customer.getDealStatus()) { // 这里只处理成交的 | |
| 426 | - return false; | |
| 427 | - } | |
| 428 | - LocalDateTime lastTime = ObjUtil.defaultIfNull(customer.getContactLastTime(), customer.getCreateTime()); | |
| 429 | - return (poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime)) <= 0; | |
| 430 | - })); | |
| 431 | - | |
| 430 | + // 1. 获得需要放到的客户列表 | |
| 431 | + List<CrmCustomerDO> customerList = customerMapper.selectListByAutoPool(poolConfig); | |
| 432 | 432 | // 2. 逐个放入公海 |
| 433 | 433 | int count = 0; |
| 434 | - for (CrmCustomerDO customer : poolCustomerList) { | |
| 434 | + for (CrmCustomerDO customer : customerList) { | |
| 435 | 435 | try { |
| 436 | 436 | getSelf().putCustomerPool(customer); |
| 437 | 437 | count++; |
| 438 | 438 | } catch (Throwable e) { |
| 439 | - log.error("[autoPutCustomerPool][Customer 客户({}) 放入公海异常]", customer.getId(), e); | |
| 439 | + log.error("[autoPutCustomerPool][客户({}) 放入公海异常]", customer.getId(), e); | |
| 440 | 440 | } |
| 441 | 441 | } |
| 442 | 442 | return count; |
| 443 | 443 | } |
| 444 | 444 | |
| 445 | - private void putCustomerPool(CrmCustomerDO customer) { | |
| 445 | + @Transactional // 需要 protected 修饰,因为需要在事务中调用 | |
| 446 | + protected void putCustomerPool(CrmCustomerDO customer) { | |
| 446 | 447 | // 1. 设置负责人为 NULL |
| 447 | 448 | int updateOwnerUserIncr = customerMapper.updateOwnerUserIdById(customer.getId(), null); |
| 448 | 449 | if (updateOwnerUserIncr == 0) { |
| ... | ... | @@ -486,17 +487,29 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 486 | 487 | } |
| 487 | 488 | |
| 488 | 489 | @Override |
| 489 | - public PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, | |
| 490 | - CrmCustomerPoolConfigDO poolConfigDO, | |
| 491 | - Long userId) { | |
| 492 | - return customerMapper.selectPutInPoolRemindCustomerPage(pageReqVO, poolConfigDO, userId); | |
| 490 | + public PageResult<CrmCustomerDO> getPutPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, Long userId) { | |
| 491 | + CrmCustomerPoolConfigDO poolConfig = customerPoolConfigService.getCustomerPoolConfig(); | |
| 492 | + if (ObjUtil.isNull(poolConfig) | |
| 493 | + || Boolean.FALSE.equals(poolConfig.getEnabled()) | |
| 494 | + || Boolean.FALSE.equals(poolConfig.getNotifyEnabled())) { | |
| 495 | + return PageResult.empty(); | |
| 496 | + } | |
| 497 | + return customerMapper.selectPutPoolRemindCustomerPage(pageVO, poolConfig, userId); | |
| 493 | 498 | } |
| 494 | 499 | |
| 495 | 500 | @Override |
| 496 | - public Long getPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO, | |
| 497 | - CrmCustomerPoolConfigDO poolConfigDO, | |
| 498 | - Long userId) { | |
| 499 | - return customerMapper.selectPutInPoolRemindCustomerCount(pageReqVO, poolConfigDO, userId); | |
| 501 | + public Long getPutPoolRemindCustomerCount(Long userId) { | |
| 502 | + CrmCustomerPoolConfigDO poolConfig = customerPoolConfigService.getCustomerPoolConfig(); | |
| 503 | + if (ObjUtil.isNull(poolConfig) | |
| 504 | + || Boolean.FALSE.equals(poolConfig.getEnabled()) | |
| 505 | + || Boolean.FALSE.equals(poolConfig.getNotifyEnabled())) { | |
| 506 | + return 0L; | |
| 507 | + } | |
| 508 | + CrmCustomerPageReqVO pageVO = new CrmCustomerPageReqVO() | |
| 509 | + .setPool(null) | |
| 510 | + .setContactStatus(CrmCustomerPageReqVO.CONTACT_TODAY) | |
| 511 | + .setSceneType(CrmSceneTypeEnum.OWNER.getType()); | |
| 512 | + return customerMapper.selectPutPoolRemindCustomerCount(pageVO, poolConfig, userId); | |
| 500 | 513 | } |
| 501 | 514 | |
| 502 | 515 | @Override |
| ... | ... | @@ -596,7 +609,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 596 | 609 | } |
| 597 | 610 | } |
| 598 | 611 | |
| 599 | - | |
| 600 | 612 | /** |
| 601 | 613 | * 获得自身的代理对象,解决 AOP 生效问题 |
| 602 | 614 | * | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java
| ... | ... | @@ -72,24 +72,24 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { |
| 72 | 72 | CrmFollowUpRecordDO followUpRecord = BeanUtils.toBean(createReqVO, CrmFollowUpRecordDO.class); |
| 73 | 73 | crmFollowUpRecordMapper.insert(followUpRecord); |
| 74 | 74 | |
| 75 | - LocalDateTime now = LocalDateTime.now(); | |
| 76 | - CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()) | |
| 77 | - .setContactLastTime(now).setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent()); | |
| 78 | 75 | // 2. 更新 bizId 对应的记录; |
| 79 | - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { // 更新商机跟进信息 | |
| 76 | + CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()) | |
| 77 | + .setContactLastTime(LocalDateTime.now()) | |
| 78 | + .setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent()); | |
| 79 | + if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { // 更新商机跟进信息 | |
| 80 | 80 | businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); |
| 81 | 81 | } |
| 82 | - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CLUE.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息 | |
| 82 | + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息 | |
| 83 | 83 | clueService.updateClueFollowUp(followUpRecord.getId(), followUpRecord.getNextTime(), followUpRecord.getContent()); |
| 84 | 84 | } |
| 85 | - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { // 更新联系人跟进信息 | |
| 85 | + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { // 更新联系人跟进信息 | |
| 86 | 86 | contactService.updateContactFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); |
| 87 | 87 | } |
| 88 | - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTRACT.getType(), followUpRecord.getBizType())) { // 更新合同跟进信息 | |
| 88 | + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTRACT.getType(), followUpRecord.getBizType())) { // 更新合同跟进信息 | |
| 89 | 89 | contractService.updateContractFollowUp(updateFollowUpReqBO); |
| 90 | 90 | } |
| 91 | - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CUSTOMER.getType(), followUpRecord.getBizType())) { // 更新客户跟进信息 | |
| 92 | - customerService.updateCustomerFollowUp(updateFollowUpReqBO); | |
| 91 | + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CUSTOMER.getType(), followUpRecord.getBizType())) { // 更新客户跟进信息 | |
| 92 | + customerService.updateCustomerFollowUp(followUpRecord.getBizId(), followUpRecord.getNextTime(), followUpRecord.getContent()); | |
| 93 | 93 | } |
| 94 | 94 | |
| 95 | 95 | // 3.1 更新 contactIds 对应的记录,不更新 lastTime 和 lastContent | ... | ... |