Commit 51f52ff4b723391d4482da8089997c3fa532e2a8

Authored by 芋道源码
Committed by Gitee
2 parents 4bf4432f 1ba2b7b6

!870 feat: CRM/backlog 提醒数量

Merge pull request !870 from dhb52/develop
Showing 26 changed files with 384 additions and 198 deletions
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/CrmBacklogController.java deleted
1 -package cn.iocoder.yudao.module.crm.controller.admin.backlog;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
4 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
5 -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;  
6 -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerRespVO;  
7 -import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO;  
8 -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;  
9 -import cn.iocoder.yudao.module.crm.service.message.CrmBacklogService;  
10 -import io.swagger.v3.oas.annotations.Operation;  
11 -import io.swagger.v3.oas.annotations.tags.Tag;  
12 -import jakarta.annotation.Resource;  
13 -import jakarta.validation.Valid;  
14 -import org.springframework.security.access.prepost.PreAuthorize;  
15 -import org.springframework.validation.annotation.Validated;  
16 -import org.springframework.web.bind.annotation.GetMapping;  
17 -import org.springframework.web.bind.annotation.RequestMapping;  
18 -import org.springframework.web.bind.annotation.RestController;  
19 -  
20 -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;  
21 -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;  
22 -  
23 -@Tag(name = "管理后台 - CRM待办消息")  
24 -@RestController  
25 -@RequestMapping("/crm/backlog")  
26 -@Validated  
27 -public class CrmBacklogController {  
28 -  
29 - @Resource  
30 - private CrmBacklogService crmMessageService;  
31 -  
32 - // TODO 芋艿:未来可能合并到 CrmCustomerController  
33 - @GetMapping("/today-customer-page")  
34 - @Operation(summary = "今日需联系客户")  
35 - @PreAuthorize("@ss.hasPermission('crm:customer:query')")  
36 - public CommonResult<PageResult<CrmCustomerRespVO>> getTodayCustomerPage(@Valid CrmTodayCustomerPageReqVO pageReqVO) {  
37 - PageResult<CrmCustomerDO> pageResult = crmMessageService.getTodayCustomerPage(pageReqVO, getLoginUserId());  
38 - return success(BeanUtils.toBean(pageResult, CrmCustomerRespVO.class));  
39 - }  
40 -  
41 -}  
42 \ No newline at end of file 0 \ No newline at end of file
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/vo/CrmTodayCustomerPageReqVO.java deleted
1 -package cn.iocoder.yudao.module.crm.controller.admin.backlog.vo;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageParam;  
4 -import cn.iocoder.yudao.framework.common.validation.InEnum;  
5 -import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;  
6 -import io.swagger.v3.oas.annotations.media.Schema;  
7 -import lombok.Data;  
8 -import lombok.EqualsAndHashCode;  
9 -import lombok.ToString;  
10 -  
11 -@Schema(description = "管理后台 - 今日需联系客户 Request VO")  
12 -@Data  
13 -@EqualsAndHashCode(callSuper = true)  
14 -@ToString(callSuper = true)  
15 -public class CrmTodayCustomerPageReqVO extends PageParam {  
16 -  
17 - /**  
18 - * 联系状态 - 今日需联系  
19 - */  
20 - public static final int CONTACT_TODAY = 1;  
21 - /**  
22 - * 联系状态 - 已逾期  
23 - */  
24 - public static final int CONTACT_EXPIRED = 2;  
25 - /**  
26 - * 联系状态 - 已联系  
27 - */  
28 - public static final int CONTACT_ALREADY = 3;  
29 -  
30 - @Schema(description = "联系状态", example = "1")  
31 - private Integer contactStatus;  
32 -  
33 - @Schema(description = "场景类型", example = "1")  
34 - @InEnum(CrmSceneTypeEnum.class)  
35 - private Integer sceneType;  
36 -  
37 -}  
38 \ No newline at end of file 0 \ No newline at end of file
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/clue/vo/CrmCluePageReqVO.java
@@ -39,4 +39,7 @@ public class CrmCluePageReqVO extends PageParam { @@ -39,4 +39,7 @@ public class CrmCluePageReqVO extends PageParam {
39 @Schema(description = "客户来源", example = "1") 39 @Schema(description = "客户来源", example = "1")
40 private Integer source; 40 private Integer source;
41 41
  42 + @Schema(description = "跟进状态", example = "true")
  43 + private Boolean followUpStatus;
  44 +
42 } 45 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
@@ -184,4 +184,19 @@ public class CrmContractController { @@ -184,4 +184,19 @@ public class CrmContractController {
184 return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap, contractProductMap, productList); 184 return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap, contractProductMap, productList);
185 } 185 }
186 186
  187 + @GetMapping("/check-contract-count")
  188 + @Operation(summary = "获得待审核合同数量")
  189 + @PreAuthorize("@ss.hasPermission('crm:contract:query')")
  190 + public CommonResult<Long> getCheckContractCount() {
  191 + return success(contractService.getCheckContractCount(getLoginUserId()));
  192 + }
  193 +
  194 +
  195 + @GetMapping("/end-contract-count")
  196 + @Operation(summary = "获得即将到期的合同数量")
  197 + @PreAuthorize("@ss.hasPermission('crm:contract:query')")
  198 + public CommonResult<Long> getEndContractCount() {
  199 + return success(contractService.getEndContractCount(getLoginUserId()));
  200 + }
  201 +
187 } 202 }
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;
@@ -128,8 +129,7 @@ public class CrmCustomerController { @@ -128,8 +129,7 @@ public class CrmCustomerController {
128 CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig(); 129 CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig();
129 if (ObjUtil.isNull(poolConfigDO) 130 if (ObjUtil.isNull(poolConfigDO)
130 || Boolean.FALSE.equals(poolConfigDO.getEnabled()) 131 || Boolean.FALSE.equals(poolConfigDO.getEnabled())
131 - || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())  
132 - ) { // TODO @dbh52:这个括号,一般不换行,在 java 这里; 132 + || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) {
133 throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED); 133 throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED);
134 } 134 }
135 135
@@ -148,6 +148,41 @@ public class CrmCustomerController { @@ -148,6 +148,41 @@ public class CrmCustomerController {
148 return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap)); 148 return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap));
149 } 149 }
150 150
  151 + @GetMapping("/put-in-pool-remind-count")
  152 + @Operation(summary = "获得待进入公海客户数量")
  153 + @PreAuthorize("@ss.hasPermission('crm:customer:query')")
  154 + public CommonResult<Long> getPutInPoolRemindCustomerCount() {
  155 + // 获取公海配置 TODO @dbh52:合并到 getPutInPoolRemindCustomerPage 会更合适哈;
  156 + CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig();
  157 + if (ObjUtil.isNull(poolConfigDO)
  158 + || Boolean.FALSE.equals(poolConfigDO.getEnabled())
  159 + || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) {
  160 + throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED);
  161 + }
  162 +
  163 + CrmCustomerPageReqVO pageVO = new CrmCustomerPageReqVO();
  164 + pageVO.setPool(null);
  165 + pageVO.setContactStatus(CrmCustomerPageReqVO.CONTACT_TODAY);
  166 + pageVO.setSceneType(CrmSceneTypeEnum.OWNER.getType());
  167 +
  168 + return success(customerService.getPutInPoolRemindCustomerCount(pageVO, poolConfigDO, getLoginUserId()));
  169 + }
  170 +
  171 + @GetMapping("/today-customer-count")
  172 + @Operation(summary = "获得今日需联系客户数量")
  173 + @PreAuthorize("@ss.hasPermission('crm:customer:query')")
  174 + public CommonResult<Long> getTodayCustomerCount() {
  175 + return success(customerService.getTodayCustomerCount(getLoginUserId()));
  176 + }
  177 +
  178 + @GetMapping("/follow-customer-count")
  179 + @Operation(summary = "获得分配给我的客户数量")
  180 + @PreAuthorize("@ss.hasPermission('crm:customer:query')")
  181 + public CommonResult<Long> getFollowCustomerCount() {
  182 + return success(customerService.getFollowCustomerCount(getLoginUserId()));
  183 + }
  184 +
  185 +
151 /** 186 /**
152 * 获取距离进入公海的时间 187 * 获取距离进入公海的时间
153 * 188 *
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java
@@ -14,6 +14,19 @@ import lombok.ToString; @@ -14,6 +14,19 @@ import lombok.ToString;
14 @ToString(callSuper = true) 14 @ToString(callSuper = true)
15 public class CrmCustomerPageReqVO extends PageParam { 15 public class CrmCustomerPageReqVO extends PageParam {
16 16
  17 + /**
  18 + * 联系状态 - 今日需联系
  19 + */
  20 + public static final int CONTACT_TODAY = 1;
  21 + /**
  22 + * 联系状态 - 已逾期
  23 + */
  24 + public static final int CONTACT_EXPIRED = 2;
  25 + /**
  26 + * 联系状态 - 已联系
  27 + */
  28 + public static final int CONTACT_ALREADY = 3;
  29 +
17 @Schema(description = "客户名称", example = "赵六") 30 @Schema(description = "客户名称", example = "赵六")
18 private String name; 31 private String name;
19 32
@@ -36,4 +49,13 @@ public class CrmCustomerPageReqVO extends PageParam { @@ -36,4 +49,13 @@ public class CrmCustomerPageReqVO extends PageParam {
36 @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") 49 @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
37 private Boolean pool; // null 则表示为不是公海数据 50 private Boolean pool; // null 则表示为不是公海数据
38 51
  52 + @Schema(description = "联系状态", example = "1")
  53 + private Integer contactStatus; // backlog查询条件, null 则表示为不做查询
  54 +
  55 + @Schema(description = "跟进状态", example = "true")
  56 + private Boolean followUpStatus; // backlog查询条件, null 则表示为不做查询
  57 +
  58 + @Schema(description = "跟进状态", example = "true")
  59 + private Boolean followUpStatus;
  60 +
39 } 61 }
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;
@@ -40,6 +41,7 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; { @@ -40,6 +41,7 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; {
40 .eqIfPresent(CrmClueDO::getIndustryId, pageReqVO.getIndustryId()) 41 .eqIfPresent(CrmClueDO::getIndustryId, pageReqVO.getIndustryId())
41 .eqIfPresent(CrmClueDO::getLevel, pageReqVO.getLevel()) 42 .eqIfPresent(CrmClueDO::getLevel, pageReqVO.getLevel())
42 .eqIfPresent(CrmClueDO::getSource, pageReqVO.getSource()) 43 .eqIfPresent(CrmClueDO::getSource, pageReqVO.getSource())
  44 + .eqIfPresent(CrmClueDO::getFollowUpStatus, pageReqVO.getFollowUpStatus())
43 .orderByDesc(CrmClueDO::getId); 45 .orderByDesc(CrmClueDO::getId);
44 return selectJoinPage(pageReqVO, CrmClueDO.class, query); 46 return selectJoinPage(pageReqVO, CrmClueDO.class, query);
45 } 47 }
@@ -53,4 +55,17 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; { @@ -53,4 +55,17 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; {
53 return selectJoinList(CrmClueDO.class, query); 55 return selectJoinList(CrmClueDO.class, query);
54 } 56 }
55 57
  58 + default Long getFollowLeadsCount(Long userId) {
  59 + MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>();
  60 +
  61 + // 我负责的, 非公海
  62 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(),
  63 + CrmClueDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
  64 +
  65 + // 未跟进, 未转化
  66 + query.ne(CrmClueDO::getFollowUpStatus, true)
  67 + .ne(CrmClueDO::getTransformStatus, true);
  68 +
  69 + return selectCount(query);
  70 + }
56 } 71 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
@@ -6,9 +6,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -6,9 +6,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
7 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; 7 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
8 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; 8 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
  9 +import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
9 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; 10 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
10 import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; 11 import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum;
11 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 12 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
  13 +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
12 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; 14 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
13 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 15 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
14 import org.apache.ibatis.annotations.Mapper; 16 import org.apache.ibatis.annotations.Mapper;
@@ -87,4 +89,33 @@ public interface CrmContractMapper extends BaseMapperX&lt;CrmContractDO&gt; { @@ -87,4 +89,33 @@ public interface CrmContractMapper extends BaseMapperX&lt;CrmContractDO&gt; {
87 return selectCount(CrmContractDO::getBusinessId, businessId); 89 return selectCount(CrmContractDO::getBusinessId, businessId);
88 } 90 }
89 91
  92 + default Long getCheckContractCount(Long userId) {
  93 + MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>();
  94 +
  95 + // 我负责的, 非公海
  96 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(),
  97 + CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
  98 +
  99 + // 未提交 or 审核不通过
  100 + query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus());
  101 +
  102 + return selectCount(query);
  103 + }
  104 +
  105 + default Long getEndContractCount(Long userId) {
  106 + MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>();
  107 +
  108 + // 我负责的, 非公海
  109 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(),
  110 + CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
  111 +
  112 + // 即将到期
  113 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
  114 + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());
  115 + int REMIND_DAYS = 20;
  116 + query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus())
  117 + .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS));
  118 +
  119 + return selectCount(query);
  120 + }
90 } 121 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
1 package cn.iocoder.yudao.module.crm.dal.mysql.customer; 1 package cn.iocoder.yudao.module.crm.dal.mysql.customer;
2 2
3 import cn.hutool.core.date.LocalDateTimeUtil; 3 import cn.hutool.core.date.LocalDateTimeUtil;
  4 +import cn.hutool.core.util.ObjUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 7 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
7 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; 8 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
8 -import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO;  
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;
16 import org.apache.ibatis.annotations.Mapper; 18 import org.apache.ibatis.annotations.Mapper;
17 import org.springframework.lang.Nullable; 19 import org.springframework.lang.Nullable;
  20 +import org.springframework.util.Assert;
18 21
19 import java.time.LocalDateTime; 22 import java.time.LocalDateTime;
20 import java.util.Collection; 23 import java.util.Collection;
@@ -28,6 +31,40 @@ import java.util.List; @@ -28,6 +31,40 @@ import java.util.List;
28 @Mapper 31 @Mapper
29 public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { 32 public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
30 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 +
31 default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) { 68 default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) {
32 return selectCount(new LambdaUpdateWrapper<CrmCustomerDO>() 69 return selectCount(new LambdaUpdateWrapper<CrmCustomerDO>()
33 .eq(CrmCustomerDO::getLockStatus, lockStatus) 70 .eq(CrmCustomerDO::getLockStatus, lockStatus)
@@ -57,50 +94,38 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; { @@ -57,50 +94,38 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
57 .eqIfPresent(CrmCustomerDO::getMobile, pageReqVO.getMobile()) 94 .eqIfPresent(CrmCustomerDO::getMobile, pageReqVO.getMobile())
58 .eqIfPresent(CrmCustomerDO::getIndustryId, pageReqVO.getIndustryId()) 95 .eqIfPresent(CrmCustomerDO::getIndustryId, pageReqVO.getIndustryId())
59 .eqIfPresent(CrmCustomerDO::getLevel, pageReqVO.getLevel()) 96 .eqIfPresent(CrmCustomerDO::getLevel, pageReqVO.getLevel())
60 - .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource());  
61 - return selectJoinPage(pageReqVO, CrmCustomerDO.class, query);  
62 - } 97 + .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource())
  98 + .eqIfPresent(CrmCustomerDO::getFollowUpStatus, pageReqVO.getFollowUpStatus());
63 99
64 - default List<CrmCustomerDO> selectBatchIds(Collection<Long> ids, Long userId) {  
65 - MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();  
66 - // 拼接数据权限的查询条件  
67 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId);  
68 - // 拼接自身的查询条件  
69 - query.selectAll(CrmCustomerDO.class).in(CrmCustomerDO::getId, ids).orderByDesc(CrmCustomerDO::getId);  
70 - return selectJoinList(CrmCustomerDO.class, query);  
71 - } 100 + // backlog 查询
  101 + if (ObjUtil.isNotNull(pageReqVO.getContactStatus())) {
  102 + Assert.isNull(pageReqVO.getPool(), "[是否为公海数据]必须是null");
72 103
73 - /**  
74 - * 待办事项 - 今日需联系客户  
75 - *  
76 - * @param pageReqVO 分页请求参数  
77 - * @param userId 当前用户ID  
78 - * @return 分页结果  
79 - */  
80 - default PageResult<CrmCustomerDO> selectTodayCustomerPage(CrmTodayCustomerPageReqVO pageReqVO, Long userId) {  
81 - MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();  
82 - // 拼接数据权限的查询条件  
83 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),  
84 - CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null);  
85 -  
86 - // 拼接自身的查询条件  
87 - query.selectAll(CrmCustomerDO.class);  
88 - if (pageReqVO.getContactStatus() != null) {  
89 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); 104 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
90 LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); 105 LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());
91 - if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_TODAY)) { // 今天需联系 106 + if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_TODAY)) { // 今天需联系
92 query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); 107 query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday);
93 - } else if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_EXPIRED)) { // 已逾期 108 + } else if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_EXPIRED)) { // 已逾期
94 query.lt(CrmCustomerDO::getContactNextTime, beginOfToday); 109 query.lt(CrmCustomerDO::getContactNextTime, beginOfToday);
95 - } else if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_ALREADY)) { // 已联系 110 + } else if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_ALREADY)) { // 已联系
96 query.between(CrmCustomerDO::getContactLastTime, beginOfToday, endOfToday); 111 query.between(CrmCustomerDO::getContactLastTime, beginOfToday, endOfToday);
97 } else { 112 } else {
98 throw new IllegalArgumentException("未知联系状态:" + pageReqVO.getContactStatus()); 113 throw new IllegalArgumentException("未知联系状态:" + pageReqVO.getContactStatus());
99 } 114 }
100 } 115 }
  116 +
101 return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); 117 return selectJoinPage(pageReqVO, CrmCustomerDO.class, query);
102 } 118 }
103 119
  120 + default List<CrmCustomerDO> selectBatchIds(Collection<Long> ids, Long userId) {
  121 + MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
  122 + // 拼接数据权限的查询条件
  123 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId);
  124 + // 拼接自身的查询条件
  125 + query.selectAll(CrmCustomerDO.class).in(CrmCustomerDO::getId, ids).orderByDesc(CrmCustomerDO::getId);
  126 + return selectJoinList(CrmCustomerDO.class, query);
  127 + }
  128 +
104 default List<CrmCustomerDO> selectListByLockAndNotPool(Boolean lockStatus) { 129 default List<CrmCustomerDO> selectListByLockAndNotPool(Boolean lockStatus) {
105 return selectList(new LambdaQueryWrapper<CrmCustomerDO>() 130 return selectList(new LambdaQueryWrapper<CrmCustomerDO>()
106 .eq(CrmCustomerDO::getLockStatus, lockStatus) 131 .eq(CrmCustomerDO::getLockStatus, lockStatus)
@@ -114,37 +139,42 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; { @@ -114,37 +139,42 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
114 default PageResult<CrmCustomerDO> selectPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, 139 default PageResult<CrmCustomerDO> selectPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO,
115 CrmCustomerPoolConfigDO poolConfigDO, 140 CrmCustomerPoolConfigDO poolConfigDO,
116 Long userId) { 141 Long userId) {
  142 + final MPJLambdaWrapperX<CrmCustomerDO> query = buildPutInPoolRemindCustomerWrapper(pageReqVO, poolConfigDO, userId);
  143 + return selectJoinPage(pageReqVO, CrmCustomerDO.class, query.selectAll(CrmCustomerDO.class));
  144 + }
  145 +
  146 + default Long selectPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO,
  147 + CrmCustomerPoolConfigDO poolConfigDO,
  148 + Long userId) {
  149 + final MPJLambdaWrapperX<CrmCustomerDO> query = buildPutInPoolRemindCustomerWrapper(pageReqVO, poolConfigDO, userId);
  150 + return selectCount(query);
  151 + }
  152 +
  153 + default Long getTodayCustomerCount(Long userId) {
117 MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); 154 MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
118 - // 拼接数据权限的查询条件 155 +
  156 + // 我负责的, 非公海
119 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), 157 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
120 - CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null);  
121 - // TODO @dhb52:lock 的情况,不需要提醒哈; 158 + CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
122 159
123 - // 拼接自身的查询条件  
124 - query.selectAll(CrmCustomerDO.class);  
125 - // 情况一:未成交提醒日期区间  
126 - Integer dealExpireDays = poolConfigDO.getDealExpireDays();  
127 - LocalDateTime startDealRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now())  
128 - .minusDays(dealExpireDays);  
129 - LocalDateTime endDealRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now())  
130 - .minusDays(Math.max(dealExpireDays - poolConfigDO.getNotifyDays(), 0));  
131 - // 情况二:未跟进提醒日期区间  
132 - Integer contactExpireDays = poolConfigDO.getContactExpireDays();  
133 - LocalDateTime startContactRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now())  
134 - .minusDays(contactExpireDays);  
135 - LocalDateTime endContactRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now())  
136 - .minusDays(Math.max(contactExpireDays - poolConfigDO.getNotifyDays(), 0));  
137 - query  
138 - // 情况一:1. 未成交放入公海提醒  
139 - .eq(CrmCustomerDO::getDealStatus, false)  
140 - .between(CrmCustomerDO::getCreateTime, startDealRemindDate, endDealRemindDate)  
141 - // 情况二:未跟进放入公海提醒  
142 - .or() // 2.1 contactLastTime 为空 TODO 芋艿:这个要不要搞个默认值;  
143 - .isNull(CrmCustomerDO::getContactLastTime)  
144 - .between(CrmCustomerDO::getCreateTime, startContactRemindDate, endContactRemindDate)  
145 - .or() // 2.2 ContactLastTime 不为空  
146 - .between(CrmCustomerDO::getContactLastTime, startContactRemindDate, endContactRemindDate);  
147 - return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); 160 + // 今天需联系
  161 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
  162 + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());
  163 + query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday);
  164 +
  165 + return selectCount(query);
148 } 166 }
149 167
  168 + default Long getFollowCustomerCount(Long userId) {
  169 + MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
  170 +
  171 + // 我负责的, 非公海
  172 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
  173 + CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
  174 +
  175 + // 未跟进
  176 + query.ne(CrmClueDO::getFollowUpStatus, true);
  177 +
  178 + return selectCount(query);
  179 + }
150 } 180 }
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;
@@ -78,4 +79,19 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO @@ -78,4 +79,19 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO
78 return selectJoinList(CrmReceivablePlanDO.class, query); 79 return selectJoinList(CrmReceivablePlanDO.class, query);
79 } 80 }
80 81
  82 + default Long getRemindReceivablePlanCount(Long userId) {
  83 + MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>();
  84 +
  85 + // 我负责的, 非公海
  86 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(),
  87 + CrmReceivablePlanDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
  88 +
  89 + // 待回款
  90 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
  91 + query.isNull(CrmReceivablePlanDO::getReceivableId)
  92 + .gt(CrmReceivablePlanDO::getReturnTime, beginOfToday)
  93 + .apply("to_days(return_time) <= to_days(now())+ remind_days");
  94 +
  95 + return selectCount(query);
  96 + }
81 } 97 }
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
@@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR @@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR
6 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; 6 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
7 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; 7 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
8 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; 8 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
9 -import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO;  
10 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 9 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
11 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; 10 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
12 import jakarta.validation.Valid; 11 import jakarta.validation.Valid;
@@ -135,12 +134,21 @@ public interface CrmContractService { @@ -135,12 +134,21 @@ public interface CrmContractService {
135 */ 134 */
136 Long getContractCountByBusinessId(Long businessId); 135 Long getContractCountByBusinessId(Long businessId);
137 136
  137 +
138 /** 138 /**
139 - * 获取合同商品列表 139 + * 获得待审核合同数量
140 * 140 *
141 - * @param contactId 合同编号  
142 - * @return 合同商品列表 141 + * @param userId 用户编号
  142 + * @return 提醒数量
  143 + */
  144 + Long getCheckContractCount(Long userId);
  145 +
  146 + /**
  147 + * 获得即将到期的合同数量
  148 + *
  149 + * @param userId 用户编号
  150 + * @return 提醒数量
143 */ 151 */
144 - List<CrmContractProductDO> getContractProductListByContractId(Long contactId); 152 + Long getEndContractCount(Long userId);
145 153
146 } 154 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
@@ -361,4 +361,15 @@ public class CrmContractServiceImpl implements CrmContractService { @@ -361,4 +361,15 @@ public class CrmContractServiceImpl implements CrmContractService {
361 } 361 }
362 362
363 // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒; 363 // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒;
  364 +
  365 + @Override
  366 + public Long getCheckContractCount(Long userId) {
  367 + return contractMapper.getCheckContractCount(userId);
  368 + }
  369 +
  370 + @Override
  371 + public Long getEndContractCount(Long userId) {
  372 + return contractMapper.getEndContractCount(userId);
  373 + }
  374 +
364 } 375 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
@@ -140,7 +140,43 @@ public interface CrmCustomerService { @@ -140,7 +140,43 @@ public interface CrmCustomerService {
140 */ 140 */
141 int autoPutCustomerPool(); 141 int autoPutCustomerPool();
142 142
  143 + /**
  144 + * 获得放入公海提醒的客户分页数据
  145 + *
  146 + * @param pageVO 分页查询
  147 + * @param poolConfigDO 公海配置
  148 + * @param userId 用户编号
  149 + * @return 客户分页
  150 + */
143 PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, 151 PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO,
144 CrmCustomerPoolConfigDO poolConfigDO, 152 CrmCustomerPoolConfigDO poolConfigDO,
145 - Long loginUserId); 153 + Long userId);
  154 +
  155 + /**
  156 + * 获得今日需联系客户数量
  157 + *
  158 + * @param userId 用户编号
  159 + * @return 提醒数量
  160 + */
  161 + Long getTodayCustomerCount(Long userId);
  162 +
  163 + /**
  164 + * 获得待进入公海的客户数量
  165 + *
  166 + * @param pageVO 分页查询
  167 + * @param poolConfigDO 公海配置
  168 + * @param userId 用户编号
  169 + * @return 提醒数量
  170 + */
  171 + Long getPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageVO,
  172 + CrmCustomerPoolConfigDO poolConfigDO,
  173 + Long userId);
  174 +
  175 + /**
  176 + * 获得分配给我的客户数量
  177 + *
  178 + * @param userId 用户编号
  179 + * @return 提醒数量
  180 + */
  181 + Long getFollowCustomerCount(Long userId);
146 } 182 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
@@ -466,12 +466,30 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -466,12 +466,30 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
466 return customerMapper.selectPage(pageReqVO, userId); 466 return customerMapper.selectPage(pageReqVO, userId);
467 } 467 }
468 468
  469 + @Override
469 public PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, 470 public PageResult<CrmCustomerDO> getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO,
470 CrmCustomerPoolConfigDO poolConfigDO, 471 CrmCustomerPoolConfigDO poolConfigDO,
471 Long userId) { 472 Long userId) {
472 return customerMapper.selectPutInPoolRemindCustomerPage(pageReqVO, poolConfigDO, userId); 473 return customerMapper.selectPutInPoolRemindCustomerPage(pageReqVO, poolConfigDO, userId);
473 } 474 }
474 475
  476 + @Override
  477 + public Long getPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO,
  478 + CrmCustomerPoolConfigDO poolConfigDO,
  479 + Long userId) {
  480 + return customerMapper.selectPutInPoolRemindCustomerCount(pageReqVO, poolConfigDO, userId);
  481 + }
  482 +
  483 + @Override
  484 + public Long getTodayCustomerCount(Long userId) {
  485 + return customerMapper.getTodayCustomerCount(userId);
  486 + }
  487 +
  488 + @Override
  489 + public Long getFollowCustomerCount(Long userId) {
  490 + return customerMapper.getFollowCustomerCount(userId);
  491 + }
  492 +
475 // ======================= 校验相关 ======================= 493 // ======================= 校验相关 =======================
476 494
477 /** 495 /**
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogService.java deleted
1 -package cn.iocoder.yudao.module.crm.service.message;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO;  
5 -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;  
6 -import jakarta.validation.Valid;  
7 -  
8 -/**  
9 - * CRM 待办消息 Service 接口  
10 - *  
11 - * @author dhb52  
12 - */  
13 -public interface CrmBacklogService {  
14 -  
15 - /**  
16 - * 根据【联系状态】、【场景类型】筛选客户分页  
17 - *  
18 - * @param pageReqVO 分页查询  
19 - * @return 分页数据  
20 - */  
21 - PageResult<CrmCustomerDO> getTodayCustomerPage(@Valid CrmTodayCustomerPageReqVO pageReqVO, Long userId);  
22 -  
23 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java deleted
1 -package cn.iocoder.yudao.module.crm.service.message;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO;  
5 -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;  
6 -import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper;  
7 -import jakarta.annotation.Resource;  
8 -import org.springframework.stereotype.Component;  
9 -import org.springframework.validation.annotation.Validated;  
10 -  
11 -/**  
12 - * 待办消息 Service 实现类  
13 - *  
14 - * @author dhb52  
15 - */  
16 -@Component  
17 -@Validated  
18 -public class CrmBacklogServiceImpl implements CrmBacklogService {  
19 -  
20 - @Resource  
21 - private CrmCustomerMapper customerMapper;  
22 -  
23 - @Override  
24 - public PageResult<CrmCustomerDO> getTodayCustomerPage(CrmTodayCustomerPageReqVO pageReqVO, Long userId) {  
25 - return customerMapper.selectTodayCustomerPage(pageReqVO, userId);  
26 - }  
27 -  
28 -}  
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 }