Commit d23dfd4276716dfbcefded0b6ed980ceac180777

Authored by dhb52
1 parent a5d33692

feat: CRM/backlog 提醒数量

Showing 20 changed files with 339 additions and 32 deletions
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java
@@ -104,4 +104,11 @@ public class CrmClueController { @@ -104,4 +104,11 @@ public class CrmClueController {
104 return success(Boolean.TRUE); 104 return success(Boolean.TRUE);
105 } 105 }
106 106
  107 + @GetMapping("/follow-leads-count")
  108 + @Operation(summary = "获得分配给我的线索数量")
  109 + @PreAuthorize("@ss.hasPermission('crm:clue:query')")
  110 + public CommonResult<Long> getFollowLeadsCount() {
  111 + return success(clueService.getFollowLeadsCount(getLoginUserId()));
  112 + }
  113 +
107 } 114 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
@@ -192,4 +192,19 @@ public class CrmContractController { @@ -192,4 +192,19 @@ public class CrmContractController {
192 return success(true); 192 return success(true);
193 } 193 }
194 194
  195 + @GetMapping("/check-contract-count")
  196 + @Operation(summary = "获得待审核合同数量")
  197 + @PreAuthorize("@ss.hasPermission('crm:contract:query')")
  198 + public CommonResult<Long> getCheckContractCount() {
  199 + return success(contractService.getCheckContractCount(getLoginUserId()));
  200 + }
  201 +
  202 +
  203 + @GetMapping("/end-contract-count")
  204 + @Operation(summary = "获得即将到期的合同数量")
  205 + @PreAuthorize("@ss.hasPermission('crm:contract:query')")
  206 + public CommonResult<Long> getEndContractCount() {
  207 + return success(contractService.getEndContractCount(getLoginUserId()));
  208 + }
  209 +
195 } 210 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
@@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
13 import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; 13 import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
14 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 14 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
15 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; 15 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
  16 +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
16 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerPoolConfigService; 17 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerPoolConfigService;
17 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; 18 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
18 import cn.iocoder.yudao.module.system.api.dept.DeptApi; 19 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
@@ -149,6 +150,41 @@ public class CrmCustomerController { @@ -149,6 +150,41 @@ public class CrmCustomerController {
149 return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap)); 150 return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap));
150 } 151 }
151 152
  153 + @GetMapping("/put-in-pool-remind-count")
  154 + @Operation(summary = "获得待进入公海客户数量")
  155 + @PreAuthorize("@ss.hasPermission('crm:customer:query')")
  156 + public CommonResult<Long> getPutInPoolRemindCustomerCount() {
  157 + // 获取公海配置 TODO @dbh52:合并到 getPutInPoolRemindCustomerPage 会更合适哈;
  158 + CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig();
  159 + if (ObjUtil.isNull(poolConfigDO)
  160 + || Boolean.FALSE.equals(poolConfigDO.getEnabled())
  161 + || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) {
  162 + throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED);
  163 + }
  164 +
  165 + CrmCustomerPageReqVO pageVO = new CrmCustomerPageReqVO();
  166 + pageVO.setPool(null);
  167 + pageVO.setContactStatus(CrmCustomerPageReqVO.CONTACT_TODAY);
  168 + pageVO.setSceneType(CrmSceneTypeEnum.OWNER.getType());
  169 +
  170 + return success(customerService.getPutInPoolRemindCustomerCount(pageVO, poolConfigDO, getLoginUserId()));
  171 + }
  172 +
  173 + @GetMapping("/today-customer-count")
  174 + @Operation(summary = "获得今日需联系客户数量")
  175 + @PreAuthorize("@ss.hasPermission('crm:customer:query')")
  176 + public CommonResult<Long> getTodayCustomerCount() {
  177 + return success(customerService.getTodayCustomerCount(getLoginUserId()));
  178 + }
  179 +
  180 + @GetMapping("/follow-customer-count")
  181 + @Operation(summary = "获得分配给我的客户数量")
  182 + @PreAuthorize("@ss.hasPermission('crm:customer:query')")
  183 + public CommonResult<Long> getFollowCustomerCount() {
  184 + return success(customerService.getFollowCustomerCount(getLoginUserId()));
  185 + }
  186 +
  187 +
152 /** 188 /**
153 * 获取距离进入公海的时间 189 * 获取距离进入公海的时间
154 * 190 *
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java
@@ -144,4 +144,12 @@ public class CrmReceivableController { @@ -144,4 +144,12 @@ public class CrmReceivableController {
144 return CrmReceivableConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList); 144 return CrmReceivableConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList);
145 } 145 }
146 146
  147 +
  148 + @GetMapping("/check-receivables-count")
  149 + @Operation(summary = "获得待审核回款数量")
  150 + @PreAuthorize("@ss.hasPermission('crm:receivable:query')")
  151 + public CommonResult<Long> getCheckReceivablesCount() {
  152 + return success(receivableService.getCheckReceivablesCount(getLoginUserId()));
  153 + }
  154 +
147 } 155 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java
@@ -153,4 +153,12 @@ public class CrmReceivablePlanController { @@ -153,4 +153,12 @@ public class CrmReceivablePlanController {
153 return CrmReceivablePlanConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList, receivableList); 153 return CrmReceivablePlanConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList, receivableList);
154 } 154 }
155 155
  156 +
  157 + @GetMapping("/remind-receivable-plan-count")
  158 + @Operation(summary = "获得待回款提醒数量")
  159 + @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')")
  160 + public CommonResult<Long> getRemindReceivablesCount() {
  161 + return success(receivablePlanService.getRemindReceivablePlanCount(getLoginUserId()));
  162 + }
  163 +
156 } 164 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
6 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; 6 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO;
7 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; 7 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
8 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 8 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
  9 +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
9 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; 10 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
10 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 11 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
11 import org.apache.ibatis.annotations.Mapper; 12 import org.apache.ibatis.annotations.Mapper;
@@ -53,4 +54,17 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; { @@ -53,4 +54,17 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; {
53 return selectJoinList(CrmClueDO.class, query); 54 return selectJoinList(CrmClueDO.class, query);
54 } 55 }
55 56
  57 + default Long getFollowLeadsCount(Long userId) {
  58 + MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>();
  59 +
  60 + // 我负责的, 非公海
  61 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(),
  62 + CrmClueDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
  63 +
  64 + // 未跟进, 未转化
  65 + query.ne(CrmClueDO::getFollowUpStatus, true)
  66 + .ne(CrmClueDO::getTransformStatus, true);
  67 +
  68 + return selectCount(query);
  69 + }
56 } 70 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
@@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR
9 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; 9 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
10 import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; 10 import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum;
11 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 11 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
  12 +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
12 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; 13 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
13 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 14 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
14 import org.apache.ibatis.annotations.Mapper; 15 import org.apache.ibatis.annotations.Mapper;
@@ -90,4 +91,33 @@ public interface CrmContractMapper extends BaseMapperX&lt;CrmContractDO&gt; { @@ -90,4 +91,33 @@ public interface CrmContractMapper extends BaseMapperX&lt;CrmContractDO&gt; {
90 return selectCount(CrmContractDO::getBusinessId, businessId); 91 return selectCount(CrmContractDO::getBusinessId, businessId);
91 } 92 }
92 93
  94 + default Long getCheckContractCount(Long userId) {
  95 + MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>();
  96 +
  97 + // 我负责的, 非公海
  98 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(),
  99 + CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
  100 +
  101 + // 未提交 or 审核不通过
  102 + query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus());
  103 +
  104 + return selectCount(query);
  105 + }
  106 +
  107 + default Long getEndContractCount(Long userId) {
  108 + MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>();
  109 +
  110 + // 我负责的, 非公海
  111 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(),
  112 + CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
  113 +
  114 + // 即将到期
  115 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
  116 + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());
  117 + int REMIND_DAYS = 20;
  118 + query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus())
  119 + .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS));
  120 +
  121 + return selectCount(query);
  122 + }
93 } 123 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
@@ -7,9 +7,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -7,9 +7,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
7 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 7 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
8 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; 8 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
9 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; 9 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;
  10 +import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
10 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 11 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
11 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; 12 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
12 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 13 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
  14 +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
13 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; 15 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
14 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 16 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
15 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 17 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -29,6 +31,40 @@ import java.util.List; @@ -29,6 +31,40 @@ import java.util.List;
29 @Mapper 31 @Mapper
30 public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { 32 public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
31 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 +
32 default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) { 68 default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) {
33 return selectCount(new LambdaUpdateWrapper<CrmCustomerDO>() 69 return selectCount(new LambdaUpdateWrapper<CrmCustomerDO>()
34 .eq(CrmCustomerDO::getLockStatus, lockStatus) 70 .eq(CrmCustomerDO::getLockStatus, lockStatus)
@@ -102,39 +138,42 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; { @@ -102,39 +138,42 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
102 default PageResult<CrmCustomerDO> selectPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, 138 default PageResult<CrmCustomerDO> selectPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO,
103 CrmCustomerPoolConfigDO poolConfigDO, 139 CrmCustomerPoolConfigDO poolConfigDO,
104 Long userId) { 140 Long userId) {
  141 + final MPJLambdaWrapperX<CrmCustomerDO> query = buildPutInPoolRemindCustomerWrapper(pageReqVO, poolConfigDO, userId);
  142 + return selectJoinPage(pageReqVO, CrmCustomerDO.class, query.selectAll(CrmCustomerDO.class));
  143 + }
  144 +
  145 + default Long selectPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO,
  146 + CrmCustomerPoolConfigDO poolConfigDO,
  147 + Long userId) {
  148 + final MPJLambdaWrapperX<CrmCustomerDO> query = buildPutInPoolRemindCustomerWrapper(pageReqVO, poolConfigDO, userId);
  149 + return selectCount(query);
  150 + }
  151 +
  152 + default Long getTodayCustomerCount(Long userId) {
105 MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); 153 MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
106 - // 拼接数据权限的查询条件 154 +
  155 + // 我负责的, 非公海
107 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), 156 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
108 - CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); 157 + CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
109 158
110 - // 锁定状态不需要提醒  
111 - query.ne(CrmCustomerDO::getLockStatus, true); 159 + // 今天需联系
  160 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
  161 + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());
  162 + query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday);
112 163
113 - // 拼接自身的查询条件  
114 - query.selectAll(CrmCustomerDO.class);  
115 - // 情况一:未成交提醒日期区间  
116 - Integer dealExpireDays = poolConfigDO.getDealExpireDays();  
117 - LocalDateTime startDealRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now())  
118 - .minusDays(dealExpireDays);  
119 - LocalDateTime endDealRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now())  
120 - .minusDays(Math.max(dealExpireDays - poolConfigDO.getNotifyDays(), 0));  
121 - // 情况二:未跟进提醒日期区间  
122 - Integer contactExpireDays = poolConfigDO.getContactExpireDays();  
123 - LocalDateTime startContactRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now())  
124 - .minusDays(contactExpireDays);  
125 - LocalDateTime endContactRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now())  
126 - .minusDays(Math.max(contactExpireDays - poolConfigDO.getNotifyDays(), 0));  
127 - query  
128 - // 情况一:1. 未成交放入公海提醒  
129 - .eq(CrmCustomerDO::getDealStatus, false)  
130 - .between(CrmCustomerDO::getCreateTime, startDealRemindDate, endDealRemindDate)  
131 - // 情况二:未跟进放入公海提醒  
132 - .or() // 2.1 contactLastTime 为空 TODO 芋艿:这个要不要搞个默认值;  
133 - .isNull(CrmCustomerDO::getContactLastTime)  
134 - .between(CrmCustomerDO::getCreateTime, startContactRemindDate, endContactRemindDate)  
135 - .or() // 2.2 ContactLastTime 不为空  
136 - .between(CrmCustomerDO::getContactLastTime, startContactRemindDate, endContactRemindDate);  
137 - return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); 164 + return selectCount(query);
138 } 165 }
139 166
  167 + default Long getFollowCustomerCount(Long userId) {
  168 + MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
  169 +
  170 + // 我负责的, 非公海
  171 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
  172 + CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
  173 +
  174 + // 未跟进
  175 + query.ne(CrmClueDO::getFollowUpStatus, true);
  176 +
  177 + return selectCount(query);
  178 + }
140 } 179 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
@@ -5,8 +5,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -5,8 +5,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
7 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; 7 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO;
  8 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
8 import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; 9 import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO;
  10 +import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum;
9 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 11 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
  12 +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
10 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; 13 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
11 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 14 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
12 import org.apache.ibatis.annotations.Mapper; 15 import org.apache.ibatis.annotations.Mapper;
@@ -59,4 +62,17 @@ public interface CrmReceivableMapper extends BaseMapperX&lt;CrmReceivableDO&gt; { @@ -59,4 +62,17 @@ public interface CrmReceivableMapper extends BaseMapperX&lt;CrmReceivableDO&gt; {
59 return selectJoinList(CrmReceivableDO.class, query); 62 return selectJoinList(CrmReceivableDO.class, query);
60 } 63 }
61 64
  65 + default Long getCheckReceivablesCount(Long userId) {
  66 + MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>();
  67 +
  68 + // 我负责的, 非公海
  69 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(),
  70 + CrmReceivableDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
  71 +
  72 + // 未提交 or 审核不通过
  73 + query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus());
  74 +
  75 + return selectCount(query);
  76 + }
  77 +
62 } 78 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; @@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
8 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; 8 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO;
9 import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; 9 import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
10 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 10 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
  11 +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
11 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; 12 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
12 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 13 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
13 import org.apache.ibatis.annotations.Mapper; 14 import org.apache.ibatis.annotations.Mapper;
@@ -80,4 +81,19 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO @@ -80,4 +81,19 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO
80 return selectJoinList(CrmReceivablePlanDO.class, query); 81 return selectJoinList(CrmReceivablePlanDO.class, query);
81 } 82 }
82 83
  84 + default Long getRemindReceivablePlanCount(Long userId) {
  85 + MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>();
  86 +
  87 + // 我负责的, 非公海
  88 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(),
  89 + CrmReceivablePlanDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
  90 +
  91 + // 待回款
  92 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
  93 + query.isNull(CrmReceivablePlanDO::getReceivableId)
  94 + .gt(CrmReceivablePlanDO::getReturnTime, beginOfToday)
  95 + .apply("to_days(return_time) <= to_days(now())+ remind_days");
  96 +
  97 + return selectCount(query);
  98 + }
83 } 99 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java
@@ -90,4 +90,12 @@ public interface CrmClueService { @@ -90,4 +90,12 @@ public interface CrmClueService {
90 */ 90 */
91 void translateCustomer(CrmClueTranslateReqVO reqVO, Long userId); 91 void translateCustomer(CrmClueTranslateReqVO reqVO, Long userId);
92 92
  93 + /**
  94 + * 获得分配给我的线索数量
  95 + *
  96 + * @param userId 用户编号
  97 + * @return 提醒数量
  98 + */
  99 + Long getFollowLeadsCount(Long userId);
  100 +
93 } 101 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
@@ -276,4 +276,9 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -276,4 +276,9 @@ public class CrmClueServiceImpl implements CrmClueService {
276 return SpringUtil.getBean(getClass()); 276 return SpringUtil.getBean(getClass());
277 } 277 }
278 278
  279 + @Override
  280 + public Long getFollowLeadsCount(Long userId) {
  281 + return clueMapper.getFollowLeadsCount(userId);
  282 + }
  283 +
279 } 284 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
@@ -134,4 +134,21 @@ public interface CrmContractService { @@ -134,4 +134,21 @@ public interface CrmContractService {
134 */ 134 */
135 Long getContractCountByBusinessId(Long businessId); 135 Long getContractCountByBusinessId(Long businessId);
136 136
  137 +
  138 + /**
  139 + * 获得待审核合同数量
  140 + *
  141 + * @param userId 用户编号
  142 + * @return 提醒数量
  143 + */
  144 + Long getCheckContractCount(Long userId);
  145 +
  146 + /**
  147 + * 获得即将到期的合同数量
  148 + *
  149 + * @param userId 用户编号
  150 + * @return 提醒数量
  151 + */
  152 + Long getEndContractCount(Long userId);
  153 +
137 } 154 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
@@ -314,4 +314,15 @@ public class CrmContractServiceImpl implements CrmContractService { @@ -314,4 +314,15 @@ public class CrmContractServiceImpl implements CrmContractService {
314 return contractMapper.selectCountByBusinessId(businessId); 314 return contractMapper.selectCountByBusinessId(businessId);
315 } 315 }
316 // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒; 316 // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒;
  317 +
  318 + @Override
  319 + public Long getCheckContractCount(Long userId) {
  320 + return contractMapper.getCheckContractCount(userId);
  321 + }
  322 +
  323 + @Override
  324 + public Long getEndContractCount(Long userId) {
  325 + return contractMapper.getEndContractCount(userId);
  326 + }
  327 +
317 } 328 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
@@ -141,7 +141,43 @@ public interface CrmCustomerService { @@ -141,7 +141,43 @@ public interface CrmCustomerService {
141 */ 141 */
142 int autoPutCustomerPool(); 142 int autoPutCustomerPool();
143 143
  144 + /**
  145 + * 获得放入公海提醒的客户分页数据
  146 + *
  147 + * @param pageVO 分页查询
  148 + * @param poolConfigDO 公海配置
  149 + * @param userId 用户编号
  150 + * @return 客户分页
  151 + */
144 PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, 152 PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO,
145 CrmCustomerPoolConfigDO poolConfigDO, 153 CrmCustomerPoolConfigDO poolConfigDO,
146 - Long loginUserId); 154 + Long userId);
  155 +
  156 + /**
  157 + * 获得今日需联系客户数量
  158 + *
  159 + * @param userId 用户编号
  160 + * @return 提醒数量
  161 + */
  162 + Long getTodayCustomerCount(Long userId);
  163 +
  164 + /**
  165 + * 获得待进入公海的客户数量
  166 + *
  167 + * @param pageVO 分页查询
  168 + * @param poolConfigDO 公海配置
  169 + * @param userId 用户编号
  170 + * @return 提醒数量
  171 + */
  172 + Long getPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageVO,
  173 + CrmCustomerPoolConfigDO poolConfigDO,
  174 + Long userId);
  175 +
  176 + /**
  177 + * 获得分配给我的客户数量
  178 + *
  179 + * @param userId 用户编号
  180 + * @return 提醒数量
  181 + */
  182 + Long getFollowCustomerCount(Long userId);
147 } 183 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
@@ -465,12 +465,30 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -465,12 +465,30 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
465 return customerMapper.selectPage(pageReqVO, userId); 465 return customerMapper.selectPage(pageReqVO, userId);
466 } 466 }
467 467
  468 + @Override
468 public PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, 469 public PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO,
469 CrmCustomerPoolConfigDO poolConfigDO, 470 CrmCustomerPoolConfigDO poolConfigDO,
470 Long userId) { 471 Long userId) {
471 return customerMapper.selectPutInPoolRemindCustomerPage(pageReqVO, poolConfigDO, userId); 472 return customerMapper.selectPutInPoolRemindCustomerPage(pageReqVO, poolConfigDO, userId);
472 } 473 }
473 474
  475 + @Override
  476 + public Long getPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO,
  477 + CrmCustomerPoolConfigDO poolConfigDO,
  478 + Long userId) {
  479 + return customerMapper.selectPutInPoolRemindCustomerCount(pageReqVO, poolConfigDO, userId);
  480 + }
  481 +
  482 + @Override
  483 + public Long getTodayCustomerCount(Long userId) {
  484 + return customerMapper.getTodayCustomerCount(userId);
  485 + }
  486 +
  487 + @Override
  488 + public Long getFollowCustomerCount(Long userId) {
  489 + return customerMapper.getFollowCustomerCount(userId);
  490 + }
  491 +
474 // ======================= 校验相关 ======================= 492 // ======================= 校验相关 =======================
475 493
476 /** 494 /**
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java
@@ -77,4 +77,11 @@ public interface CrmReceivablePlanService { @@ -77,4 +77,11 @@ public interface CrmReceivablePlanService {
77 */ 77 */
78 PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO); 78 PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO);
79 79
  80 + /**
  81 + * 获得待回款提醒数量
  82 + *
  83 + * @param userId 用户编号
  84 + * @return 提醒数量
  85 + */
  86 + Long getRemindReceivablePlanCount(Long userId);
80 } 87 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java
@@ -24,7 +24,6 @@ import com.mzt.logapi.context.LogRecordContext; @@ -24,7 +24,6 @@ import com.mzt.logapi.context.LogRecordContext;
24 import com.mzt.logapi.service.impl.DiffParseFunction; 24 import com.mzt.logapi.service.impl.DiffParseFunction;
25 import com.mzt.logapi.starter.annotation.LogRecord; 25 import com.mzt.logapi.starter.annotation.LogRecord;
26 import jakarta.annotation.Resource; 26 import jakarta.annotation.Resource;
27 -import org.springframework.context.annotation.Lazy;  
28 import org.springframework.stereotype.Service; 27 import org.springframework.stereotype.Service;
29 import org.springframework.validation.annotation.Validated; 28 import org.springframework.validation.annotation.Validated;
30 29
@@ -163,4 +162,9 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { @@ -163,4 +162,9 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
163 return receivablePlanMapper.selectPageByCustomerId(pageReqVO); 162 return receivablePlanMapper.selectPageByCustomerId(pageReqVO);
164 } 163 }
165 164
  165 + @Override
  166 + public Long getRemindReceivablePlanCount(Long userId) {
  167 + return receivablePlanMapper.getRemindReceivablePlanCount(userId);
  168 + }
  169 +
166 } 170 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
@@ -78,4 +78,12 @@ public interface CrmReceivableService { @@ -78,4 +78,12 @@ public interface CrmReceivableService {
78 */ 78 */
79 PageResult<CrmReceivableDO> getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO); 79 PageResult<CrmReceivableDO> getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO);
80 80
  81 + /**
  82 + * 获得待审核回款数量
  83 + *
  84 + * @param userId 用户编号
  85 + * @return 提醒数量
  86 + */
  87 + Long getCheckReceivablesCount(Long userId);
  88 +
81 } 89 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
@@ -27,7 +27,6 @@ import com.mzt.logapi.context.LogRecordContext; @@ -27,7 +27,6 @@ import com.mzt.logapi.context.LogRecordContext;
27 import com.mzt.logapi.service.impl.DiffParseFunction; 27 import com.mzt.logapi.service.impl.DiffParseFunction;
28 import com.mzt.logapi.starter.annotation.LogRecord; 28 import com.mzt.logapi.starter.annotation.LogRecord;
29 import jakarta.annotation.Resource; 29 import jakarta.annotation.Resource;
30 -import org.springframework.context.annotation.Lazy;  
31 import org.springframework.stereotype.Service; 30 import org.springframework.stereotype.Service;
32 import org.springframework.validation.annotation.Validated; 31 import org.springframework.validation.annotation.Validated;
33 32
@@ -183,4 +182,9 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { @@ -183,4 +182,9 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
183 return receivableMapper.selectPageByCustomerId(pageReqVO); 182 return receivableMapper.selectPageByCustomerId(pageReqVO);
184 } 183 }
185 184
  185 + @Override
  186 + public Long getCheckReceivablesCount(Long userId) {
  187 + return receivableMapper.getCheckReceivablesCount(userId);
  188 + }
  189 +
186 } 190 }