Commit eab962725312beb7786c6431fddd4822dc89ef1d

Authored by 芋道源码
Committed by Gitee
2 parents 94b724e3 03213e32

!909 feat: [CRM-客户分析]增加[时间间隔]选项

Merge pull request !909 from dhb52/develop
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/DateIntervalEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.common.enums;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +/**
  10 + * 时间间隔类型枚举
  11 + *
  12 + * @author dhb52
  13 + */
  14 +@Getter
  15 +@AllArgsConstructor
  16 +public enum DateIntervalEnum implements IntArrayValuable {
  17 +
  18 + TODAY(1, "今天"),
  19 + YESTERDAY(2, "昨天"),
  20 + THIS_WEEK(3, "本周"),
  21 + LAST_WEEK(4, "上周"),
  22 + THIS_MONTH(5, "本月"),
  23 + LAST_MONTH(6, "上月"),
  24 + THIS_QUARTER(7, "本季度"),
  25 + LAST_QUARTER(8, "上季度"),
  26 + THIS_YEAR(9, "本年"),
  27 + LAST_YEAR(10, "去年"),
  28 + CUSTOMER(11, "自定义"),
  29 + ;
  30 +
  31 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DateIntervalEnum::getType).toArray();
  32 +
  33 + /**
  34 + * 类型
  35 + */
  36 + private final Integer type;
  37 +
  38 + /**
  39 + * 名称
  40 + */
  41 + private final String name;
  42 +
  43 + @Override
  44 + public int[] array() {
  45 + return ARRAYS;
  46 + }
  47 +
  48 +}
0 49 \ No newline at end of file
... ...
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
... ... @@ -103,4 +103,7 @@ public interface ErrorCodeConstants {
103 103 ErrorCode FOLLOW_UP_RECORD_NOT_EXISTS = new ErrorCode(1_020_013_000, "跟进记录不存在");
104 104 ErrorCode FOLLOW_UP_RECORD_DELETE_DENIED = new ErrorCode(1_020_013_001, "删除跟进记录失败,原因:没有权限");
105 105  
  106 + // ========== 数据统计 1_020_014_000 ==========
  107 + ErrorCode STATISTICS_CUSTOMER_TIMES_NOT_SET = new ErrorCode(1_020_014_000, "自定义时间间隔,必须输入时间区间");
  108 +
106 109 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.http
1 1 # == 1. 客户总量分析 ==
2 2 ### 1.1 客户总量分析(按日)
3   -GET {{baseUrl}}/crm/statistics-customer/get-customer-summary-by-date?deptId=100&times[0]=2024-01-01 00:00:00&times[1]=2024-01-29 23:59:59
  3 +GET {{baseUrl}}/crm/statistics-customer/get-customer-summary-by-date?deptId=100&intervalType=11&times[0]=2024-01-01 00:00:00&times[1]=2024-01-29 23:59:59
4 4 Authorization: Bearer {{token}}
5 5 tenant-id: {{adminTenentId}}
6 6  
7 7 ### 1.2 客户总量分析(按月)
8   -GET {{baseUrl}}/crm/statistics-customer/get-customer-summary-by-date?deptId=100&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
  8 +GET {{baseUrl}}/crm/statistics-customer/get-customer-summary-by-date?deptId=100&intervalType=11&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
9 9 Authorization: Bearer {{token}}
10 10 tenant-id: {{adminTenentId}}
11 11  
12 12 ### 1.3 客户总量统计(按用户)
13   -GET {{baseUrl}}/crm/statistics-customer/get-customer-summary-by-user?deptId=100&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
  13 +GET {{baseUrl}}/crm/statistics-customer/get-customer-summary-by-user?deptId=100&intervalType=11&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
14 14 Authorization: Bearer {{token}}
15 15 tenant-id: {{adminTenentId}}
16 16  
17 17  
18 18 # == 2. 客户跟进次数分析 ==
19 19 ### 2.1 客户跟进次数分析(按日)
20   -GET {{baseUrl}}/crm/statistics-customer/get-followup-summary-by-date?deptId=100&times[0]=2024-01-01 00:00:00&times[1]=2024-01-29 23:59:59
  20 +GET {{baseUrl}}/crm/statistics-customer/get-followup-summary-by-date?deptId=100&intervalType=11&times[0]=2024-01-01 00:00:00&times[1]=2024-01-29 23:59:59
21 21 Authorization: Bearer {{token}}
22 22 tenant-id: {{adminTenentId}}
23 23  
24 24 ### 2.2 客户跟进次数分析(按月)
25   -GET {{baseUrl}}/crm/statistics-customer/get-followup-summary-by-date?deptId=100&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
  25 +GET {{baseUrl}}/crm/statistics-customer/get-followup-summary-by-date?deptId=100&intervalType=11&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
26 26 Authorization: Bearer {{token}}
27 27 tenant-id: {{adminTenentId}}
28 28  
29 29 ### 2.3 客户总量统计(按用户)
30   -GET {{baseUrl}}/crm/statistics-customer/get-followup-summary-by-user?deptId=100&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
  30 +GET {{baseUrl}}/crm/statistics-customer/get-followup-summary-by-user?deptId=100&intervalType=11&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
31 31 Authorization: Bearer {{token}}
32 32 tenant-id: {{adminTenentId}}
33 33  
34 34  
35 35 # == 3. 客户跟进方式分析 ==
36 36 ### 3.1 客户跟进方式分析
37   -GET {{baseUrl}}/crm/statistics-customer/get-followup-summary-by-type?deptId=100&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
  37 +GET {{baseUrl}}/crm/statistics-customer/get-followup-summary-by-type?deptId=100&intervalType=11&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
38 38 Authorization: Bearer {{token}}
39 39 tenant-id: {{adminTenentId}}
40 40 tenant-id: {{adminTenentId}}
... ... @@ -42,7 +42,7 @@ tenant-id: {{adminTenentId}}
42 42  
43 43 # == 4. 客户成交周期 ==
44 44 ### 4.1 合同摘要信息(客户转化率页面)
45   -GET {{baseUrl}}/crm/statistics-customer/get-contract-summary?deptId=100&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
  45 +GET {{baseUrl}}/crm/statistics-customer/get-contract-summary?deptId=100&intervalType=11&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
46 46 Authorization: Bearer {{token}}
47 47 tenant-id: {{adminTenentId}}
48 48 tenant-id: {{adminTenentId}}
... ... @@ -50,19 +50,19 @@ tenant-id: {{adminTenentId}}
50 50  
51 51 # == 5. 客户成交周期 ==
52 52 ### 5.1 客户成交周期(按日)
53   -GET {{baseUrl}}/crm/statistics-customer/get-customer-deal-cycle-by-date?deptId=100&times[0]=2024-01-01 00:00:00&times[1]=2024-01-29 23:59:59
  53 +GET {{baseUrl}}/crm/statistics-customer/get-customer-deal-cycle-by-date?deptId=100&intervalType=11&times[0]=2024-01-01 00:00:00&times[1]=2024-01-29 23:59:59
54 54 Authorization: Bearer {{token}}
55 55 tenant-id: {{adminTenentId}}
56 56 tenant-id: {{adminTenentId}}
57 57  
58 58 ### 5.2 客户成交周期(按月)
59   -GET {{baseUrl}}/crm/statistics-customer/get-customer-deal-cycle-by-date?deptId=100&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
  59 +GET {{baseUrl}}/crm/statistics-customer/get-customer-deal-cycle-by-date?deptId=100&intervalType=11&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
60 60 Authorization: Bearer {{token}}
61 61 tenant-id: {{adminTenentId}}
62 62 tenant-id: {{adminTenentId}}
63 63  
64 64 ### 5.3 获取客户成交周期(按用户)
65   -GET {{baseUrl}}/crm/statistics-customer/get-customer-deal-cycle-by-user?deptId=100&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
  65 +GET {{baseUrl}}/crm/statistics-customer/get-customer-deal-cycle-by-user?deptId=100&intervalType=11&times[0]=2023-01-01 00:00:00&times[1]=2024-12-12 23:59:59
66 66 Authorization: Bearer {{token}}
67 67 tenant-id: {{adminTenentId}}
68 68 tenant-id: {{adminTenentId}}
69 69 \ No newline at end of file
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerReqVO.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer;
2 2  
3   -import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
  3 +import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum;
  4 +import cn.iocoder.yudao.framework.common.validation.InEnum;
4 5 import io.swagger.v3.oas.annotations.media.Schema;
5   -import jakarta.validation.constraints.NotEmpty;
6 6 import jakarta.validation.constraints.NotNull;
7 7 import lombok.Data;
8 8 import org.springframework.format.annotation.DateTimeFormat;
... ... @@ -28,31 +28,28 @@ public class CrmStatisticsCustomerReqVO {
28 28  
29 29 /**
30 30 * userIds 目前不用前端传递,目前是方便后端通过 deptId 读取编号后,设置回来
31   - * <p>
32 31 * 后续,可能会支持选择部分用户进行查询
33 32 */
34 33 @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2")
35 34 private List<Long> userIds;
36 35  
37   - @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.REQUIRED)
  36 + @Schema(description = "时间间隔类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  37 + @InEnum(value = DateIntervalEnum.class, message = "时间间隔类型,必须是 {value}")
  38 + private Integer intervalType;
  39 +
  40 + /**
  41 + * 前端如果选择自定义时间, 那么前端传递起始-终止时间, 如果选择其他时间间隔类型, 则由后台计算起始-终止时间
  42 + * 并作为参数传递给Mapper
  43 + */
  44 + @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
38 45 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
39   - @NotEmpty(message = "时间范围不能为空")
40 46 private LocalDateTime[] times;
41 47  
42   - // TODO @dhb52:这个时间间隔,建议前端传递;例如说:字段叫 interval,枚举有天、周、月、季度、年。因为一般分析类的系统,都是交给用户选择筛选时间间隔,而我们这里是默认根据日期选项,默认对应的 interval 而已
43   - // 然后实现上,可以在 common 包的 enums 加个 DateIntervalEnum,里面一个是 interval 字段,枚举过去,然后有个 pattern 字段,用于格式化时间格式;
44   - // 这样的话,可以通过 interval 获取到 pattern,然后前端就可以根据 pattern 格式化时间,计算还是交给数据库
45 48 /**
46 49 * group by DATE_FORMAT(field, #{dateFormat})
  50 + * 非前端传递, 由Service计算后传递给Mapper的参数
47 51 */
48 52 @Schema(description = "Group By 日期格式", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "%Y%m")
49 53 private String sqlDateFormat;
50 54  
51   - // TODO @dhb52:这个字段,目前是不是没啥用呀?
52   - /**
53   - * 数据类型 {@link CrmBizTypeEnum}
54   - */
55   - @Schema(description = "数据类型", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2")
56   - private Integer bizType;
57   -
58 55 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsCustomerMapper.java
... ... @@ -13,33 +13,32 @@ import java.util.List;
13 13 @Mapper
14 14 public interface CrmStatisticsCustomerMapper {
15 15  
16   - // TODO @dhb52:拼写,GroupBy。一般 idea 如果出现绿色的警告,可能是单词拼写错误,建议是要修改的哈;
17   - List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerCreateCountGroupbyDate(CrmStatisticsCustomerReqVO reqVO); // 已经 review
  16 + List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerCreateCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); // 已经 review
18 17  
19   - List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerDealCountGroupbyDate(CrmStatisticsCustomerReqVO reqVO); // 已经 review
  18 + List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerDealCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); // 已经 review
20 19  
21   - List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerCreateCountGroupbyUser(CrmStatisticsCustomerReqVO reqVO); // 已经 review
  20 + List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerCreateCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); // 已经 review
22 21  
23   - List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerDealCountGroupbyUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review
  22 + List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerDealCountGroupByUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review
24 23  
25   - List<CrmStatisticsCustomerSummaryByUserRespVO> selectContractPriceGroupbyUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review
  24 + List<CrmStatisticsCustomerSummaryByUserRespVO> selectContractPriceGroupByUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review
26 25  
27   - List<CrmStatisticsCustomerSummaryByUserRespVO> selectReceivablePriceGroupbyUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review
  26 + List<CrmStatisticsCustomerSummaryByUserRespVO> selectReceivablePriceGroupByUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review
28 27  
29   - List<CrmStatisticsFollowupSummaryByDateRespVO> selectFollowupRecordCountGroupbyDate(CrmStatisticsCustomerReqVO reqVO);
  28 + List<CrmStatisticsFollowupSummaryByDateRespVO> selectFollowupRecordCountGroupByDate(CrmStatisticsCustomerReqVO reqVO);
30 29  
31   - List<CrmStatisticsFollowupSummaryByDateRespVO> selectFollowupCustomerCountGroupbyDate(CrmStatisticsCustomerReqVO reqVO);
  30 + List<CrmStatisticsFollowupSummaryByDateRespVO> selectFollowupCustomerCountGroupByDate(CrmStatisticsCustomerReqVO reqVO);
32 31  
33   - List<CrmStatisticsFollowupSummaryByUserRespVO> selectFollowupRecordCountGroupbyUser(CrmStatisticsCustomerReqVO reqVO);
  32 + List<CrmStatisticsFollowupSummaryByUserRespVO> selectFollowupRecordCountGroupByUser(CrmStatisticsCustomerReqVO reqVO);
34 33  
35   - List<CrmStatisticsFollowupSummaryByUserRespVO> selectFollowupCustomerCountGroupbyUser(CrmStatisticsCustomerReqVO reqVO);
  34 + List<CrmStatisticsFollowupSummaryByUserRespVO> selectFollowupCustomerCountGroupByUser(CrmStatisticsCustomerReqVO reqVO);
36 35  
37 36 List<CrmStatisticsCustomerContractSummaryRespVO> selectContractSummary(CrmStatisticsCustomerReqVO reqVO);
38 37  
39   - List<CrmStatisticsFollowupSummaryByTypeRespVO> selectFollowupRecordCountGroupbyType(CrmStatisticsCustomerReqVO reqVO);
  38 + List<CrmStatisticsFollowupSummaryByTypeRespVO> selectFollowupRecordCountGroupByType(CrmStatisticsCustomerReqVO reqVO);
40 39  
41   - List<CrmStatisticsCustomerDealCycleByDateRespVO> selectCustomerDealCycleGroupbyDate(CrmStatisticsCustomerReqVO reqVO);
  40 + List<CrmStatisticsCustomerDealCycleByDateRespVO> selectCustomerDealCycleGroupByDate(CrmStatisticsCustomerReqVO reqVO);
42 41  
43   - List<CrmStatisticsCustomerDealCycleByUserRespVO> selectCustomerDealCycleGroupbyUser(CrmStatisticsCustomerReqVO reqVO);
  42 + List<CrmStatisticsCustomerDealCycleByUserRespVO> selectCustomerDealCycleGroupByUser(CrmStatisticsCustomerReqVO reqVO);
44 43  
45 44 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerServiceImpl.java
1 1 package cn.iocoder.yudao.module.crm.service.statistics;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.date.DateTime;
  5 +import cn.hutool.core.date.DateUtil;
4 6 import cn.hutool.core.date.LocalDateTimeUtil;
5 7 import cn.hutool.core.util.ObjUtil;
  8 +import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum;
6 9 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
7 10 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
8 11 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
9 12 import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsCustomerMapper;
10   -import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
11 13 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
12 14 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
13 15 import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
... ... @@ -20,14 +22,15 @@ import org.springframework.validation.annotation.Validated;
20 22  
21 23 import java.math.BigDecimal;
22 24 import java.time.LocalDateTime;
23   -import java.util.ArrayList;
24 25 import java.util.Collections;
25 26 import java.util.List;
26 27 import java.util.Map;
27 28 import java.util.stream.Stream;
28 29  
  30 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
29 31 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
30 32 import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.*;
  33 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.STATISTICS_CUSTOMER_TIMES_NOT_SET;
31 34  
32 35 /**
33 36 * CRM 客户分析 Service 实现类
... ... @@ -58,114 +61,107 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
58 61 @Override
59 62 public List<CrmStatisticsCustomerSummaryByDateRespVO> getCustomerSummaryByDate(CrmStatisticsCustomerReqVO reqVO) {
60 63 // 1. 获得用户编号数组
61   - final List<Long> userIds = getUserIds(reqVO);
  64 + List<Long> userIds = getUserIds(reqVO);
62 65 if (CollUtil.isEmpty(userIds)) {
63 66 return Collections.emptyList();
64 67 }
65 68 reqVO.setUserIds(userIds);
66 69  
67 70 // 2. 获取分项统计数据
68   - // TODO @dhb52:如果是 list 变量,要么 List 要么 s 后缀
69   - reqVO.setSqlDateFormat(getSqlDateFormat(reqVO.getTimes()[0], reqVO.getTimes()[1]));
70   - final List<CrmStatisticsCustomerSummaryByDateRespVO> customerCreateCount = customerMapper.selectCustomerCreateCountGroupbyDate(reqVO);
71   - final List<CrmStatisticsCustomerSummaryByDateRespVO> customerDealCount = customerMapper.selectCustomerDealCountGroupbyDate(reqVO);
72   -
73   - // 3. 获取时间序列
74   - // TODO @dhb52:3 和 4 其实做的是一类事情,所以可以考虑 3.1 获取时间序列、3.2 合并统计数据 这样注释;然后中间就不空行了;就是说,一般空行的目的,是让逻辑分片,看着整体性更好,但是不能让逻辑感觉碎碎的;
75   - final List<String> times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]);
76   -
77   - // 4. 合并统计数据
78   - // TODO @dhb52:这个是不是要 add 到 respVoList 里?或者还可以 convertList(times, time -> new CrmStatisticsCustomerDealCycleByDateRespVO()...)
79   - List<CrmStatisticsCustomerSummaryByDateRespVO> respVoList = new ArrayList<>(times.size());
80   - final Map<String, Integer> customerCreateCountMap = convertMap(customerCreateCount,
  71 + initParams(reqVO);
  72 + List<CrmStatisticsCustomerSummaryByDateRespVO> customerCreateCountVoList = customerMapper.selectCustomerCreateCountGroupByDate(reqVO);
  73 + List<CrmStatisticsCustomerSummaryByDateRespVO> customerDealCountVoList = customerMapper.selectCustomerDealCountGroupByDate(reqVO);
  74 +
  75 + // 3. 合并数据
  76 + List<String> times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]);
  77 + Map<String, Integer> customerCreateCountMap = convertMap(customerCreateCountVoList,
81 78 CrmStatisticsCustomerSummaryByDateRespVO::getTime,
82 79 CrmStatisticsCustomerSummaryByDateRespVO::getCustomerCreateCount);
83   - final Map<String, Integer> customerDealCountMap = convertMap(customerDealCount,
  80 + Map<String, Integer> customerDealCountMap = convertMap(customerDealCountVoList,
84 81 CrmStatisticsCustomerSummaryByDateRespVO::getTime,
85 82 CrmStatisticsCustomerSummaryByDateRespVO::getCustomerDealCount);
86   - times.forEach(time -> respVoList.add(
87   - new CrmStatisticsCustomerSummaryByDateRespVO().setTime(time)
  83 + List<CrmStatisticsCustomerSummaryByDateRespVO> respVoList = convertList(times,
  84 + time -> new CrmStatisticsCustomerSummaryByDateRespVO()
  85 + .setTime(time)
88 86 .setCustomerCreateCount(customerCreateCountMap.getOrDefault(time, 0))
89   - .setCustomerDealCount(customerDealCountMap.getOrDefault(time, 0))
90   - ));
  87 + .setCustomerDealCount(customerDealCountMap.getOrDefault(time, 0)));
  88 +
91 89 return respVoList;
92 90 }
93 91  
94 92 @Override
95 93 public List<CrmStatisticsCustomerSummaryByUserRespVO> getCustomerSummaryByUser(CrmStatisticsCustomerReqVO reqVO) {
96 94 // 1. 获得用户编号数组
97   - final List<Long> userIds = getUserIds(reqVO);
  95 + List<Long> userIds = getUserIds(reqVO);
98 96 if (CollUtil.isEmpty(userIds)) {
99 97 return Collections.emptyList();
100 98 }
101 99 reqVO.setUserIds(userIds);
102 100  
103 101 // 2. 获取分项统计数据
104   - final List<CrmStatisticsCustomerSummaryByUserRespVO> customerCreateCount = customerMapper.selectCustomerCreateCountGroupbyUser(reqVO);
105   - final List<CrmStatisticsCustomerSummaryByUserRespVO> customerDealCount = customerMapper.selectCustomerDealCountGroupbyUser(reqVO);
106   - final List<CrmStatisticsCustomerSummaryByUserRespVO> contractPrice = customerMapper.selectContractPriceGroupbyUser(reqVO);
107   - final List<CrmStatisticsCustomerSummaryByUserRespVO> receivablePrice = customerMapper.selectReceivablePriceGroupbyUser(reqVO);
  102 + initParams(reqVO);
  103 + List<CrmStatisticsCustomerSummaryByUserRespVO> customerCreateCount = customerMapper.selectCustomerCreateCountGroupByUser(reqVO);
  104 + List<CrmStatisticsCustomerSummaryByUserRespVO> customerDealCount = customerMapper.selectCustomerDealCountGroupByUser(reqVO);
  105 + List<CrmStatisticsCustomerSummaryByUserRespVO> contractPrice = customerMapper.selectContractPriceGroupByUser(reqVO);
  106 + List<CrmStatisticsCustomerSummaryByUserRespVO> receivablePrice = customerMapper.selectReceivablePriceGroupByUser(reqVO);
108 107  
109 108 // 3. 合并统计数据
110   - final Map<Long, Integer> customerCreateCountMap = convertMap(customerCreateCount,
  109 + Map<Long, Integer> customerCreateCountMap = convertMap(customerCreateCount,
111 110 CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
112 111 CrmStatisticsCustomerSummaryByUserRespVO::getCustomerCreateCount);
113   - final Map<Long, Integer> customerDealCountMap = convertMap(customerDealCount,
  112 + Map<Long, Integer> customerDealCountMap = convertMap(customerDealCount,
114 113 CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
115 114 CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount);
116   - final Map<Long, BigDecimal> contractPriceMap = convertMap(contractPrice,
  115 + Map<Long, BigDecimal> contractPriceMap = convertMap(contractPrice,
117 116 CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
118 117 CrmStatisticsCustomerSummaryByUserRespVO::getContractPrice);
119   - final Map<Long, BigDecimal> receivablePriceMap = convertMap(receivablePrice,
  118 + Map<Long, BigDecimal> receivablePriceMap = convertMap(receivablePrice,
120 119 CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
121 120 CrmStatisticsCustomerSummaryByUserRespVO::getReceivablePrice);
122   - List<CrmStatisticsCustomerSummaryByUserRespVO> respVoList = new ArrayList<>(userIds.size());
123   - userIds.forEach(userId -> {
124   - final CrmStatisticsCustomerSummaryByUserRespVO vo = new CrmStatisticsCustomerSummaryByUserRespVO();
  121 + List<CrmStatisticsCustomerSummaryByUserRespVO> respVoList = convertList(userIds, userId -> {
  122 + CrmStatisticsCustomerSummaryByUserRespVO vo = new CrmStatisticsCustomerSummaryByUserRespVO();
  123 + // ownerUserId 为基类属性
125 124 vo.setOwnerUserId(userId);
126 125 vo.setCustomerCreateCount(customerCreateCountMap.getOrDefault(userId, 0))
127 126 .setCustomerDealCount(customerDealCountMap.getOrDefault(userId, 0))
128 127 .setContractPrice(contractPriceMap.getOrDefault(userId, BigDecimal.ZERO))
129 128 .setReceivablePrice(receivablePriceMap.getOrDefault(userId, BigDecimal.ZERO));
130   - respVoList.add(vo);
  129 + return vo;
131 130 });
132 131  
133 132 // 4. 拼接用户信息
134 133 appendUserInfo(respVoList);
  134 +
135 135 return respVoList;
136 136 }
137 137  
138 138 @Override
139 139 public List<CrmStatisticsFollowupSummaryByDateRespVO> getFollowupSummaryByDate(CrmStatisticsCustomerReqVO reqVO) {
140 140 // 1. 获得用户编号数组
141   - final List<Long> userIds = getUserIds(reqVO);
  141 + List<Long> userIds = getUserIds(reqVO);
142 142 if (CollUtil.isEmpty(userIds)) {
143 143 return Collections.emptyList();
144 144 }
145 145 reqVO.setUserIds(userIds);
146 146  
147 147 // 2. 获取分项统计数据
148   - reqVO.setSqlDateFormat(getSqlDateFormat(reqVO.getTimes()[0], reqVO.getTimes()[1]));
149   - reqVO.setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType());
150   - final List<CrmStatisticsFollowupSummaryByDateRespVO> followupRecordCount = customerMapper.selectFollowupRecordCountGroupbyDate(reqVO);
151   - final List<CrmStatisticsFollowupSummaryByDateRespVO> followupCustomerCount = customerMapper.selectFollowupCustomerCountGroupbyDate(reqVO);
152   -
153   - // 3. 获取时间序列
154   - final List<String> times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]);
  148 + initParams(reqVO);
  149 + List<CrmStatisticsFollowupSummaryByDateRespVO> followupRecordCount = customerMapper.selectFollowupRecordCountGroupByDate(reqVO);
  150 + List<CrmStatisticsFollowupSummaryByDateRespVO> followupCustomerCount = customerMapper.selectFollowupCustomerCountGroupByDate(reqVO);
155 151  
156   - // 4. 合并统计数据
157   - List<CrmStatisticsFollowupSummaryByDateRespVO> respVoList = new ArrayList<>(times.size());
158   - final Map<String, Integer> followupRecordCountMap = convertMap(followupRecordCount,
  152 + // 3. 合并统计数据
  153 + List<String> times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]);
  154 + Map<String, Integer> followupRecordCountMap = convertMap(followupRecordCount,
159 155 CrmStatisticsFollowupSummaryByDateRespVO::getTime,
160 156 CrmStatisticsFollowupSummaryByDateRespVO::getFollowupRecordCount);
161   - final Map<String, Integer> followupCustomerCountMap = convertMap(followupCustomerCount,
  157 + Map<String, Integer> followupCustomerCountMap = convertMap(followupCustomerCount,
162 158 CrmStatisticsFollowupSummaryByDateRespVO::getTime,
163 159 CrmStatisticsFollowupSummaryByDateRespVO::getFollowupCustomerCount);
164   - times.forEach(time -> respVoList.add(
  160 + List<CrmStatisticsFollowupSummaryByDateRespVO> respVoList = convertList(times, time ->
165 161 new CrmStatisticsFollowupSummaryByDateRespVO().setTime(time)
166 162 .setFollowupRecordCount(followupRecordCountMap.getOrDefault(time, 0))
167 163 .setFollowupCustomerCount(followupCustomerCountMap.getOrDefault(time, 0))
168   - ));
  164 + );
169 165  
170 166 return respVoList;
171 167 }
... ... @@ -173,31 +169,31 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
173 169 @Override
174 170 public List<CrmStatisticsFollowupSummaryByUserRespVO> getFollowupSummaryByUser(CrmStatisticsCustomerReqVO reqVO) {
175 171 // 1. 获得用户编号数组
176   - final List<Long> userIds = getUserIds(reqVO);
  172 + List<Long> userIds = getUserIds(reqVO);
177 173 if (CollUtil.isEmpty(userIds)) {
178 174 return Collections.emptyList();
179 175 }
180 176 reqVO.setUserIds(userIds);
181 177  
182 178 // 2. 获取分项统计数据
183   - reqVO.setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType());
184   - final List<CrmStatisticsFollowupSummaryByUserRespVO> followupRecordCount = customerMapper.selectFollowupRecordCountGroupbyUser(reqVO);
185   - final List<CrmStatisticsFollowupSummaryByUserRespVO> followupCustomerCount = customerMapper.selectFollowupCustomerCountGroupbyUser(reqVO);
  179 + initParams(reqVO);
  180 + List<CrmStatisticsFollowupSummaryByUserRespVO> followupRecordCount = customerMapper.selectFollowupRecordCountGroupByUser(reqVO);
  181 + List<CrmStatisticsFollowupSummaryByUserRespVO> followupCustomerCount = customerMapper.selectFollowupCustomerCountGroupByUser(reqVO);
186 182  
187 183 // 3. 合并统计数据
188   - final Map<Long, Integer> followupRecordCountMap = convertMap(followupRecordCount,
  184 + Map<Long, Integer> followupRecordCountMap = convertMap(followupRecordCount,
189 185 CrmStatisticsFollowupSummaryByUserRespVO::getOwnerUserId,
190 186 CrmStatisticsFollowupSummaryByUserRespVO::getFollowupRecordCount);
191   - final Map<Long, Integer> followupCustomerCountMap = convertMap(followupCustomerCount,
  187 + Map<Long, Integer> followupCustomerCountMap = convertMap(followupCustomerCount,
192 188 CrmStatisticsFollowupSummaryByUserRespVO::getOwnerUserId,
193 189 CrmStatisticsFollowupSummaryByUserRespVO::getFollowupCustomerCount);
194   - List<CrmStatisticsFollowupSummaryByUserRespVO> respVoList = new ArrayList<>(userIds.size());
195   - userIds.forEach(userId -> {
196   - final CrmStatisticsFollowupSummaryByUserRespVO vo = new CrmStatisticsFollowupSummaryByUserRespVO()
  190 + List<CrmStatisticsFollowupSummaryByUserRespVO> respVoList = convertList(userIds, userId -> {
  191 + CrmStatisticsFollowupSummaryByUserRespVO vo = new CrmStatisticsFollowupSummaryByUserRespVO()
197 192 .setFollowupRecordCount(followupRecordCountMap.getOrDefault(userId, 0))
198 193 .setFollowupCustomerCount(followupCustomerCountMap.getOrDefault(userId, 0));
  194 + // ownerUserId 为基类属性
199 195 vo.setOwnerUserId(userId);
200   - respVoList.add(vo);
  196 + return vo;
201 197 });
202 198  
203 199 // 4. 拼接用户信息
... ... @@ -208,19 +204,19 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
208 204 @Override
209 205 public List<CrmStatisticsFollowupSummaryByTypeRespVO> getFollowupSummaryByType(CrmStatisticsCustomerReqVO reqVO) {
210 206 // 1. 获得用户编号数组
211   - final List<Long> userIds = getUserIds(reqVO);
  207 + List<Long> userIds = getUserIds(reqVO);
212 208 if (CollUtil.isEmpty(userIds)) {
213 209 return Collections.emptyList();
214 210 }
215 211 reqVO.setUserIds(userIds);
216 212  
217 213 // 2. 获得排行数据
218   - reqVO.setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType());
219   - List<CrmStatisticsFollowupSummaryByTypeRespVO> respVoList = customerMapper.selectFollowupRecordCountGroupbyType(reqVO);
  214 + initParams(reqVO);
  215 + List<CrmStatisticsFollowupSummaryByTypeRespVO> respVoList = customerMapper.selectFollowupRecordCountGroupByType(reqVO);
220 216  
221 217 // 3. 获取字典数据
222 218 List<DictDataRespDTO> followUpTypes = dictDataApi.getDictDataList(CRM_FOLLOW_UP_TYPE);
223   - final Map<String, String> followUpTypeMap = convertMap(followUpTypes,
  219 + Map<String, String> followUpTypeMap = convertMap(followUpTypes,
224 220 DictDataRespDTO::getValue, DictDataRespDTO::getLabel);
225 221 respVoList.forEach(vo -> {
226 222 vo.setFollowupType(followUpTypeMap.get(vo.getFollowupType()));
... ... @@ -232,26 +228,27 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
232 228 @Override
233 229 public List<CrmStatisticsCustomerContractSummaryRespVO> getContractSummary(CrmStatisticsCustomerReqVO reqVO) {
234 230 // 1. 获得用户编号数组
235   - final List<Long> userIds = getUserIds(reqVO);
  231 + List<Long> userIds = getUserIds(reqVO);
236 232 if (CollUtil.isEmpty(userIds)) {
237 233 return Collections.emptyList();
238 234 }
239 235 reqVO.setUserIds(userIds);
240 236  
241 237 // 2. 获取统计数据
  238 + initParams(reqVO);
242 239 List<CrmStatisticsCustomerContractSummaryRespVO> respVoList = customerMapper.selectContractSummary(reqVO);
243 240  
244 241 // 3. 设置 创建人、负责人、行业、来源
245   - // 获取客户所属行业
  242 + // 3.1 获取客户所属行业
246 243 Map<String, String> industryMap = convertMap(dictDataApi.getDictDataList(CRM_CUSTOMER_INDUSTRY),
247 244 DictDataRespDTO::getValue, DictDataRespDTO::getLabel);
248   - // 获取客户来源
  245 + // 3.2 获取客户来源
249 246 Map<String, String> sourceMap = convertMap(dictDataApi.getDictDataList(CRM_CUSTOMER_SOURCE),
250 247 DictDataRespDTO::getValue, DictDataRespDTO::getLabel);
251   - // 获取创建人、负责人列表
  248 + // 3.3 获取创建人、负责人列表
252 249 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(respVoList,
253 250 vo -> Stream.of(NumberUtils.parseLong(vo.getCreatorUserId()), vo.getOwnerUserId())));
254   -
  251 + // 3.4 设置 创建人、负责人、行业、来源
255 252 respVoList.forEach(vo -> {
256 253 MapUtils.findAndThen(industryMap, vo.getIndustryId(), vo::setIndustryName);
257 254 MapUtils.findAndThen(sourceMap, vo.getSource(), vo::setSourceName);
... ... @@ -266,60 +263,57 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
266 263 @Override
267 264 public List<CrmStatisticsCustomerDealCycleByDateRespVO> getCustomerDealCycleByDate(CrmStatisticsCustomerReqVO reqVO) {
268 265 // 1. 获得用户编号数组
269   - final List<Long> userIds = getUserIds(reqVO);
  266 + List<Long> userIds = getUserIds(reqVO);
270 267 if (CollUtil.isEmpty(userIds)) {
271 268 return Collections.emptyList();
272 269 }
273 270 reqVO.setUserIds(userIds);
274 271  
275 272 // 2. 获取分项统计数据
276   - reqVO.setSqlDateFormat(getSqlDateFormat(reqVO.getTimes()[0], reqVO.getTimes()[1]));
277   - reqVO.setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType());
278   - final List<CrmStatisticsCustomerDealCycleByDateRespVO> customerDealCycle = customerMapper.selectCustomerDealCycleGroupbyDate(reqVO);
279   -
280   - // 3. 获取时间序列
281   - final List<String> times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]);
  273 + initParams(reqVO);
  274 + List<CrmStatisticsCustomerDealCycleByDateRespVO> customerDealCycle = customerMapper.selectCustomerDealCycleGroupByDate(reqVO);
282 275  
283   - // 4. 合并统计数据
284   - List<CrmStatisticsCustomerDealCycleByDateRespVO> respVoList = new ArrayList<>(times.size());
285   - final Map<String, Double> customerDealCycleMap = convertMap(customerDealCycle,
  276 + // 3. 合并统计数据
  277 + List<String> times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]);
  278 + Map<String, Double> customerDealCycleMap = convertMap(customerDealCycle,
286 279 CrmStatisticsCustomerDealCycleByDateRespVO::getTime,
287 280 CrmStatisticsCustomerDealCycleByDateRespVO::getCustomerDealCycle);
288   - times.forEach(time -> respVoList.add(
  281 + List<CrmStatisticsCustomerDealCycleByDateRespVO> respVoList = convertList(times, time ->
289 282 new CrmStatisticsCustomerDealCycleByDateRespVO().setTime(time)
290 283 .setCustomerDealCycle(customerDealCycleMap.getOrDefault(time, 0D))
291   - ));
  284 + );
  285 +
292 286 return respVoList;
293 287 }
294 288  
295 289 @Override
296 290 public List<CrmStatisticsCustomerDealCycleByUserRespVO> getCustomerDealCycleByUser(CrmStatisticsCustomerReqVO reqVO) {
297 291 // 1. 获得用户编号数组
298   - final List<Long> userIds = getUserIds(reqVO);
  292 + List<Long> userIds = getUserIds(reqVO);
299 293 if (CollUtil.isEmpty(userIds)) {
300 294 return Collections.emptyList();
301 295 }
302 296 reqVO.setUserIds(userIds);
303 297  
304 298 // 2. 获取分项统计数据
305   - reqVO.setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType());
306   - final List<CrmStatisticsCustomerDealCycleByUserRespVO> customerDealCycle = customerMapper.selectCustomerDealCycleGroupbyUser(reqVO);
307   - final List<CrmStatisticsCustomerSummaryByUserRespVO> customerDealCount = customerMapper.selectCustomerDealCountGroupbyUser(reqVO);
  299 + initParams(reqVO);
  300 + List<CrmStatisticsCustomerDealCycleByUserRespVO> customerDealCycle = customerMapper.selectCustomerDealCycleGroupByUser(reqVO);
  301 + List<CrmStatisticsCustomerSummaryByUserRespVO> customerDealCount = customerMapper.selectCustomerDealCountGroupByUser(reqVO);
308 302  
309 303 // 3. 合并统计数据
310   - final Map<Long, Double> customerDealCycleMap = convertMap(customerDealCycle,
  304 + Map<Long, Double> customerDealCycleMap = convertMap(customerDealCycle,
311 305 CrmStatisticsCustomerDealCycleByUserRespVO::getOwnerUserId,
312 306 CrmStatisticsCustomerDealCycleByUserRespVO::getCustomerDealCycle);
313   - final Map<Long, Integer> customerDealCountMap = convertMap(customerDealCount,
  307 + Map<Long, Integer> customerDealCountMap = convertMap(customerDealCount,
314 308 CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
315 309 CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount);
316   - List<CrmStatisticsCustomerDealCycleByUserRespVO> respVoList = new ArrayList<>(userIds.size());
317   - userIds.forEach(userId -> {
318   - final CrmStatisticsCustomerDealCycleByUserRespVO vo = new CrmStatisticsCustomerDealCycleByUserRespVO()
  310 + List<CrmStatisticsCustomerDealCycleByUserRespVO> respVoList = convertList(userIds, userId -> {
  311 + CrmStatisticsCustomerDealCycleByUserRespVO vo = new CrmStatisticsCustomerDealCycleByUserRespVO()
319 312 .setCustomerDealCycle(customerDealCycleMap.getOrDefault(userId, 0.0))
320 313 .setCustomerDealCount(customerDealCountMap.getOrDefault(userId, 0));
  314 + // ownerUserId 为基类属性
321 315 vo.setOwnerUserId(userId);
322   - respVoList.add(vo);
  316 + return vo;
323 317 });
324 318  
325 319 // 4. 拼接用户信息
... ... @@ -335,8 +329,9 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
335 329 */
336 330 private <T extends CrmStatisticsCustomerByUserBaseRespVO> void appendUserInfo(List<T> respVoList) {
337 331 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(respVoList,
338   - CrmStatisticsCustomerByUserBaseRespVO::getOwnerUserId));
339   - respVoList.forEach(vo -> MapUtils.findAndThen(userMap, vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname())));
  332 + CrmStatisticsCustomerByUserBaseRespVO::getOwnerUserId));
  333 + respVoList.forEach(vo -> MapUtils.findAndThen(userMap,
  334 + vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname())));
340 335 }
341 336  
342 337 /**
... ... @@ -352,7 +347,7 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
352 347 }
353 348 // 情况二:选中某个部门
354 349 // 2.1 获得部门列表
355   - final Long deptId = reqVO.getDeptId();
  350 + Long deptId = reqVO.getDeptId();
356 351 List<Long> deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId);
357 352 deptIds.add(deptId);
358 353 // 2.2 获得用户编号
... ... @@ -378,7 +373,6 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
378 373 * @param endTime 结束时间
379 374 * @return 时间序列
380 375 */
381   - // TODO @dhb52:可以抽象到 DateUtils 里,开始时间、结束时间,事件间隔,然后返回这个哈;
382 376 private List<String> generateTimeSeries(LocalDateTime startTime, LocalDateTime endTime) {
383 377 boolean byMonth = queryByMonth(startTime, endTime);
384 378 List<String> times = CollUtil.newArrayList();
... ... @@ -404,4 +398,62 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
404 398 return queryByMonth(startTime, endTime) ? SQL_DATE_FORMAT_BY_MONTH : SQL_DATE_FORMAT_BY_DAY;
405 399 }
406 400  
  401 + private void initParams(CrmStatisticsCustomerReqVO reqVO) {
  402 + final Integer intervalType = reqVO.getIntervalType();
  403 +
  404 + // 1. 自定义时间间隔,必须输入起始日期-结束日期
  405 + if (DateIntervalEnum.CUSTOMER.getType().equals(intervalType)) {
  406 + if (ObjUtil.isEmpty(reqVO.getTimes()) || reqVO.getTimes().length != 2) {
  407 + throw exception(STATISTICS_CUSTOMER_TIMES_NOT_SET);
  408 + }
  409 + // 设置 mapper sqlDateFormat 参数
  410 + reqVO.setSqlDateFormat(getSqlDateFormat(reqVO.getTimes()[0], reqVO.getTimes()[1]));
  411 + // 自定义日期无需计算日期参数
  412 + return;
  413 + }
  414 +
  415 + // 2. 根据时间区间类型计算时间段区间日期
  416 + DateTime beginDate = null;
  417 + DateTime endDate = null;
  418 + if (DateIntervalEnum.TODAY.getType().equals(intervalType)) {
  419 + beginDate = DateUtil.beginOfDay(DateUtil.date());
  420 + endDate = DateUtil.endOfDay(DateUtil.date());
  421 + } else if (DateIntervalEnum.YESTERDAY.getType().equals(intervalType)) {
  422 + beginDate = DateUtil.offsetDay(DateUtil.date(), -1);
  423 + endDate = DateUtil.offsetDay(DateUtil.date(), -1);
  424 + } else if (DateIntervalEnum.THIS_WEEK.getType().equals(intervalType)) {
  425 + beginDate = DateUtil.beginOfWeek(DateUtil.date());
  426 + endDate = DateUtil.endOfWeek(DateUtil.date());
  427 + } else if (DateIntervalEnum.LAST_WEEK.getType().equals(intervalType)) {
  428 + beginDate = DateUtil.beginOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1));
  429 + endDate = DateUtil.endOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1));
  430 + } else if (DateIntervalEnum.THIS_MONTH.getType().equals(intervalType)) {
  431 + beginDate = DateUtil.beginOfMonth(DateUtil.date());
  432 + endDate = DateUtil.endOfMonth(DateUtil.date());
  433 + } else if (DateIntervalEnum.LAST_MONTH.getType().equals(intervalType)) {
  434 + beginDate = DateUtil.beginOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1));
  435 + endDate = DateUtil.endOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1));
  436 + } else if (DateIntervalEnum.THIS_QUARTER.getType().equals(intervalType)) {
  437 + beginDate = DateUtil.beginOfQuarter(DateUtil.date());
  438 + endDate = DateUtil.endOfQuarter(DateUtil.date());
  439 + } else if (DateIntervalEnum.LAST_QUARTER.getType().equals(intervalType)) {
  440 + beginDate = DateUtil.beginOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3));
  441 + endDate = DateUtil.endOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3));
  442 + } else if (DateIntervalEnum.THIS_YEAR.getType().equals(intervalType)) {
  443 + beginDate = DateUtil.beginOfYear(DateUtil.date());
  444 + endDate = DateUtil.endOfYear(DateUtil.date());
  445 + } else if (DateIntervalEnum.LAST_YEAR.getType().equals(intervalType)) {
  446 + beginDate = DateUtil.beginOfYear(DateUtil.offsetMonth(DateUtil.date(), -12));
  447 + endDate = DateUtil.endOfYear(DateUtil.offsetMonth(DateUtil.date(), -12));
  448 + }
  449 +
  450 + // 3. 计算开始、结束日期时间,并设置reqVo
  451 + LocalDateTime[] times = new LocalDateTime[2];
  452 + times[0] = LocalDateTimeUtil.beginOfDay(LocalDateTimeUtil.of(beginDate));
  453 + times[1] = LocalDateTimeUtil.endOfDay(LocalDateTimeUtil.of(endDate));
  454 + // 3.1 设置 mapper 时间区间 参数
  455 + reqVO.setTimes(times);
  456 + // 3.2 设置 mapper sqlDateFormat 参数
  457 + reqVO.setSqlDateFormat(getSqlDateFormat(times[0], times[1]));
  458 + }
407 459 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsCustomerMapper.xml
... ... @@ -2,251 +2,233 @@
2 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3 3 <mapper namespace="cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsCustomerMapper">
4 4  
5   - <!-- TODO @dhb52:数据库的关键字,进行大写。例如说,COUNT -->
6   -
7   - <select id="selectCustomerCreateCountGroupbyDate"
  5 + <select id="selectCustomerCreateCountGroupByDate"
8 6 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByDateRespVO">
9 7 SELECT
10   - <!-- TODO @dhb52:下面这个,缩进一个 tab;这样可读性更好哈 -->
11   - DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time,
12   - COUNT(*) AS customerCreateCount
13   - FROM crm_customer
14   - WHERE deleted = 0
15   - AND owner_user_id IN
16   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
17   - #{userId}
18   - </foreach>
19   - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
20   - <!-- TODO @dhb52:这可以考虑不换行,直接跟在后面的 AND,更连贯哈; -->
21   - #{times[1],javaType=java.time.LocalDateTime}
22   - GROUP BY time
  8 + DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time,
  9 + COUNT(*) AS customerCreateCount
  10 + FROM crm_customer
  11 + WHERE deleted = 0
  12 + AND owner_user_id IN
  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}
  17 + GROUP BY time
23 18 </select>
24 19  
25   - <select id="selectCustomerDealCountGroupbyDate"
  20 + <select id="selectCustomerDealCountGroupByDate"
26 21 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByDateRespVO">
27 22 SELECT
28   - <!-- TODO @dhb52:下面这个,缩进一个 tab;这样可读性更好哈 -->
29   - <!-- TODO @dhb52:表变量最好不要用 a、b;可以用 customer 和 constract;虽然长一点,但是一眼看的清楚哈 -->
30   - DATE_FORMAT( b.order_date, #{sqlDateFormat} ) AS time,
31   - count( DISTINCT a.id ) AS customerDealCount
32   - FROM crm_customer AS a
33   - LEFT JOIN crm_contract AS b ON b.customer_id = a.id
34   - WHERE a.deleted = 0 AND b.deleted = 0
35   - AND b.audit_status = 20
36   - AND a.owner_user_id IN
37   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
38   - #{userId}
39   - </foreach>
40   - <!-- TODO @dhb52:这个应该是 order_date 的范围哈;貌似如果改成这样,不需要查询 customer 表,只要 contract 表就 ok 拉 -->
41   - AND b.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
42   - #{times[1],javaType=java.time.LocalDateTime}
  23 + DATE_FORMAT( order_date, #{sqlDateFormat} ) AS time,
  24 + COUNT( DISTINCT customer_id ) AS customerDealCount
  25 + FROM crm_contract
  26 + WHERE deleted = 0
  27 + AND audit_status = 20
  28 + AND owner_user_id IN
  29 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  30 + #{userId}
  31 + </foreach>
  32 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
43 33 GROUP BY time
44 34 </select>
45 35  
46   - <!-- TODO @dhb52:根据上面建议,进行优化 -->
47   - <select id="selectCustomerCreateCountGroupbyUser"
  36 + <select id="selectCustomerCreateCountGroupByUser"
48 37 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO">
49   - SELECT owner_user_id, COUNT(1) AS customer_create_count
50   - FROM crm_customer
51   - WHERE deleted = 0
52   - AND owner_user_id in
53   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
54   - #{userId}
55   - </foreach>
56   - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
57   - #{times[1],javaType=java.time.LocalDateTime}
  38 + SELECT
  39 + owner_user_id,
  40 + COUNT(1) AS customer_create_count
  41 + FROM crm_customer
  42 + WHERE deleted = 0
  43 + AND owner_user_id in
  44 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  45 + #{userId}
  46 + </foreach>
  47 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
58 48 GROUP BY owner_user_id
59 49 </select>
60 50  
61   - <!-- TODO @dhb52:根据上面建议,进行优化 -->
62   - <select id="selectCustomerDealCountGroupbyUser"
  51 + <select id="selectCustomerDealCountGroupByUser"
63 52 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO">
64   - SELECT a.owner_user_id, count( DISTINCT a.id ) AS customer_deal_count
65   - FROM crm_customer AS a
66   - LEFT JOIN crm_contract AS b ON b.customer_id = a.id
67   - WHERE a.deleted = 0 AND b.deleted = 0
68   - AND b.audit_status = 20
69   - AND a.owner_user_id IN
70   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
71   - #{userId}
72   - </foreach>
73   - AND b.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
74   - #{times[1],javaType=java.time.LocalDateTime}
75   - GROUP BY a.owner_user_id
  53 + SELECT
  54 + customer.owner_user_id,
  55 + COUNT( DISTINCT customer.id ) AS customer_deal_count
  56 + FROM crm_customer AS customer
  57 + LEFT JOIN crm_contract AS contract ON contract.customer_id = customer.id
  58 + WHERE customer.deleted = 0 AND contract.deleted = 0
  59 + AND contract.audit_status = 20
  60 + AND customer.owner_user_id IN
  61 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  62 + #{userId}
  63 + </foreach>
  64 + AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
  65 + GROUP BY customer.owner_user_id
76 66 </select>
77 67  
78   - <!-- TODO @dhb52:根据上面建议,进行优化 -->
79   - <select id="selectContractPriceGroupbyUser"
  68 + <select id="selectContractPriceGroupByUser"
80 69 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO">
81   - SELECT owner_user_id, IFNULL(SUM(total_price), 0) AS contract_price
82   - FROM crm_contract
83   - WHERE deleted = 0
84   - AND audit_status = 20
85   - AND owner_user_id in
86   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
87   - #{userId}
88   - </foreach>
89   - AND order_date BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
90   - #{times[1],javaType=java.time.LocalDateTime}
91   - GROUP BY owner_user_id
  70 + SELECT
  71 + owner_user_id,
  72 + IFNULL(SUM(total_price), 0) AS contract_price
  73 + FROM crm_contract
  74 + WHERE deleted = 0
  75 + AND audit_status = 20
  76 + AND owner_user_id in
  77 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  78 + #{userId}
  79 + </foreach>
  80 + AND order_date BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
  81 + GROUP BY owner_user_id
92 82 </select>
93 83  
94   -
95   - <!-- TODO @dhb52:根据上面建议,进行优化 -->
96   - <select id="selectReceivablePriceGroupbyUser"
  84 + <select id="selectReceivablePriceGroupByUser"
97 85 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO">
98   - SELECT owner_user_id,
99   - IFNULL(SUM(price), 0) AS receivable_price
100   - FROM crm_receivable
101   - WHERE deleted = 0
102   - AND audit_status = 20
103   - AND owner_user_id IN
104   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
105   - #{userId}
106   - </foreach>
107   - AND return_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
108   - #{times[1],javaType=java.time.LocalDateTime}
109   - GROUP BY owner_user_id
  86 + SELECT
  87 + owner_user_id,
  88 + IFNULL(SUM(price), 0) AS receivable_price
  89 + FROM crm_receivable
  90 + WHERE deleted = 0
  91 + AND audit_status = 20
  92 + AND owner_user_id IN
  93 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  94 + #{userId}
  95 + </foreach>
  96 + AND return_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
  97 + GROUP BY owner_user_id
110 98 </select>
111 99  
112   - <select id="selectFollowupRecordCountGroupbyDate"
  100 + <select id="selectFollowupRecordCountGroupByDate"
113 101 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowupSummaryByDateRespVO">
114   - SELECT DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time,
115   - count(*) AS followup_record_count
116   - FROM crm_follow_up_record
117   - WHERE creator IN
118   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
119   - #{userId}
120   - </foreach>
121   - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
122   - #{times[1],javaType=java.time.LocalDateTime}
123   - AND biz_type = #{bizType}
124   - GROUP BY time
  102 + SELECT
  103 + DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time,
  104 + COUNT(*) AS followup_record_count
  105 + FROM crm_follow_up_record
  106 + WHERE creator IN
  107 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  108 + #{userId}
  109 + </foreach>
  110 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
  111 + AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type}
  112 + GROUP BY time
125 113 </select>
126 114  
127   - <select id="selectFollowupCustomerCountGroupbyDate"
  115 + <select id="selectFollowupCustomerCountGroupByDate"
128 116 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowupSummaryByDateRespVO">
129 117 SELECT
130   - DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time,
131   - count(DISTINCT biz_id) AS followup_customer_count
132   - FROM crm_follow_up_record
133   - WHERE creator IN
134   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
135   - #{userId}
136   - </foreach>
137   - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
138   - #{times[1],javaType=java.time.LocalDateTime}
139   - AND biz_type = #{bizType}
140   - GROUP BY time
  118 + DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time,
  119 + COUNT(DISTINCT biz_id) AS followup_customer_count
  120 + FROM crm_follow_up_record
  121 + WHERE creator IN
  122 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  123 + #{userId}
  124 + </foreach>
  125 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
  126 + AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type}
  127 + GROUP BY time
141 128 </select>
142 129  
143   - <select id="selectFollowupRecordCountGroupbyUser"
  130 + <select id="selectFollowupRecordCountGroupByUser"
144 131 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowupSummaryByUserRespVO">
145   - SELECT creator as owner_user_id,
146   - count(*) AS followup_record_count
147   - FROM crm_follow_up_record
148   - WHERE creator IN
149   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
150   - #{userId}
151   - </foreach>
152   - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
153   - #{times[1],javaType=java.time.LocalDateTime}
154   - AND biz_type = #{bizType}
155   - GROUP BY creator
  132 + SELECT
  133 + creator as owner_user_id,
  134 + COUNT(*) AS followup_record_count
  135 + FROM crm_follow_up_record
  136 + WHERE creator IN
  137 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  138 + #{userId}
  139 + </foreach>
  140 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
  141 + AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type}
  142 + GROUP BY creator
156 143 </select>
157 144  
158   - <select id="selectFollowupCustomerCountGroupbyUser"
  145 + <select id="selectFollowupCustomerCountGroupByUser"
159 146 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowupSummaryByUserRespVO">
160   - SELECT creator as owner_user_id,
161   - count(DISTINCT biz_id) AS followup_customer_count
162   - FROM crm_follow_up_record
163   - WHERE creator IN
164   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
165   - #{userId}
166   - </foreach>
167   - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
168   - #{times[1],javaType=java.time.LocalDateTime}
169   - AND biz_type = #{bizType}
170   - GROUP BY creator
  147 + SELECT
  148 + creator as owner_user_id,
  149 + COUNT(DISTINCT biz_id) AS followup_customer_count
  150 + FROM crm_follow_up_record
  151 + WHERE creator IN
  152 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  153 + #{userId}
  154 + </foreach>
  155 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
  156 + AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type}
  157 + GROUP BY creator
171 158 </select>
172 159  
173   - <select id="selectFollowupRecordCountGroupbyType"
  160 + <select id="selectFollowupRecordCountGroupByType"
174 161 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowupSummaryByTypeRespVO">
175 162 SELECT
176   - type AS followupType,
177   - count(*) AS followup_record_count
178   - FROM crm_follow_up_record
179   - WHERE creator IN
180   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
181   - #{userId}
182   - </foreach>
183   - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
184   - #{times[1],javaType=java.time.LocalDateTime}
185   - AND biz_type = #{bizType}
186   - GROUP BY followupType
  163 + type AS followupType,
  164 + COUNT(*) AS followup_record_count
  165 + FROM crm_follow_up_record
  166 + WHERE creator IN
  167 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  168 + #{userId}
  169 + </foreach>
  170 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
  171 + AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type}
  172 + GROUP BY followupType
187 173 </select>
188 174  
189 175 <select id="selectContractSummary"
190 176 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerContractSummaryRespVO">
191 177 SELECT
192   - a.`name` AS customer_name,
193   - b.`name` AS contract_name,
194   - b.total_price,
195   - IFNULL( c.price, 0 ) AS receivable_price,
196   - a.industry_id,
197   - a.source,
198   - a.owner_user_id,
199   - a.creator AS creator_user_id,
200   - a.create_time,
201   - b.order_date
202   - FROM
203   - crm_customer AS a
204   - INNER JOIN crm_contract AS b ON a.id = b.customer_id
205   - LEFT JOIN crm_receivable AS c ON b.id = c.contract_id
206   - WHERE a.deleted = 0 AND b.deleted = 0 AND c.deleted = 0
207   - AND b.audit_status = 20
208   - AND a.owner_user_id IN
209   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
210   - #{userId}
211   - </foreach>
212   - AND b.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
213   - #{times[1],javaType=java.time.LocalDateTime}
  178 + customer.`name` AS customer_name,
  179 + contract.`name` AS contract_name,
  180 + contract.total_price,
  181 + IFNULL( receivable.price, 0 ) AS receivable_price,
  182 + customer.industry_id,
  183 + customer.source,
  184 + customer.owner_user_id,
  185 + customer.creator AS creator_user_id,
  186 + customer.create_time,
  187 + contract.order_date
  188 + FROM crm_customer AS customer
  189 + INNER JOIN crm_contract AS contract ON customer.id = contract.customer_id
  190 + LEFT JOIN crm_receivable AS receivable ON contract.id = receivable.contract_id
  191 + WHERE customer.deleted = 0 AND contract.deleted = 0 AND receivable.deleted = 0
  192 + AND contract.audit_status = 20
  193 + AND customer.owner_user_id IN
  194 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  195 + #{userId}
  196 + </foreach>
  197 + AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
214 198 </select>
215 199  
216   - <select id="selectCustomerDealCycleGroupbyDate"
  200 + <select id="selectCustomerDealCycleGroupByDate"
217 201 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerDealCycleByDateRespVO">
218 202 SELECT
219   - DATE_FORMAT( b.order_date, #{sqlDateFormat} ) AS time,
220   - IFNULL( TRUNCATE ( AVG( TIMESTAMPDIFF( DAY, a.create_time, b.order_date )), 1 ), 0 ) AS customer_deal_cycle
221   - FROM crm_customer AS a
222   - LEFT JOIN crm_contract AS b ON b.customer_id = a.id
223   - WHERE a.deleted = 0 AND b.deleted = 0
224   - AND b.audit_status = 20
225   - AND a.owner_user_id IN
226   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
227   - #{userId}
228   - </foreach>
229   - AND b.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
230   - #{times[1],javaType=java.time.LocalDateTime}
231   - GROUP BY time
  203 + DATE_FORMAT( contract.order_date, #{sqlDateFormat} ) AS time,
  204 + IFNULL( TRUNCATE ( AVG( TIMESTAMPDIFF( DAY, customer.create_time, contract.order_date )), 1 ), 0 ) AS customer_deal_cycle
  205 + FROM crm_customer AS customer
  206 + LEFT JOIN crm_contract AS contract ON contract.customer_id = customer.id
  207 + WHERE customer.deleted = 0 AND contract.deleted = 0
  208 + AND contract.audit_status = 20
  209 + AND customer.owner_user_id IN
  210 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  211 + #{userId}
  212 + </foreach>
  213 + AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
  214 + GROUP BY time
232 215 </select>
233 216  
234   - <select id="selectCustomerDealCycleGroupbyUser"
  217 + <select id="selectCustomerDealCycleGroupByUser"
235 218 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerDealCycleByUserRespVO">
236 219 SELECT
237   - a.owner_user_id,
238   - IFNULL( TRUNCATE ( AVG( TIMESTAMPDIFF( DAY, a.create_time, b.order_date )), 1 ), 0 ) AS customer_deal_cycle
239   - FROM crm_customer AS a
240   - LEFT JOIN crm_contract AS b ON b.customer_id = a.id
241   - WHERE a.deleted = 0 AND b.deleted = 0
242   - AND b.audit_status = 20
243   - AND a.owner_user_id IN
244   - <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
245   - #{userId}
246   - </foreach>
247   - AND b.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
248   - #{times[1],javaType=java.time.LocalDateTime}
249   - GROUP BY a.owner_user_id
  220 + customer.owner_user_id,
  221 + IFNULL( TRUNCATE ( AVG( TIMESTAMPDIFF( DAY, customer.create_time, contract.order_date )), 1 ), 0 ) AS customer_deal_cycle
  222 + FROM crm_customer AS customer
  223 + LEFT JOIN crm_contract AS contract ON contract.customer_id = customer.id
  224 + WHERE customer.deleted = 0 AND contract.deleted = 0
  225 + AND contract.audit_status = 20
  226 + AND customer.owner_user_id IN
  227 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  228 + #{userId}
  229 + </foreach>
  230 + AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
  231 + GROUP BY customer.owner_user_id
250 232 </select>
251 233  
252 234 </mapper>
... ...