Commit 3f5724e97803557d54a746ee26f4cc6cbf78e3d2

Authored by YunaiV
1 parent 924580f4

CRM:code review【客户画像】的实现

yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsPortraitController.java
... ... @@ -30,32 +30,34 @@ public class CrmStatisticsPortraitController {
30 30 @Resource
31 31 private CrmStatisticsPortraitService statisticsPortraitService;
32 32  
  33 + // TODO @puhui999:搞个属于自己的 CrmStatisticsCustomerReqVO 类哈
  34 +
33 35 @GetMapping("/get-customer-area-summary")
34 36 @Operation(summary = "获取客户地区统计数据", description = "用于【城市分布分析】页面")
35 37 @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')")
36 38 public CommonResult<List<CrmStatisticCustomerAreaRespVO>> getCustomerAreaSummary(@Valid CrmStatisticsCustomerReqVO reqVO) {
37   - return success(statisticsPortraitService.getCustomerArea(reqVO));
  39 + return success(statisticsPortraitService.getCustomerAreaSummary(reqVO));
38 40 }
39 41  
40 42 @GetMapping("/get-customer-industry-summary")
41   - @Operation(summary = "获取客户行业统计数据")
  43 + @Operation(summary = "获取客户行业统计数据", description = "用于【客户行业分析】页面")
42 44 @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')")
43   - public CommonResult<List<CrmStatisticCustomerIndustryRespVO>> getCustomerIndustry(@Valid CrmStatisticsCustomerReqVO reqVO) {
44   - return success(statisticsPortraitService.getCustomerIndustry(reqVO));
  45 + public CommonResult<List<CrmStatisticCustomerIndustryRespVO>> getCustomerIndustrySummary(@Valid CrmStatisticsCustomerReqVO reqVO) {
  46 + return success(statisticsPortraitService.getCustomerIndustrySummary(reqVO));
45 47 }
46 48  
47 49 @GetMapping("/get-customer-level-summary")
48   - @Operation(summary = "获取客户级别统计数据")
  50 + @Operation(summary = "获取客户级别统计数据", description = "用于【客户级别分析】页面")
49 51 @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')")
50   - public CommonResult<List<CrmStatisticCustomerLevelRespVO>> getCustomerLevel(@Valid CrmStatisticsCustomerReqVO reqVO) {
51   - return success(statisticsPortraitService.getCustomerLevel(reqVO));
  52 + public CommonResult<List<CrmStatisticCustomerLevelRespVO>> getCustomerLevelSummary(@Valid CrmStatisticsCustomerReqVO reqVO) {
  53 + return success(statisticsPortraitService.getCustomerLevelSummary(reqVO));
52 54 }
53 55  
54 56 @GetMapping("/get-customer-source-summary")
55   - @Operation(summary = "获取客户来源统计数据")
  57 + @Operation(summary = "获取客户来源统计数据", description = "用于【客户来源分析】页面")
56 58 @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')")
57   - public CommonResult<List<CrmStatisticCustomerSourceRespVO>> getCustomerSource(@Valid CrmStatisticsCustomerReqVO reqVO) {
58   - return success(statisticsPortraitService.getCustomerSource(reqVO));
  59 + public CommonResult<List<CrmStatisticCustomerSourceRespVO>> getCustomerSourceSummary(@Valid CrmStatisticsCustomerReqVO reqVO) {
  60 + return success(statisticsPortraitService.getCustomerSourceSummary(reqVO));
59 61 }
60 62  
61 63 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerAreaRespVO.java
... ... @@ -18,6 +18,8 @@ public class CrmStatisticCustomerAreaRespVO {
18 18 @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
19 19 private Integer dealCount;
20 20  
  21 + // TODO @puhui999:下面两个的计算,交给前端。后端只返回数据即可。
  22 +
21 23 @Schema(description = "省份占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
22 24 private Double areaPortion;
23 25  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerIndustryRespVO.java
... ... @@ -9,6 +9,7 @@ public class CrmStatisticCustomerIndustryRespVO {
9 9  
10 10 @Schema(description = "客户行业ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
11 11 private Integer industryId;
  12 + // TODO @puhui999:这个前端字典翻译哈
12 13 @Schema(description = "客户行业名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
13 14 private String industryName;
14 15  
... ... @@ -18,6 +19,8 @@ public class CrmStatisticCustomerIndustryRespVO {
18 19 @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
19 20 private Integer dealCount;
20 21  
  22 + // TODO @puhui999:下面两个的计算,交给前端。后端只返回数据即可。
  23 +
21 24 @Schema(description = "行业占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
22 25 private Double industryPortion;
23 26  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerLevelRespVO.java
... ... @@ -7,8 +7,9 @@ import lombok.Data;
7 7 @Data
8 8 public class CrmStatisticCustomerLevelRespVO {
9 9  
10   - @Schema(description = "客户级别ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  10 + @Schema(description = "客户级别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
11 11 private Integer level;
  12 + // TODO @puhui999:这个前端字典翻译哈
12 13 @Schema(description = "客户级别名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
13 14 private String levelName;
14 15  
... ... @@ -18,6 +19,8 @@ public class CrmStatisticCustomerLevelRespVO {
18 19 @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
19 20 private Integer dealCount;
20 21  
  22 + // TODO @puhui999:下面两个的计算,交给前端。后端只返回数据即可。
  23 +
21 24 @Schema(description = "级别占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
22 25 private Double levelPortion;
23 26  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerSourceRespVO.java
... ... @@ -7,8 +7,9 @@ import lombok.Data;
7 7 @Data
8 8 public class CrmStatisticCustomerSourceRespVO {
9 9  
10   - @Schema(description = "客户来源ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  10 + @Schema(description = "客户来源编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
11 11 private Integer source;
  12 + // TODO @puhui999:这个前端字典翻译哈
12 13 @Schema(description = "客户来源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
13 14 private String sourceName;
14 15  
... ... @@ -18,6 +19,8 @@ public class CrmStatisticCustomerSourceRespVO {
18 19 @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
19 20 private Integer dealCount;
20 21  
  22 + // TODO @puhui999:下面两个的计算,交给前端。后端只返回数据即可。
  23 +
21 24 @Schema(description = "来源占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
22 25 private Double sourcePortion;
23 26  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPortraitMapper.java
... ... @@ -12,11 +12,13 @@ import java.util.List;
12 12 /**
13 13 * CRM 数据画像 Mapper
14 14 *
15   - * @author dhb52
  15 + * @author HUIHUI
16 16 */
17 17 @Mapper
18 18 public interface CrmStatisticsPortraitMapper {
19 19  
  20 + // TODO @puuhui999:GroupBy
  21 +
20 22 List<CrmStatisticCustomerIndustryRespVO> selectCustomerIndustryListGroupbyIndustryId(CrmStatisticsCustomerReqVO reqVO);
21 23  
22 24 List<CrmStatisticCustomerSourceRespVO> selectCustomerSourceListGroupbySource(CrmStatisticsCustomerReqVO reqVO);
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPortraitService.java
... ... @@ -21,7 +21,7 @@ public interface CrmStatisticsPortraitService {
21 21 * @param reqVO 请求参数
22 22 * @return 统计数据
23 23 */
24   - List<CrmStatisticCustomerAreaRespVO> getCustomerArea(CrmStatisticsCustomerReqVO reqVO);
  24 + List<CrmStatisticCustomerAreaRespVO> getCustomerAreaSummary(CrmStatisticsCustomerReqVO reqVO);
25 25  
26 26 /**
27 27 * 获取客户行业统计数据
... ... @@ -29,7 +29,7 @@ public interface CrmStatisticsPortraitService {
29 29 * @param reqVO 请求参数
30 30 * @return 统计数据
31 31 */
32   - List<CrmStatisticCustomerIndustryRespVO> getCustomerIndustry(CrmStatisticsCustomerReqVO reqVO);
  32 + List<CrmStatisticCustomerIndustryRespVO> getCustomerIndustrySummary(CrmStatisticsCustomerReqVO reqVO);
33 33  
34 34 /**
35 35 * 获取客户级别统计数据
... ... @@ -37,7 +37,7 @@ public interface CrmStatisticsPortraitService {
37 37 * @param reqVO 请求参数
38 38 * @return 统计数据
39 39 */
40   - List<CrmStatisticCustomerLevelRespVO> getCustomerLevel(CrmStatisticsCustomerReqVO reqVO);
  40 + List<CrmStatisticCustomerLevelRespVO> getCustomerLevelSummary(CrmStatisticsCustomerReqVO reqVO);
41 41  
42 42 /**
43 43 * 获取客户来源统计数据
... ... @@ -45,6 +45,6 @@ public interface CrmStatisticsPortraitService {
45 45 * @param reqVO 请求参数
46 46 * @return 统计数据
47 47 */
48   - List<CrmStatisticCustomerSourceRespVO> getCustomerSource(CrmStatisticsCustomerReqVO reqVO);
  48 + List<CrmStatisticCustomerSourceRespVO> getCustomerSourceSummary(CrmStatisticsCustomerReqVO reqVO);
49 49  
50 50 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPortraitServiceImpl.java
... ... @@ -28,6 +28,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
28 28 import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
29 29 import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.*;
30 30  
  31 +// TODO @puhui999:参考 CrmStatisticsCustomerServiceImpl 代码风格,优化下这个类哈;包括命名、空行、注释等;
31 32 /**
32 33 * CRM 客户画像 Service 实现类
33 34 *
... ... @@ -47,30 +48,37 @@ public class CrmStatisticsPortraitServiceImpl implements CrmStatisticsPortraitSe
47 48 private DictDataApi dictDataApi;
48 49  
49 50 @Override
50   - public List<CrmStatisticCustomerIndustryRespVO> getCustomerIndustry(CrmStatisticsCustomerReqVO reqVO) {
  51 + public List<CrmStatisticCustomerAreaRespVO> getCustomerAreaSummary(CrmStatisticsCustomerReqVO reqVO) {
51 52 // 1. 获得用户编号数组
52 53 List<Long> userIds = getUserIds(reqVO);
53 54 if (CollUtil.isEmpty(userIds)) {
54 55 return Collections.emptyList();
55 56 }
56 57 reqVO.setUserIds(userIds);
57   - // 2. 获取客户行业统计数据
58   - List<CrmStatisticCustomerIndustryRespVO> industryRespVOList = portraitMapper.selectCustomerIndustryListGroupbyIndustryId(reqVO);
59   - if (CollUtil.isEmpty(industryRespVOList)) {
  58 + // 2. 获取客户地区统计数据
  59 + List<CrmStatisticCustomerAreaRespVO> list = portraitMapper.selectSummaryListByAreaId(reqVO);
  60 + if (CollUtil.isEmpty(list)) {
60 61 return Collections.emptyList();
61 62 }
62 63  
63   - return convertList(industryRespVOList, item -> {
64   - if (ObjUtil.isNull(item.getIndustryId())) {
  64 + // 拼接数据
  65 + List<Area> areaList = AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area);
  66 + areaList.add(new Area().setId(null).setName("未知"));
  67 + Map<Integer, Area> areaMap = convertMap(areaList, Area::getId);
  68 + List<CrmStatisticCustomerAreaRespVO> customerAreaRespVOList = convertList(list, item -> {
  69 + Integer parentId = AreaUtils.getParentIdByType(item.getAreaId(), AreaTypeEnum.PROVINCE);
  70 + // TODO @puhui999:找不到,可以归到未知哈;
  71 + if (parentId == null) {
65 72 return item;
66 73 }
67   - item.setIndustryName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, item.getIndustryId()));
  74 + findAndThen(areaMap, parentId, area -> item.setAreaId(parentId).setAreaName(area.getName()));
68 75 return item;
69 76 });
  77 + return customerAreaRespVOList;
70 78 }
71 79  
72 80 @Override
73   - public List<CrmStatisticCustomerSourceRespVO> getCustomerSource(CrmStatisticsCustomerReqVO reqVO) {
  81 + public List<CrmStatisticCustomerIndustryRespVO> getCustomerIndustrySummary(CrmStatisticsCustomerReqVO reqVO) {
74 82 // 1. 获得用户编号数组
75 83 List<Long> userIds = getUserIds(reqVO);
76 84 if (CollUtil.isEmpty(userIds)) {
... ... @@ -78,70 +86,65 @@ public class CrmStatisticsPortraitServiceImpl implements CrmStatisticsPortraitSe
78 86 }
79 87 reqVO.setUserIds(userIds);
80 88 // 2. 获取客户行业统计数据
81   - List<CrmStatisticCustomerSourceRespVO> sourceRespVOList = portraitMapper.selectCustomerSourceListGroupbySource(reqVO);
82   - if (CollUtil.isEmpty(sourceRespVOList)) {
  89 + List<CrmStatisticCustomerIndustryRespVO> industryRespVOList = portraitMapper.selectCustomerIndustryListGroupbyIndustryId(reqVO);
  90 + if (CollUtil.isEmpty(industryRespVOList)) {
83 91 return Collections.emptyList();
84 92 }
85 93  
86   - return convertList(sourceRespVOList, item -> {
87   - if (ObjUtil.isNull(item.getSource())) {
  94 + return convertList(industryRespVOList, item -> {
  95 + if (ObjUtil.isNull(item.getIndustryId())) {
88 96 return item;
89 97 }
90   - item.setSourceName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_SOURCE, item.getSource()));
  98 + item.setIndustryName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, item.getIndustryId()));
91 99 return item;
92 100 });
93 101 }
94 102  
95 103 @Override
96   - public List<CrmStatisticCustomerLevelRespVO> getCustomerLevel(CrmStatisticsCustomerReqVO reqVO) {
  104 + public List<CrmStatisticCustomerSourceRespVO> getCustomerSourceSummary(CrmStatisticsCustomerReqVO reqVO) {
97 105 // 1. 获得用户编号数组
98 106 List<Long> userIds = getUserIds(reqVO);
99 107 if (CollUtil.isEmpty(userIds)) {
100 108 return Collections.emptyList();
101 109 }
102 110 reqVO.setUserIds(userIds);
  111 +
103 112 // 2. 获取客户行业统计数据
104   - List<CrmStatisticCustomerLevelRespVO> levelRespVOList = portraitMapper.selectCustomerLevelListGroupbyLevel(reqVO);
105   - if (CollUtil.isEmpty(levelRespVOList)) {
  113 + List<CrmStatisticCustomerSourceRespVO> sourceRespVOList = portraitMapper.selectCustomerSourceListGroupbySource(reqVO);
  114 + if (CollUtil.isEmpty(sourceRespVOList)) {
106 115 return Collections.emptyList();
107 116 }
108 117  
109   - return convertList(levelRespVOList, item -> {
110   - if (ObjUtil.isNull(item.getLevel())) {
  118 + return convertList(sourceRespVOList, item -> {
  119 + if (ObjUtil.isNull(item.getSource())) {
111 120 return item;
112 121 }
113   - item.setLevelName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_LEVEL, item.getLevel()));
  122 + item.setSourceName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_SOURCE, item.getSource()));
114 123 return item;
115 124 });
116 125 }
117 126  
118 127 @Override
119   - public List<CrmStatisticCustomerAreaRespVO> getCustomerArea(CrmStatisticsCustomerReqVO reqVO) {
  128 + public List<CrmStatisticCustomerLevelRespVO> getCustomerLevelSummary(CrmStatisticsCustomerReqVO reqVO) {
120 129 // 1. 获得用户编号数组
121 130 List<Long> userIds = getUserIds(reqVO);
122 131 if (CollUtil.isEmpty(userIds)) {
123 132 return Collections.emptyList();
124 133 }
125 134 reqVO.setUserIds(userIds);
126   - // 2. 获取客户地区统计数据
127   - List<CrmStatisticCustomerAreaRespVO> list = portraitMapper.selectSummaryListByAreaId(reqVO);
128   - if (CollUtil.isEmpty(list)) {
  135 + // 2. 获取客户行业统计数据
  136 + List<CrmStatisticCustomerLevelRespVO> levelRespVOList = portraitMapper.selectCustomerLevelListGroupbyLevel(reqVO);
  137 + if (CollUtil.isEmpty(levelRespVOList)) {
129 138 return Collections.emptyList();
130 139 }
131 140  
132   - // 拼接数据
133   - List<Area> areaList = AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area);
134   - areaList.add(new Area().setId(null).setName("未知"));
135   - Map<Integer, Area> areaMap = convertMap(areaList, Area::getId);
136   - List<CrmStatisticCustomerAreaRespVO> customerAreaRespVOList = convertList(list, item -> {
137   - Integer parentId = AreaUtils.getParentIdByType(item.getAreaId(), AreaTypeEnum.PROVINCE);
138   - if (parentId == null) {
  141 + return convertList(levelRespVOList, item -> {
  142 + if (ObjUtil.isNull(item.getLevel())) {
139 143 return item;
140 144 }
141   - findAndThen(areaMap, parentId, area -> item.setAreaId(parentId).setAreaName(area.getName()));
  145 + item.setLevelName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_LEVEL, item.getLevel()));
142 146 return item;
143 147 });
144   - return customerAreaRespVOList;
145 148 }
146 149  
147 150 /**
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPortraitMapper.xml
... ... @@ -2,6 +2,8 @@
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 +
5 7 <select id="selectCustomerIndustryListGroupbyIndustryId"
6 8 resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerIndustryRespVO">
7 9 SELECT
... ...