Commit ed5f3a6bc2031a5eedf6be32e0a3fe0f3f156813

Authored by YunaiV
1 parent 0eff2ae6

crm:code review 销售漏斗

Showing 13 changed files with 38 additions and 82 deletions
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
@@ -177,7 +177,7 @@ public class CrmBusinessController { @@ -177,7 +177,7 @@ public class CrmBusinessController {
177 buildBusinessDetailList(list)); 177 buildBusinessDetailList(list));
178 } 178 }
179 179
180 - private List<CrmBusinessRespVO> buildBusinessDetailList(List<CrmBusinessDO> list) { 180 + public List<CrmBusinessRespVO> buildBusinessDetailList(List<CrmBusinessDO> list) {
181 if (CollUtil.isEmpty(list)) { 181 if (CollUtil.isEmpty(list)) {
182 return Collections.emptyList(); 182 return Collections.emptyList();
183 } 183 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsFunnelController.java
1 package cn.iocoder.yudao.module.crm.controller.admin.statistics; 1 package cn.iocoder.yudao.module.crm.controller.admin.statistics;
2 2
3 -import cn.hutool.core.collection.CollUtil; 3 +import cn.hutool.extra.spring.SpringUtil;
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 -import cn.iocoder.yudao.framework.common.util.collection.MapUtils;  
7 -import cn.iocoder.yudao.framework.common.util.number.NumberUtils;  
8 -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 6 +import cn.iocoder.yudao.module.crm.controller.admin.business.CrmBusinessController;
9 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; 7 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;
10 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticBusinessEndStatusRespVO; 8 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticBusinessEndStatusRespVO;
11 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticFunnelRespVO; 9 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticFunnelRespVO;
12 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticsBusinessSummaryByDateRespVO; 10 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticsBusinessSummaryByDateRespVO;
13 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticsFunnelReqVO; 11 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticsFunnelReqVO;
14 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; 12 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
15 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;  
16 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;  
17 -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;  
18 -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;  
19 -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService;  
20 -import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;  
21 import cn.iocoder.yudao.module.crm.service.statistics.CrmStatisticsFunnelService; 13 import cn.iocoder.yudao.module.crm.service.statistics.CrmStatisticsFunnelService;
22 -import cn.iocoder.yudao.module.system.api.dept.DeptApi;  
23 -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;  
24 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
25 -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;  
26 import io.swagger.v3.oas.annotations.Operation; 14 import io.swagger.v3.oas.annotations.Operation;
27 import io.swagger.v3.oas.annotations.tags.Tag; 15 import io.swagger.v3.oas.annotations.tags.Tag;
28 import jakarta.annotation.Resource; 16 import jakarta.annotation.Resource;
@@ -33,14 +21,9 @@ import org.springframework.web.bind.annotation.GetMapping; @@ -33,14 +21,9 @@ import org.springframework.web.bind.annotation.GetMapping;
33 import org.springframework.web.bind.annotation.RequestMapping; 21 import org.springframework.web.bind.annotation.RequestMapping;
34 import org.springframework.web.bind.annotation.RestController; 22 import org.springframework.web.bind.annotation.RestController;
35 23
36 -import java.util.Collections;  
37 import java.util.List; 24 import java.util.List;
38 -import java.util.Map;  
39 -import java.util.stream.Stream;  
40 25
41 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 26 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
42 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;  
43 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;  
44 27
45 @Tag(name = "管理后台 - CRM 销售漏斗") 28 @Tag(name = "管理后台 - CRM 销售漏斗")
46 @RestController 29 @RestController
@@ -48,31 +31,20 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. @@ -48,31 +31,20 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
48 @Validated 31 @Validated
49 public class CrmStatisticsFunnelController { 32 public class CrmStatisticsFunnelController {
50 33
  34 + // TODO @puhui999:crmStatisticsFunnelService 改成 funnelService 更好点哈
51 @Resource 35 @Resource
52 private CrmStatisticsFunnelService crmStatisticsFunnelService; 36 private CrmStatisticsFunnelService crmStatisticsFunnelService;
53 - @Resource  
54 - private CrmBusinessService businessService;  
55 - @Resource  
56 - private CrmCustomerService customerService;  
57 - @Resource  
58 - private CrmBusinessStatusService businessStatusTypeService;  
59 - @Resource  
60 - private CrmBusinessStatusService businessStatusService;  
61 -  
62 - @Resource  
63 - private AdminUserApi adminUserApi;  
64 - @Resource  
65 - private DeptApi deptApi;  
66 37
67 @GetMapping("/get-funnel-summary") 38 @GetMapping("/get-funnel-summary")
68 - @Operation(summary = "获取销售漏斗统计数据", description = "用于【销售漏斗】页面") 39 + @Operation(summary = "获取销售漏斗统计数据", description = "用于【销售漏斗】页面的【销售漏斗分析】")
69 @PreAuthorize("@ss.hasPermission('crm:statistics-funnel:query')") 40 @PreAuthorize("@ss.hasPermission('crm:statistics-funnel:query')")
70 public CommonResult<CrmStatisticFunnelRespVO> getFunnelSummary(@Valid CrmStatisticsFunnelReqVO reqVO) { 41 public CommonResult<CrmStatisticFunnelRespVO> getFunnelSummary(@Valid CrmStatisticsFunnelReqVO reqVO) {
71 return success(crmStatisticsFunnelService.getFunnelSummary(reqVO)); 42 return success(crmStatisticsFunnelService.getFunnelSummary(reqVO));
72 } 43 }
73 44
  45 + // TODO @puhui:这个接口,应该是 getBusinessSummaryByEndStatus?这样更统一哈;
74 @GetMapping("/get-business-end-status-summary") 46 @GetMapping("/get-business-end-status-summary")
75 - @Operation(summary = "获取商机结束状态统计", description = "用于【销售漏斗】页面") 47 + @Operation(summary = "获取商机结束状态统计", description = "用于【销售漏斗】页面的【销售漏斗分析】")
76 @PreAuthorize("@ss.hasPermission('crm:statistics-funnel:query')") 48 @PreAuthorize("@ss.hasPermission('crm:statistics-funnel:query')")
77 public CommonResult<List<CrmStatisticBusinessEndStatusRespVO>> getBusinessEndStatusSummary(@Valid CrmStatisticsFunnelReqVO reqVO) { 49 public CommonResult<List<CrmStatisticBusinessEndStatusRespVO>> getBusinessEndStatusSummary(@Valid CrmStatisticsFunnelReqVO reqVO) {
78 return success(crmStatisticsFunnelService.getBusinessEndStatusSummary(reqVO)); 50 return success(crmStatisticsFunnelService.getBusinessEndStatusSummary(reqVO));
@@ -86,7 +58,7 @@ public class CrmStatisticsFunnelController { @@ -86,7 +58,7 @@ public class CrmStatisticsFunnelController {
86 } 58 }
87 59
88 @GetMapping("/get-business-page-by-date") 60 @GetMapping("/get-business-page-by-date")
89 - @Operation(summary = "获得商机分页(按日期)", description = "用于【销售漏斗】页面") 61 + @Operation(summary = "获得商机分页(按日期)", description = "用于【销售漏斗】页面的【新增商机分析】")
90 @PreAuthorize("@ss.hasPermission('crm:business:query')") 62 @PreAuthorize("@ss.hasPermission('crm:business:query')")
91 public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByDate(@Valid CrmStatisticsFunnelReqVO pageVO) { 63 public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByDate(@Valid CrmStatisticsFunnelReqVO pageVO) {
92 PageResult<CrmBusinessDO> pageResult = crmStatisticsFunnelService.getBusinessPageByDate(pageVO); 64 PageResult<CrmBusinessDO> pageResult = crmStatisticsFunnelService.getBusinessPageByDate(pageVO);
@@ -94,37 +66,7 @@ public class CrmStatisticsFunnelController { @@ -94,37 +66,7 @@ public class CrmStatisticsFunnelController {
94 } 66 }
95 67
96 private List<CrmBusinessRespVO> buildBusinessDetailList(List<CrmBusinessDO> list) { 68 private List<CrmBusinessRespVO> buildBusinessDetailList(List<CrmBusinessDO> list) {
97 - if (CollUtil.isEmpty(list)) {  
98 - return Collections.emptyList();  
99 - }  
100 - // 1.1 获取客户列表  
101 - Map<Long, CrmCustomerDO> customerMap = customerService.getCustomerMap(  
102 - convertSet(list, CrmBusinessDO::getCustomerId));  
103 - // 1.2 获取创建人、负责人列表  
104 - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(list,  
105 - contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));  
106 - Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));  
107 - // 1.3 获得商机状态组  
108 - Map<Long, CrmBusinessStatusTypeDO> statusTypeMap = businessStatusTypeService.getBusinessStatusTypeMap(  
109 - convertSet(list, CrmBusinessDO::getStatusTypeId));  
110 - Map<Long, CrmBusinessStatusDO> statusMap = businessStatusService.getBusinessStatusMap(  
111 - convertSet(list, CrmBusinessDO::getStatusId));  
112 - // 2. 拼接数据  
113 - return BeanUtils.toBean(list, CrmBusinessRespVO.class, businessVO -> {  
114 - // 2.1 设置客户名称  
115 - MapUtils.findAndThen(customerMap, businessVO.getCustomerId(), customer -> businessVO.setCustomerName(customer.getName()));  
116 - // 2.2 设置创建人、负责人名称  
117 - MapUtils.findAndThen(userMap, NumberUtils.parseLong(businessVO.getCreator()),  
118 - user -> businessVO.setCreatorName(user.getNickname()));  
119 - MapUtils.findAndThen(userMap, businessVO.getOwnerUserId(), user -> {  
120 - businessVO.setOwnerUserName(user.getNickname());  
121 - MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> businessVO.setOwnerUserDeptName(dept.getName()));  
122 - });  
123 - // 2.3 设置商机状态  
124 - MapUtils.findAndThen(statusTypeMap, businessVO.getStatusTypeId(), statusType -> businessVO.setStatusTypeName(statusType.getName()));  
125 - MapUtils.findAndThen(statusMap, businessVO.getStatusId(), status -> businessVO.setStatusName(  
126 - businessService.getBusinessStatusName(businessVO.getEndStatus(), status)));  
127 - }); 69 + return SpringUtil.getBean(CrmBusinessController.class).buildBusinessDetailList(list);
128 } 70 }
129 71
130 } 72 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticBusinessEndStatusRespVO.java
@@ -7,6 +7,7 @@ import lombok.NoArgsConstructor; @@ -7,6 +7,7 @@ import lombok.NoArgsConstructor;
7 7
8 import java.math.BigDecimal; 8 import java.math.BigDecimal;
9 9
  10 +// TODO @puhui999:改成 CrmStatisticsBusinessSummaryByEndStatusRespVO,按照结束状态
10 @Schema(description = "管理后台 - CRM 商机结束状态统计 Response VO") 11 @Schema(description = "管理后台 - CRM 商机结束状态统计 Response VO")
11 @NoArgsConstructor 12 @NoArgsConstructor
12 @AllArgsConstructor 13 @AllArgsConstructor
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticFunnelRespVO.java
@@ -5,6 +5,7 @@ import lombok.AllArgsConstructor; @@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
5 import lombok.Data; 5 import lombok.Data;
6 import lombok.NoArgsConstructor; 6 import lombok.NoArgsConstructor;
7 7
  8 +// TODO @puhui999:改成 CrmStatisticFunnelSummaryRespVO 更有统计的味道
8 @Schema(description = "管理后台 - CRM 销售漏斗 Response VO") 9 @Schema(description = "管理后台 - CRM 销售漏斗 Response VO")
9 @NoArgsConstructor 10 @NoArgsConstructor
10 @AllArgsConstructor 11 @AllArgsConstructor
@@ -17,6 +18,7 @@ public class CrmStatisticFunnelRespVO { @@ -17,6 +18,7 @@ public class CrmStatisticFunnelRespVO {
17 @Schema(description = "商机数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 18 @Schema(description = "商机数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
18 private Long businessCount; 19 private Long businessCount;
19 20
  21 + // TODO @puhui999:这个改成 businessWinCount 可能会更合适点哈;
20 @Schema(description = "赢单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 22 @Schema(description = "赢单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
21 private Long winCount; 23 private Long winCount;
22 24
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessRespVO.java
@@ -3,14 +3,12 @@ package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel; @@ -3,14 +3,12 @@ package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel;
3 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; 3 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
4 import com.alibaba.excel.annotation.ExcelProperty; 4 import com.alibaba.excel.annotation.ExcelProperty;
5 import io.swagger.v3.oas.annotations.media.Schema; 5 import io.swagger.v3.oas.annotations.media.Schema;
6 -import lombok.AllArgsConstructor;  
7 import lombok.Data; 6 import lombok.Data;
8 -import lombok.NoArgsConstructor;  
9 7
10 import java.math.BigDecimal; 8 import java.math.BigDecimal;
11 import java.time.LocalDateTime; 9 import java.time.LocalDateTime;
12 -import java.util.List;  
13 10
  11 +// TODO @puhui999:是不是可以删除哈?
14 @Schema(description = "管理后台 - CRM 商机 Response VO") 12 @Schema(description = "管理后台 - CRM 商机 Response VO")
15 @Data 13 @Data
16 @ExcelIgnoreUnannotated 14 @ExcelIgnoreUnannotated
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessSummaryByDateRespVO.java
@@ -15,6 +15,7 @@ public class CrmStatisticsBusinessSummaryByDateRespVO { @@ -15,6 +15,7 @@ public class CrmStatisticsBusinessSummaryByDateRespVO {
15 @Schema(description = "新增商机数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 15 @Schema(description = "新增商机数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
16 private Integer businessCreateCount; 16 private Integer businessCreateCount;
17 17
  18 + // TODO @puhui999:是不是金额哈,不是数量
18 @Schema(description = "新增商机金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 19 @Schema(description = "新增商机金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
19 private BigDecimal businessDealCount; 20 private BigDecimal businessDealCount;
20 21
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsFunnelReqVO.java
@@ -17,6 +17,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -17,6 +17,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
17 17
18 @Schema(description = "管理后台 - CRM 销售漏斗 Request VO") 18 @Schema(description = "管理后台 - CRM 销售漏斗 Request VO")
19 @Data 19 @Data
  20 +// TODO @puhui999:不用写 EqualsAndHashCode、ToString,已经全局 lombok 啦
20 @EqualsAndHashCode(callSuper = true) 21 @EqualsAndHashCode(callSuper = true)
21 @ToString(callSuper = true) 22 @ToString(callSuper = true)
22 public class CrmStatisticsFunnelReqVO extends PageParam { 23 public class CrmStatisticsFunnelReqVO extends PageParam {
@@ -42,6 +43,7 @@ public class CrmStatisticsFunnelReqVO extends PageParam { @@ -42,6 +43,7 @@ public class CrmStatisticsFunnelReqVO extends PageParam {
42 @InEnum(value = DateIntervalEnum.class, message = "时间间隔类型,必须是 {value}") 43 @InEnum(value = DateIntervalEnum.class, message = "时间间隔类型,必须是 {value}")
43 private Integer interval; 44 private Integer interval;
44 45
  46 + // TODO @puhui999:这个全部前端传递哈;参考 CrmStatisticsCustomerReqVO
45 /** 47 /**
46 * 前端如果选择自定义时间, 那么前端传递起始-终止时间, 如果选择其他时间间隔类型, 则由后台计算起始-终止时间 48 * 前端如果选择自定义时间, 那么前端传递起始-终止时间, 如果选择其他时间间隔类型, 则由后台计算起始-终止时间
47 * 并作为参数传递给Mapper 49 * 并作为参数传递给Mapper
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java
@@ -73,6 +73,7 @@ public interface CrmBusinessMapper extends BaseMapperX&lt;CrmBusinessDO&gt; { @@ -73,6 +73,7 @@ public interface CrmBusinessMapper extends BaseMapperX&lt;CrmBusinessDO&gt; {
73 .betweenIfPresent(CrmBusinessDO::getCreateTime, times)); 73 .betweenIfPresent(CrmBusinessDO::getCreateTime, times));
74 } 74 }
75 75
  76 + // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
76 default List<CrmBusinessDO> selectListByOwnerUserIdsAndEndStatusNotNull(Collection<Long> ownerUserIds, LocalDateTime[] times) { 77 default List<CrmBusinessDO> selectListByOwnerUserIdsAndEndStatusNotNull(Collection<Long> ownerUserIds, LocalDateTime[] times) {
77 return selectList(new LambdaQueryWrapperX<CrmBusinessDO>() 78 return selectList(new LambdaQueryWrapperX<CrmBusinessDO>()
78 .in(CrmBusinessDO::getOwnerUserId, ownerUserIds) 79 .in(CrmBusinessDO::getOwnerUserId, ownerUserIds)
@@ -80,6 +81,7 @@ public interface CrmBusinessMapper extends BaseMapperX&lt;CrmBusinessDO&gt; { @@ -80,6 +81,7 @@ public interface CrmBusinessMapper extends BaseMapperX&lt;CrmBusinessDO&gt; {
80 .isNotNull(CrmBusinessDO::getEndStatus)); 81 .isNotNull(CrmBusinessDO::getEndStatus));
81 } 82 }
82 83
  84 + // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
83 default List<CrmBusinessDO> selectListByOwnerUserIdsAndDate(Collection<Long> ownerUserIds, LocalDateTime[] times) { 85 default List<CrmBusinessDO> selectListByOwnerUserIdsAndDate(Collection<Long> ownerUserIds, LocalDateTime[] times) {
84 return selectList(new LambdaQueryWrapperX<CrmBusinessDO>() 86 return selectList(new LambdaQueryWrapperX<CrmBusinessDO>()
85 .in(CrmBusinessDO::getOwnerUserId, ownerUserIds) 87 .in(CrmBusinessDO::getOwnerUserId, ownerUserIds)
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
@@ -19,11 +19,9 @@ import org.apache.ibatis.annotations.Mapper; @@ -19,11 +19,9 @@ import org.apache.ibatis.annotations.Mapper;
19 import org.springframework.lang.Nullable; 19 import org.springframework.lang.Nullable;
20 import org.springframework.util.Assert; 20 import org.springframework.util.Assert;
21 21
22 -import javax.management.ObjectName;  
23 import java.time.LocalDateTime; 22 import java.time.LocalDateTime;
24 import java.util.Collection; 23 import java.util.Collection;
25 import java.util.List; 24 import java.util.List;
26 -import java.util.Set;  
27 25
28 /** 26 /**
29 * 客户 Mapper 27 * 客户 Mapper
@@ -188,6 +186,7 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; { @@ -188,6 +186,7 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
188 return selectCount(query); 186 return selectCount(query);
189 } 187 }
190 188
  189 + // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
191 default Long selectCountByOwnerUserIds(Collection<Long> ownerUserIds, LocalDateTime[] times){ 190 default Long selectCountByOwnerUserIds(Collection<Long> ownerUserIds, LocalDateTime[] times){
192 return selectCount(new LambdaQueryWrapperX<CrmCustomerDO>() 191 return selectCount(new LambdaQueryWrapperX<CrmCustomerDO>()
193 .in(CrmCustomerDO::getOwnerUserId, ownerUserIds) 192 .in(CrmCustomerDO::getOwnerUserId, ownerUserIds)
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
@@ -199,11 +199,12 @@ public interface CrmBusinessService { @@ -199,11 +199,12 @@ public interface CrmBusinessService {
199 * 199 *
200 * @param ownerUserIds 负责人编号 200 * @param ownerUserIds 负责人编号
201 * @param times 时间范围 201 * @param times 时间范围
202 - * @param endStatus 商机结束状态 202 + * @param endStatus 商机结束状态,允许为空
203 * @return 商机数 203 * @return 商机数
204 */ 204 */
205 Long getBusinessCountByOwnerUserIdsAndEndStatus(List<Long> ownerUserIds, LocalDateTime[] times, Integer endStatus); 205 Long getBusinessCountByOwnerUserIdsAndEndStatus(List<Long> ownerUserIds, LocalDateTime[] times, Integer endStatus);
206 206
  207 + // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
207 /** 208 /**
208 * 获得商机列表【数据统计】 209 * 获得商机列表【数据统计】
209 * 210 *
@@ -213,6 +214,7 @@ public interface CrmBusinessService { @@ -213,6 +214,7 @@ public interface CrmBusinessService {
213 */ 214 */
214 List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndEndStatusNotNull(List<Long> ownerUserIds, LocalDateTime[] times); 215 List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndEndStatusNotNull(List<Long> ownerUserIds, LocalDateTime[] times);
215 216
  217 + // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
216 /** 218 /**
217 * 获得商机列表【数据统计】 219 * 获得商机列表【数据统计】
218 * 220 *
@@ -223,10 +225,11 @@ public interface CrmBusinessService { @@ -223,10 +225,11 @@ public interface CrmBusinessService {
223 List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndDate(List<Long> ownerUserIds, LocalDateTime[] times); 225 List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndDate(List<Long> ownerUserIds, LocalDateTime[] times);
224 226
225 /** 227 /**
226 - * 商机分页【数据统计】 228 + * 获得商机分页,目前用于【数据统计】
  229 + *
227 * @param ownerUserIds 负责人编号 230 * @param ownerUserIds 负责人编号
228 * @param times 时间范围 231 * @param times 时间范围
229 - * @param pageNo 页码 232 + * @param pageNo 页码 TODO @puhui999:直接传递 CrmStatisticsFunnelReqVO 吧,虽然有点耦合,但是更清晰一点;
230 * @param pageSize 数量 233 * @param pageSize 数量
231 * @return 商机分页 234 * @return 商机分页
232 */ 235 */
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
@@ -383,6 +383,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -383,6 +383,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
383 return businessMapper.selectCountByOwnerUserIdsAndEndStatus(convertSet(ownerUserIds), times, endStatus); 383 return businessMapper.selectCountByOwnerUserIdsAndEndStatus(convertSet(ownerUserIds), times, endStatus);
384 } 384 }
385 385
  386 + // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
386 @Override 387 @Override
387 public List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndEndStatusNotNull(List<Long> ownerUserIds, LocalDateTime[] times) { 388 public List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndEndStatusNotNull(List<Long> ownerUserIds, LocalDateTime[] times) {
388 if (CollUtil.isEmpty(ownerUserIds)) { 389 if (CollUtil.isEmpty(ownerUserIds)) {
@@ -391,6 +392,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -391,6 +392,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
391 return businessMapper.selectListByOwnerUserIdsAndEndStatusNotNull(convertSet(ownerUserIds), times); 392 return businessMapper.selectListByOwnerUserIdsAndEndStatusNotNull(convertSet(ownerUserIds), times);
392 } 393 }
393 394
  395 + // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
394 @Override 396 @Override
395 public List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndDate(List<Long> ownerUserIds, LocalDateTime[] times) { 397 public List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndDate(List<Long> ownerUserIds, LocalDateTime[] times) {
396 if (CollUtil.isEmpty(ownerUserIds)) { 398 if (CollUtil.isEmpty(ownerUserIds)) {
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelServiceImpl.java
@@ -51,6 +51,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic @@ -51,6 +51,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic
51 @Resource 51 @Resource
52 private DeptApi deptApi; 52 private DeptApi deptApi;
53 53
  54 + // TODO @puhui999:貌似想了下,可能还是得按照;;;
54 @Override 55 @Override
55 public CrmStatisticFunnelRespVO getFunnelSummary(CrmStatisticsFunnelReqVO reqVO) { 56 public CrmStatisticFunnelRespVO getFunnelSummary(CrmStatisticsFunnelReqVO reqVO) {
56 // 1. 获得用户编号数组 57 // 1. 获得用户编号数组
@@ -76,6 +77,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic @@ -76,6 +77,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic
76 return Collections.emptyList(); 77 return Collections.emptyList();
77 } 78 }
78 79
  80 + // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
79 // 2.1 获得用户负责的商机 81 // 2.1 获得用户负责的商机
80 List<CrmBusinessDO> businessList = businessService.getBusinessListByOwnerUserIdsAndEndStatusNotNull(reqVO.getUserIds(), reqVO.getTimes()); 82 List<CrmBusinessDO> businessList = businessService.getBusinessListByOwnerUserIdsAndEndStatusNotNull(reqVO.getUserIds(), reqVO.getTimes());
81 // 2.2 统计各阶段数据 83 // 2.2 统计各阶段数据
@@ -99,6 +101,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic @@ -99,6 +101,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic
99 } 101 }
100 102
101 // 2. 按天统计,获取分项统计数据 103 // 2. 按天统计,获取分项统计数据
  104 + // TODO @puhui999:可以这个统计,返回的时候,就把数量、金额一起统计好;
102 List<CrmStatisticsBusinessSummaryByDateRespVO> businessCreateCountList = funnelMapper.selectBusinessCreateCountGroupByDate(reqVO); 105 List<CrmStatisticsBusinessSummaryByDateRespVO> businessCreateCountList = funnelMapper.selectBusinessCreateCountGroupByDate(reqVO);
103 List<CrmBusinessDO> businessList = businessService.getBusinessListByOwnerUserIdsAndDate(reqVO.getUserIds(), reqVO.getTimes()); 106 List<CrmBusinessDO> businessList = businessService.getBusinessListByOwnerUserIdsAndDate(reqVO.getUserIds(), reqVO.getTimes());
104 Map<String, BigDecimal> businessDealCountMap = businessList.stream().collect(Collectors.groupingBy(business -> 107 Map<String, BigDecimal> businessDealCountMap = businessList.stream().collect(Collectors.groupingBy(business ->
@@ -128,7 +131,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic @@ -128,7 +131,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic
128 if (CollUtil.isEmpty(pageVO.getUserIds())) { 131 if (CollUtil.isEmpty(pageVO.getUserIds())) {
129 return PageResult.empty(); 132 return PageResult.empty();
130 } 133 }
131 - 134 + // 2. 执行查询
132 return businessService.getBusinessPageByDate(pageVO.getUserIds(), pageVO.getTimes(), pageVO.getPageNo(), pageVO.getPageSize()); 135 return businessService.getBusinessPageByDate(pageVO.getUserIds(), pageVO.getTimes(), pageVO.getPageNo(), pageVO.getPageSize());
133 } 136 }
134 137
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsFunnelMapper.xml
@@ -4,15 +4,16 @@ @@ -4,15 +4,16 @@
4 4
5 <select id="selectBusinessCreateCountGroupByDate" 5 <select id="selectBusinessCreateCountGroupByDate"
6 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticsBusinessSummaryByDateRespVO"> 6 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticsBusinessSummaryByDateRespVO">
7 - SELECT DATE_FORMAT(create_time, '%Y-%m-%d') AS time, COUNT(*) AS businessCreateCount 7 + SELECT
  8 + DATE_FORMAT(create_time, '%Y-%m-%d') AS time,
  9 + COUNT(*) AS businessCreateCount
8 FROM crm_business 10 FROM crm_business
9 WHERE deleted = 0 11 WHERE deleted = 0
10 AND owner_user_id IN 12 AND owner_user_id IN
11 - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">  
12 - #{userId}  
13 - </foreach>  
14 - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND  
15 - #{times[1],javaType=java.time.LocalDateTime} 13 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  14 + #{userId}
  15 + </foreach>
  16 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
16 GROUP BY time 17 GROUP BY time
17 </select> 18 </select>
18 19