Commit 9ea43ce55ac7a79ac1894d8291c498515ef6da69

Authored by 芋道源码
Committed by Gitee
2 parents 9b9f54bb eeed1fdf

!932 CRM: 完善用户画像数据统计

Merge pull request !932 from puhui999/develop
Showing 10 changed files with 118 additions and 190 deletions
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsPortraitController.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.statistics;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerReqVO;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticsPortraitReqVO;
5 5 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerAreaRespVO;
6 6 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerIndustryRespVO;
7 7 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerLevelRespVO;
... ... @@ -30,34 +30,32 @@ public class CrmStatisticsPortraitController {
30 30 @Resource
31 31 private CrmStatisticsPortraitService statisticsPortraitService;
32 32  
33   - // TODO @puhui999:搞个属于自己的 CrmStatisticsCustomerReqVO 类哈
34   -
35 33 @GetMapping("/get-customer-area-summary")
36 34 @Operation(summary = "获取客户地区统计数据", description = "用于【城市分布分析】页面")
37 35 @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')")
38   - public CommonResult<List<CrmStatisticCustomerAreaRespVO>> getCustomerAreaSummary(@Valid CrmStatisticsCustomerReqVO reqVO) {
39   - return success(statisticsPortraitService.getCustomerAreaSummary(reqVO));
  36 + public CommonResult<List<CrmStatisticCustomerAreaRespVO>> getCustomerAreaSummary(@Valid CrmStatisticsPortraitReqVO reqVO) {
  37 + return success(statisticsPortraitService.getCustomerSummaryByArea(reqVO));
40 38 }
41 39  
42 40 @GetMapping("/get-customer-industry-summary")
43 41 @Operation(summary = "获取客户行业统计数据", description = "用于【客户行业分析】页面")
44 42 @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')")
45   - public CommonResult<List<CrmStatisticCustomerIndustryRespVO>> getCustomerIndustrySummary(@Valid CrmStatisticsCustomerReqVO reqVO) {
46   - return success(statisticsPortraitService.getCustomerIndustrySummary(reqVO));
  43 + public CommonResult<List<CrmStatisticCustomerIndustryRespVO>> getCustomerIndustrySummary(@Valid CrmStatisticsPortraitReqVO reqVO) {
  44 + return success(statisticsPortraitService.getCustomerSummaryByIndustry(reqVO));
47 45 }
48 46  
49 47 @GetMapping("/get-customer-level-summary")
50 48 @Operation(summary = "获取客户级别统计数据", description = "用于【客户级别分析】页面")
51 49 @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')")
52   - public CommonResult<List<CrmStatisticCustomerLevelRespVO>> getCustomerLevelSummary(@Valid CrmStatisticsCustomerReqVO reqVO) {
53   - return success(statisticsPortraitService.getCustomerLevelSummary(reqVO));
  50 + public CommonResult<List<CrmStatisticCustomerLevelRespVO>> getCustomerLevelSummary(@Valid CrmStatisticsPortraitReqVO reqVO) {
  51 + return success(statisticsPortraitService.getCustomerSummaryByLevel(reqVO));
54 52 }
55 53  
56 54 @GetMapping("/get-customer-source-summary")
57 55 @Operation(summary = "获取客户来源统计数据", description = "用于【客户来源分析】页面")
58 56 @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')")
59   - public CommonResult<List<CrmStatisticCustomerSourceRespVO>> getCustomerSourceSummary(@Valid CrmStatisticsCustomerReqVO reqVO) {
60   - return success(statisticsPortraitService.getCustomerSourceSummary(reqVO));
  57 + public CommonResult<List<CrmStatisticCustomerSourceRespVO>> getCustomerSourceSummary(@Valid CrmStatisticsPortraitReqVO reqVO) {
  58 + return success(statisticsPortraitService.getCustomerSummaryBySource(reqVO));
61 59 }
62 60  
63 61 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerAreaRespVO.java
... ... @@ -18,12 +18,4 @@ public class CrmStatisticCustomerAreaRespVO {
18 18 @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
19 19 private Integer dealCount;
20 20  
21   - // TODO @puhui999:下面两个的计算,交给前端。后端只返回数据即可。
22   -
23   - @Schema(description = "省份占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
24   - private Double areaPortion;
25   -
26   - @Schema(description = "成交占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
27   - private Double dealPortion;
28   -
29 21 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerIndustryRespVO.java
... ... @@ -9,9 +9,6 @@ public class CrmStatisticCustomerIndustryRespVO {
9 9  
10 10 @Schema(description = "客户行业ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
11 11 private Integer industryId;
12   - // TODO @puhui999:这个前端字典翻译哈
13   - @Schema(description = "客户行业名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
14   - private String industryName;
15 12  
16 13 @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
17 14 private Integer customerCount;
... ... @@ -19,12 +16,4 @@ public class CrmStatisticCustomerIndustryRespVO {
19 16 @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
20 17 private Integer dealCount;
21 18  
22   - // TODO @puhui999:下面两个的计算,交给前端。后端只返回数据即可。
23   -
24   - @Schema(description = "行业占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
25   - private Double industryPortion;
26   -
27   - @Schema(description = "成交占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
28   - private Double dealPortion;
29   -
30 19 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerLevelRespVO.java
... ... @@ -9,9 +9,6 @@ public class CrmStatisticCustomerLevelRespVO {
9 9  
10 10 @Schema(description = "客户级别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
11 11 private Integer level;
12   - // TODO @puhui999:这个前端字典翻译哈
13   - @Schema(description = "客户级别名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
14   - private String levelName;
15 12  
16 13 @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
17 14 private Integer customerCount;
... ... @@ -19,12 +16,4 @@ public class CrmStatisticCustomerLevelRespVO {
19 16 @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
20 17 private Integer dealCount;
21 18  
22   - // TODO @puhui999:下面两个的计算,交给前端。后端只返回数据即可。
23   -
24   - @Schema(description = "级别占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
25   - private Double levelPortion;
26   -
27   - @Schema(description = "成交占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
28   - private Double dealPortion;
29   -
30 19 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerSourceRespVO.java
... ... @@ -9,9 +9,6 @@ public class CrmStatisticCustomerSourceRespVO {
9 9  
10 10 @Schema(description = "客户来源编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
11 11 private Integer source;
12   - // TODO @puhui999:这个前端字典翻译哈
13   - @Schema(description = "客户来源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
14   - private String sourceName;
15 12  
16 13 @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
17 14 private Integer customerCount;
... ... @@ -19,12 +16,4 @@ public class CrmStatisticCustomerSourceRespVO {
19 16 @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
20 17 private Integer dealCount;
21 18  
22   - // TODO @puhui999:下面两个的计算,交给前端。后端只返回数据即可。
23   -
24   - @Schema(description = "来源占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
25   - private Double sourcePortion;
26   -
27   - @Schema(description = "成交占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
28   - private Double dealPortion;
29   -
30 19 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticsPortraitReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotNull;
  5 +import lombok.Data;
  6 +import org.springframework.format.annotation.DateTimeFormat;
  7 +
  8 +import java.time.LocalDateTime;
  9 +import java.util.List;
  10 +
  11 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  12 +
  13 +@Schema(description = "管理后台 - CRM 客户画像 Request VO")
  14 +@Data
  15 +public class CrmStatisticsPortraitReqVO {
  16 +
  17 + @Schema(description = "部门 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  18 + @NotNull(message = "部门 id 不能为空")
  19 + private Long deptId;
  20 +
  21 + /**
  22 + * 负责人用户 id, 当用户为空, 则计算部门下用户
  23 + */
  24 + @Schema(description = "负责人用户 id", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1")
  25 + private Long userId;
  26 +
  27 + /**
  28 + * userIds 目前不用前端传递,目前是方便后端通过 deptId 读取编号后,设置回来
  29 + * 后续,可能会支持选择部分用户进行查询
  30 + */
  31 + @Schema(description = "负责人用户 id 集合", hidden = true, example = "2")
  32 + private List<Long> userIds;
  33 +
  34 + /**
  35 + * 前端如果选择自定义时间, 那么前端传递起始-终止时间, 如果选择其他时间间隔类型, 则由后台计算起始-终止时间
  36 + * 并作为参数传递给Mapper
  37 + */
  38 + @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
  39 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  40 + private LocalDateTime[] times;
  41 +
  42 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPortraitMapper.java
1 1 package cn.iocoder.yudao.module.crm.dal.mysql.statistics;
2 2  
3   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
4   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerAreaRespVO;
5   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerIndustryRespVO;
6   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerLevelRespVO;
7   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerSourceRespVO;
  3 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.*;
8 4 import org.apache.ibatis.annotations.Mapper;
9 5  
10 6 import java.util.List;
... ... @@ -17,14 +13,12 @@ import java.util.List;
17 13 @Mapper
18 14 public interface CrmStatisticsPortraitMapper {
19 15  
20   - // TODO @puuhui999:GroupBy
  16 + List<CrmStatisticCustomerAreaRespVO> selectSummaryListGroupByAreaId(CrmStatisticsPortraitReqVO reqVO);
21 17  
22   - List<CrmStatisticCustomerIndustryRespVO> selectCustomerIndustryListGroupbyIndustryId(CrmStatisticsCustomerReqVO reqVO);
  18 + List<CrmStatisticCustomerIndustryRespVO> selectCustomerIndustryListGroupByIndustryId(CrmStatisticsPortraitReqVO reqVO);
23 19  
24   - List<CrmStatisticCustomerSourceRespVO> selectCustomerSourceListGroupbySource(CrmStatisticsCustomerReqVO reqVO);
  20 + List<CrmStatisticCustomerSourceRespVO> selectCustomerSourceListGroupBySource(CrmStatisticsPortraitReqVO reqVO);
25 21  
26   - List<CrmStatisticCustomerLevelRespVO> selectCustomerLevelListGroupbyLevel(CrmStatisticsCustomerReqVO reqVO);
27   -
28   - List<CrmStatisticCustomerAreaRespVO> selectSummaryListByAreaId(CrmStatisticsCustomerReqVO reqVO);
  22 + List<CrmStatisticCustomerLevelRespVO> selectCustomerLevelListGroupByLevel(CrmStatisticsPortraitReqVO reqVO);
29 23  
30 24 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPortraitService.java
1 1 package cn.iocoder.yudao.module.crm.service.statistics;
2 2  
3   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerReqVO;
4   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerAreaRespVO;
5   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerIndustryRespVO;
6   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerLevelRespVO;
7   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerSourceRespVO;
  3 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.*;
8 4  
9 5 import java.util.List;
10 6  
... ... @@ -21,7 +17,7 @@ public interface CrmStatisticsPortraitService {
21 17 * @param reqVO 请求参数
22 18 * @return 统计数据
23 19 */
24   - List<CrmStatisticCustomerAreaRespVO> getCustomerAreaSummary(CrmStatisticsCustomerReqVO reqVO);
  20 + List<CrmStatisticCustomerAreaRespVO> getCustomerSummaryByArea(CrmStatisticsPortraitReqVO reqVO);
25 21  
26 22 /**
27 23 * 获取客户行业统计数据
... ... @@ -29,7 +25,7 @@ public interface CrmStatisticsPortraitService {
29 25 * @param reqVO 请求参数
30 26 * @return 统计数据
31 27 */
32   - List<CrmStatisticCustomerIndustryRespVO> getCustomerIndustrySummary(CrmStatisticsCustomerReqVO reqVO);
  28 + List<CrmStatisticCustomerIndustryRespVO> getCustomerSummaryByIndustry(CrmStatisticsPortraitReqVO reqVO);
33 29  
34 30 /**
35 31 * 获取客户级别统计数据
... ... @@ -37,7 +33,7 @@ public interface CrmStatisticsPortraitService {
37 33 * @param reqVO 请求参数
38 34 * @return 统计数据
39 35 */
40   - List<CrmStatisticCustomerLevelRespVO> getCustomerLevelSummary(CrmStatisticsCustomerReqVO reqVO);
  36 + List<CrmStatisticCustomerLevelRespVO> getCustomerSummaryByLevel(CrmStatisticsPortraitReqVO reqVO);
41 37  
42 38 /**
43 39 * 获取客户来源统计数据
... ... @@ -45,6 +41,6 @@ public interface CrmStatisticsPortraitService {
45 41 * @param reqVO 请求参数
46 42 * @return 统计数据
47 43 */
48   - List<CrmStatisticCustomerSourceRespVO> getCustomerSourceSummary(CrmStatisticsCustomerReqVO reqVO);
  44 + List<CrmStatisticCustomerSourceRespVO> getCustomerSummaryBySource(CrmStatisticsPortraitReqVO reqVO);
49 45  
50 46 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPortraitServiceImpl.java
... ... @@ -5,15 +5,10 @@ import cn.hutool.core.util.ObjUtil;
5 5 import cn.iocoder.yudao.framework.ip.core.Area;
6 6 import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
7 7 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
8   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerReqVO;
9   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerAreaRespVO;
10   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerIndustryRespVO;
11   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerLevelRespVO;
12   -import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerSourceRespVO;
  8 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.*;
13 9 import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsPortraitMapper;
14 10 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
15 11 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
16   -import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
17 12 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
18 13 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
19 14 import jakarta.annotation.Resource;
... ... @@ -26,9 +21,7 @@ import java.util.Map;
26 21 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
27 22 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
28 23 import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
29   -import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.*;
30 24  
31   -// TODO @puhui999:参考 CrmStatisticsCustomerServiceImpl 代码风格,优化下这个类哈;包括命名、空行、注释等;
32 25 /**
33 26 * CRM 客户画像 Service 实现类
34 27 *
... ... @@ -44,64 +37,54 @@ public class CrmStatisticsPortraitServiceImpl implements CrmStatisticsPortraitSe
44 37 private AdminUserApi adminUserApi;
45 38 @Resource
46 39 private DeptApi deptApi;
47   - @Resource
48   - private DictDataApi dictDataApi;
49 40  
50 41 @Override
51   - public List<CrmStatisticCustomerAreaRespVO> getCustomerAreaSummary(CrmStatisticsCustomerReqVO reqVO) {
52   - // 1. 获得用户编号数组
  42 + public List<CrmStatisticCustomerAreaRespVO> getCustomerSummaryByArea(CrmStatisticsPortraitReqVO reqVO) {
  43 + // 1.1 获得用户编号数组
53 44 List<Long> userIds = getUserIds(reqVO);
54 45 if (CollUtil.isEmpty(userIds)) {
55 46 return Collections.emptyList();
56 47 }
57 48 reqVO.setUserIds(userIds);
58   - // 2. 获取客户地区统计数据
59   - List<CrmStatisticCustomerAreaRespVO> list = portraitMapper.selectSummaryListByAreaId(reqVO);
  49 + // 1.2 获取客户地区统计数据
  50 + List<CrmStatisticCustomerAreaRespVO> list = portraitMapper.selectSummaryListGroupByAreaId(reqVO);
60 51 if (CollUtil.isEmpty(list)) {
61 52 return Collections.emptyList();
62 53 }
63 54  
64   - // 拼接数据
  55 + // 2. 拼接数据
65 56 List<Area> areaList = AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area);
66 57 areaList.add(new Area().setId(null).setName("未知"));
67 58 Map<Integer, Area> areaMap = convertMap(areaList, Area::getId);
68   - List<CrmStatisticCustomerAreaRespVO> customerAreaRespVOList = convertList(list, item -> {
  59 + return convertList(list, item -> {
69 60 Integer parentId = AreaUtils.getParentIdByType(item.getAreaId(), AreaTypeEnum.PROVINCE);
70   - // TODO @puhui999:找不到,可以归到未知哈;
71   - if (parentId == null) {
72   - return item;
  61 + if (parentId == null) { // 找不到,归到未知
  62 + return item.setAreaId(null).setAreaName("未知");
73 63 }
74 64 findAndThen(areaMap, parentId, area -> item.setAreaId(parentId).setAreaName(area.getName()));
75 65 return item;
76 66 });
77   - return customerAreaRespVOList;
78 67 }
79 68  
80 69 @Override
81   - public List<CrmStatisticCustomerIndustryRespVO> getCustomerIndustrySummary(CrmStatisticsCustomerReqVO reqVO) {
  70 + public List<CrmStatisticCustomerIndustryRespVO> getCustomerSummaryByIndustry(CrmStatisticsPortraitReqVO reqVO) {
82 71 // 1. 获得用户编号数组
83 72 List<Long> userIds = getUserIds(reqVO);
84 73 if (CollUtil.isEmpty(userIds)) {
85 74 return Collections.emptyList();
86 75 }
87 76 reqVO.setUserIds(userIds);
  77 +
88 78 // 2. 获取客户行业统计数据
89   - List<CrmStatisticCustomerIndustryRespVO> industryRespVOList = portraitMapper.selectCustomerIndustryListGroupbyIndustryId(reqVO);
  79 + List<CrmStatisticCustomerIndustryRespVO> industryRespVOList = portraitMapper.selectCustomerIndustryListGroupByIndustryId(reqVO);
90 80 if (CollUtil.isEmpty(industryRespVOList)) {
91 81 return Collections.emptyList();
92 82 }
93   -
94   - return convertList(industryRespVOList, item -> {
95   - if (ObjUtil.isNull(item.getIndustryId())) {
96   - return item;
97   - }
98   - item.setIndustryName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, item.getIndustryId()));
99   - return item;
100   - });
  83 + return industryRespVOList;
101 84 }
102 85  
103 86 @Override
104   - public List<CrmStatisticCustomerSourceRespVO> getCustomerSourceSummary(CrmStatisticsCustomerReqVO reqVO) {
  87 + public List<CrmStatisticCustomerSourceRespVO> getCustomerSummaryBySource(CrmStatisticsPortraitReqVO reqVO) {
105 88 // 1. 获得用户编号数组
106 89 List<Long> userIds = getUserIds(reqVO);
107 90 if (CollUtil.isEmpty(userIds)) {
... ... @@ -110,41 +93,28 @@ public class CrmStatisticsPortraitServiceImpl implements CrmStatisticsPortraitSe
110 93 reqVO.setUserIds(userIds);
111 94  
112 95 // 2. 获取客户行业统计数据
113   - List<CrmStatisticCustomerSourceRespVO> sourceRespVOList = portraitMapper.selectCustomerSourceListGroupbySource(reqVO);
  96 + List<CrmStatisticCustomerSourceRespVO> sourceRespVOList = portraitMapper.selectCustomerSourceListGroupBySource(reqVO);
114 97 if (CollUtil.isEmpty(sourceRespVOList)) {
115 98 return Collections.emptyList();
116 99 }
117   -
118   - return convertList(sourceRespVOList, item -> {
119   - if (ObjUtil.isNull(item.getSource())) {
120   - return item;
121   - }
122   - item.setSourceName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_SOURCE, item.getSource()));
123   - return item;
124   - });
  100 + return sourceRespVOList;
125 101 }
126 102  
127 103 @Override
128   - public List<CrmStatisticCustomerLevelRespVO> getCustomerLevelSummary(CrmStatisticsCustomerReqVO reqVO) {
  104 + public List<CrmStatisticCustomerLevelRespVO> getCustomerSummaryByLevel(CrmStatisticsPortraitReqVO reqVO) {
129 105 // 1. 获得用户编号数组
130 106 List<Long> userIds = getUserIds(reqVO);
131 107 if (CollUtil.isEmpty(userIds)) {
132 108 return Collections.emptyList();
133 109 }
134 110 reqVO.setUserIds(userIds);
135   - // 2. 获取客户行业统计数据
136   - List<CrmStatisticCustomerLevelRespVO> levelRespVOList = portraitMapper.selectCustomerLevelListGroupbyLevel(reqVO);
  111 +
  112 + // 2. 获取客户级别统计数据
  113 + List<CrmStatisticCustomerLevelRespVO> levelRespVOList = portraitMapper.selectCustomerLevelListGroupByLevel(reqVO);
137 114 if (CollUtil.isEmpty(levelRespVOList)) {
138 115 return Collections.emptyList();
139 116 }
140   -
141   - return convertList(levelRespVOList, item -> {
142   - if (ObjUtil.isNull(item.getLevel())) {
143   - return item;
144   - }
145   - item.setLevelName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_LEVEL, item.getLevel()));
146   - return item;
147   - });
  117 + return levelRespVOList;
148 118 }
149 119  
150 120 /**
... ... @@ -153,7 +123,7 @@ public class CrmStatisticsPortraitServiceImpl implements CrmStatisticsPortraitSe
153 123 * @param reqVO 请求参数
154 124 * @return 用户编号数组
155 125 */
156   - private List<Long> getUserIds(CrmStatisticsCustomerReqVO reqVO) {
  126 + private List<Long> getUserIds(CrmStatisticsPortraitReqVO reqVO) {
157 127 // 情况一:选中某个用户
158 128 if (ObjUtil.isNotNull(reqVO.getUserId())) {
159 129 return List.of(reqVO.getUserId());
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPortraitMapper.xml
... ... @@ -2,91 +2,60 @@
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.CrmStatisticsPortraitMapper">
4 4  
5   - <!-- TODO @puhui999:参考 CrmStatisticsCustomerMapper.xml 优化下 SQL 的排版;sql 结尾不用 ; ;XML 之间有空行; -->
6   -
7   - <select id="selectCustomerIndustryListGroupbyIndustryId"
8   - resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerIndustryRespVO">
9   - SELECT
10   - industry_id,
11   - COUNT(*) AS customerCount,
12   - SUM(deal_status) AS dealCount,
13   - ROUND(COUNT(*) / (SELECT COUNT(*) FROM crm_customer WHERE deleted = 0) * 100, 2) AS industryPortion,
14   - ROUND(SUM(deal_status) / NULLIF(COUNT(*), 0) * 100, 2) AS dealPortion
15   - FROM
16   - crm_customer
17   - WHERE
18   - deleted = 0 AND industry_id IS NOT NULL
  5 + <select id="selectSummaryListGroupByAreaId"
  6 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerAreaRespVO">
  7 + SELECT area_id, COUNT(*) AS customerCount, SUM(deal_status) AS dealCount
  8 + FROM crm_customer
  9 + WHERE deleted = 0 AND area_id IS NOT NULL
19 10 AND owner_user_id IN
20 11 <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
21 12 #{userId}
22 13 </foreach>
23   - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
24   - #{times[1],javaType=java.time.LocalDateTime}
25   - GROUP BY
26   - industry_id;
  14 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime}
  15 + AND #{times[1],javaType=java.time.LocalDateTime}
  16 + GROUP BY area_id
27 17 </select>
28   - <select id="selectCustomerSourceListGroupbySource"
29   - resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerSourceRespVO">
30   - SELECT
31   - source,
32   - COUNT(*) AS customerCount,
33   - SUM(deal_status) AS dealCount,
34   - ROUND(COUNT(*) / (SELECT COUNT(*) FROM crm_customer WHERE deleted = 0) * 100, 2) AS sourcePortion,
35   - ROUND(SUM(deal_status) / NULLIF(COUNT(*), 0) * 100, 2) AS dealPortion
36   - FROM
37   - crm_customer
38   - WHERE
39   - deleted = 0 AND source IS NOT NULL
  18 +
  19 + <select id="selectCustomerIndustryListGroupByIndustryId"
  20 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerIndustryRespVO">
  21 + SELECT industry_id, COUNT(*) AS customerCount, SUM(deal_status) AS dealCount
  22 + FROM crm_customer
  23 + WHERE deleted = 0 AND industry_id IS NOT NULL
40 24 AND owner_user_id IN
41 25 <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
42 26 #{userId}
43 27 </foreach>
44   - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
45   - #{times[1],javaType=java.time.LocalDateTime}
46   - GROUP BY
47   - source;
  28 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime}
  29 + AND #{times[1],javaType=java.time.LocalDateTime}
  30 + GROUP BY industry_id
48 31 </select>
49   - <select id="selectCustomerLevelListGroupbyLevel"
50   - resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerLevelRespVO">
51   - SELECT
52   - level,
53   - COUNT(*) AS customerCount,
54   - SUM(deal_status) AS dealCount,
55   - ROUND(COUNT(*) / (SELECT COUNT(*) FROM crm_customer WHERE deleted = 0) * 100, 2) AS levelPortion,
56   - ROUND(SUM(deal_status) / NULLIF(COUNT(*), 0) * 100, 2) AS dealPortion
57   - FROM
58   - crm_customer
59   - WHERE
60   - deleted = 0 AND level IS NOT NULL
  32 +
  33 + <select id="selectCustomerSourceListGroupBySource"
  34 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerSourceRespVO">
  35 + SELECT source, COUNT(*) AS customerCount, SUM(deal_status) AS dealCount
  36 + FROM crm_customer
  37 + WHERE deleted = 0 AND source IS NOT NULL
61 38 AND owner_user_id IN
62 39 <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
63 40 #{userId}
64 41 </foreach>
65   - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
66   - #{times[1],javaType=java.time.LocalDateTime}
67   - GROUP BY
68   - level;
  42 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime}
  43 + AND #{times[1],javaType=java.time.LocalDateTime}
  44 + GROUP BY source
69 45 </select>
70   - <select id="selectSummaryListByAreaId"
71   - resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerAreaRespVO">
72   - SELECT
73   - area_id,
74   - COUNT(*) AS customerCount,
75   - SUM(deal_status) AS dealCount,
76   - ROUND(COUNT(*) / (SELECT COUNT(*) FROM crm_customer WHERE deleted = 0) * 100, 2) AS areaPortion,
77   - ROUND(SUM(deal_status) / NULLIF(COUNT(*), 0) * 100, 2) AS dealPortion
78   - FROM
79   - crm_customer
80   - WHERE
81   - deleted = 0 AND area_id IS NOT NULL
  46 +
  47 + <select id="selectCustomerLevelListGroupByLevel"
  48 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerLevelRespVO">
  49 + SELECT level, COUNT(*) AS customerCount, SUM(deal_status) AS dealCount
  50 + FROM crm_customer
  51 + WHERE deleted = 0 AND level IS NOT NULL
82 52 AND owner_user_id IN
83 53 <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
84 54 #{userId}
85 55 </foreach>
86   - AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
87   - #{times[1],javaType=java.time.LocalDateTime}
88   - GROUP BY
89   - area_id;
  56 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime}
  57 + AND #{times[1],javaType=java.time.LocalDateTime}
  58 + GROUP BY level
90 59 </select>
91 60  
92 61 </mapper>
... ...