Commit ce013a2562883f22884ce267ac8f980dd86c73d4

Authored by puhui999
1 parent 0dd36f6c

CRM: 新增客户行业、来源、级别统计数据统计

yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.java
... ... @@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.crm.controller.admin.statistics;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerIndustryRespVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerLevelRespVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerSourceRespVO;
5 8 import cn.iocoder.yudao.module.crm.service.statistics.CrmStatisticsCustomerService;
6 9 import io.swagger.v3.oas.annotations.Operation;
7 10 import io.swagger.v3.oas.annotations.tags.Tag;
... ... @@ -82,4 +85,25 @@ public class CrmStatisticsCustomerController {
82 85 return success(customerService.getCustomerDealCycleByUser(reqVO));
83 86 }
84 87  
  88 + @GetMapping("/get-customer-industry-summary")
  89 + @Operation(summary = "获取客户行业统计数据")
  90 + @PreAuthorize("@ss.hasPermission('crm:statistics-customer:query')")
  91 + public CommonResult<List<CrmStatisticCustomerIndustryRespVO>> getCustomerIndustry(@Valid CrmStatisticsCustomerReqVO reqVO) {
  92 + return success(customerService.getCustomerIndustry(reqVO));
  93 + }
  94 +
  95 + @GetMapping("/get-customer-source-summary")
  96 + @Operation(summary = "获取客户来源统计数据")
  97 + @PreAuthorize("@ss.hasPermission('crm:statistics-customer:query')")
  98 + public CommonResult<List<CrmStatisticCustomerSourceRespVO>> getCustomerSource(@Valid CrmStatisticsCustomerReqVO reqVO) {
  99 + return success(customerService.getCustomerSource(reqVO));
  100 + }
  101 +
  102 + @GetMapping("/get-customer-level-summary")
  103 + @Operation(summary = "获取客户级别统计数据")
  104 + @PreAuthorize("@ss.hasPermission('crm:statistics-customer:query')")
  105 + public CommonResult<List<CrmStatisticCustomerLevelRespVO>> getCustomerLevel(@Valid CrmStatisticsCustomerReqVO reqVO) {
  106 + return success(customerService.getCustomerLevel(reqVO));
  107 + }
  108 +
85 109 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/analyze/CrmStatisticCustomerIndustryRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "管理后台 - CRM 客户行业分析 VO")
  7 +@Data
  8 +public class CrmStatisticCustomerIndustryRespVO {
  9 +
  10 + @Schema(description = "客户行业ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  11 + private Integer industryId;
  12 + @Schema(description = "客户行业名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  13 + private String industryName;
  14 +
  15 + @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  16 + private Integer customerCount;
  17 +
  18 + @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + private Integer dealCount;
  20 +
  21 + @Schema(description = "行业占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  22 + private Double industryPortion;
  23 +
  24 + @Schema(description = "成交占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  25 + private Double dealPortion;
  26 +
  27 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/analyze/CrmStatisticCustomerLevelRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "管理后台 - CRM 客户级别分析 VO")
  7 +@Data
  8 +public class CrmStatisticCustomerLevelRespVO {
  9 +
  10 + @Schema(description = "客户级别ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  11 + private Integer level;
  12 + @Schema(description = "客户级别名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  13 + private String levelName;
  14 +
  15 + @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  16 + private Integer customerCount;
  17 +
  18 + @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + private Integer dealCount;
  20 +
  21 + @Schema(description = "级别占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  22 + private Double levelPortion;
  23 +
  24 + @Schema(description = "成交占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  25 + private Double dealPortion;
  26 +
  27 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/analyze/CrmStatisticCustomerSourceRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "管理后台 - CRM 客户来源分析 VO")
  7 +@Data
  8 +public class CrmStatisticCustomerSourceRespVO {
  9 +
  10 + @Schema(description = "客户来源ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  11 + private Integer source;
  12 + @Schema(description = "客户来源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  13 + private String sourceName;
  14 +
  15 + @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  16 + private Integer customerCount;
  17 +
  18 + @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + private Integer dealCount;
  20 +
  21 + @Schema(description = "来源占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  22 + private Double sourcePortion;
  23 +
  24 + @Schema(description = "成交占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  25 + private Double dealPortion;
  26 +
  27 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsCustomerMapper.java
1 1 package cn.iocoder.yudao.module.crm.dal.mysql.statistics;
2 2  
3 3 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerIndustryRespVO;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerLevelRespVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerSourceRespVO;
4 7 import org.apache.ibatis.annotations.Mapper;
5 8  
6 9 import java.util.List;
... ... @@ -42,4 +45,10 @@ public interface CrmStatisticsCustomerMapper {
42 45  
43 46 List<CrmStatisticsCustomerDealCycleByUserRespVO> selectCustomerDealCycleGroupbyUser(CrmStatisticsCustomerReqVO reqVO);
44 47  
  48 + List<CrmStatisticCustomerIndustryRespVO> selectCustomerIndustryListGroupbyIndustryId(CrmStatisticsCustomerReqVO reqVO);
  49 +
  50 + List<CrmStatisticCustomerSourceRespVO> selectCustomerSourceListGroupbySource(CrmStatisticsCustomerReqVO reqVO);
  51 +
  52 + List<CrmStatisticCustomerLevelRespVO> selectCustomerLevelListGroupbyLevel(CrmStatisticsCustomerReqVO reqVO);
  53 +
45 54 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerService.java
1 1 package cn.iocoder.yudao.module.crm.service.statistics;
2 2  
3 3 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerIndustryRespVO;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerLevelRespVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerSourceRespVO;
4 7  
5 8 import java.util.List;
6 9  
... ... @@ -77,4 +80,28 @@ public interface CrmStatisticsCustomerService {
77 80 */
78 81 List<CrmStatisticsCustomerDealCycleByUserRespVO> getCustomerDealCycleByUser(CrmStatisticsCustomerReqVO reqVO);
79 82  
  83 + /**
  84 + * 获取客户行业统计数据
  85 + *
  86 + * @param reqVO 请求参数
  87 + * @return 统计数据
  88 + */
  89 + List<CrmStatisticCustomerIndustryRespVO> getCustomerIndustry(CrmStatisticsCustomerReqVO reqVO);
  90 +
  91 + /**
  92 + * 获取客户来源统计数据
  93 + *
  94 + * @param reqVO 请求参数
  95 + * @return 统计数据
  96 + */
  97 + List<CrmStatisticCustomerSourceRespVO> getCustomerSource(CrmStatisticsCustomerReqVO reqVO);
  98 +
  99 + /**
  100 + * 获取客户级别统计数据
  101 + *
  102 + * @param reqVO 请求参数
  103 + * @return 统计数据
  104 + */
  105 + List<CrmStatisticCustomerLevelRespVO> getCustomerLevel(CrmStatisticsCustomerReqVO reqVO);
  106 +
80 107 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerServiceImpl.java
... ... @@ -6,6 +6,9 @@ import cn.hutool.core.util.ObjUtil;
6 6 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
7 7 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
8 8 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
  9 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerIndustryRespVO;
  10 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerLevelRespVO;
  11 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerSourceRespVO;
9 12 import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsCustomerMapper;
10 13 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
11 14 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
... ... @@ -78,15 +81,15 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
78 81 // TODO @dhb52:这个是不是要 add 到 respVoList 里?或者还可以 convertList(times, time -> new CrmStatisticsCustomerDealCycleByDateRespVO()...)
79 82 List<CrmStatisticsCustomerSummaryByDateRespVO> respVoList = new ArrayList<>(times.size());
80 83 final Map<String, Integer> customerCreateCountMap = convertMap(customerCreateCount,
81   - CrmStatisticsCustomerSummaryByDateRespVO::getTime,
82   - CrmStatisticsCustomerSummaryByDateRespVO::getCustomerCreateCount);
  84 + CrmStatisticsCustomerSummaryByDateRespVO::getTime,
  85 + CrmStatisticsCustomerSummaryByDateRespVO::getCustomerCreateCount);
83 86 final Map<String, Integer> customerDealCountMap = convertMap(customerDealCount,
84   - CrmStatisticsCustomerSummaryByDateRespVO::getTime,
85   - CrmStatisticsCustomerSummaryByDateRespVO::getCustomerDealCount);
  87 + CrmStatisticsCustomerSummaryByDateRespVO::getTime,
  88 + CrmStatisticsCustomerSummaryByDateRespVO::getCustomerDealCount);
86 89 times.forEach(time -> respVoList.add(
87   - new CrmStatisticsCustomerSummaryByDateRespVO().setTime(time)
88   - .setCustomerCreateCount(customerCreateCountMap.getOrDefault(time, 0))
89   - .setCustomerDealCount(customerDealCountMap.getOrDefault(time, 0))
  90 + new CrmStatisticsCustomerSummaryByDateRespVO().setTime(time)
  91 + .setCustomerCreateCount(customerCreateCountMap.getOrDefault(time, 0))
  92 + .setCustomerDealCount(customerDealCountMap.getOrDefault(time, 0))
90 93 ));
91 94 return respVoList;
92 95 }
... ... @@ -108,25 +111,25 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
108 111  
109 112 // 3. 合并统计数据
110 113 final Map<Long, Integer> customerCreateCountMap = convertMap(customerCreateCount,
111   - CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
112   - CrmStatisticsCustomerSummaryByUserRespVO::getCustomerCreateCount);
  114 + CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
  115 + CrmStatisticsCustomerSummaryByUserRespVO::getCustomerCreateCount);
113 116 final Map<Long, Integer> customerDealCountMap = convertMap(customerDealCount,
114   - CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
115   - CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount);
  117 + CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
  118 + CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount);
116 119 final Map<Long, BigDecimal> contractPriceMap = convertMap(contractPrice,
117   - CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
118   - CrmStatisticsCustomerSummaryByUserRespVO::getContractPrice);
  120 + CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
  121 + CrmStatisticsCustomerSummaryByUserRespVO::getContractPrice);
119 122 final Map<Long, BigDecimal> receivablePriceMap = convertMap(receivablePrice,
120   - CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
121   - CrmStatisticsCustomerSummaryByUserRespVO::getReceivablePrice);
  123 + CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
  124 + CrmStatisticsCustomerSummaryByUserRespVO::getReceivablePrice);
122 125 List<CrmStatisticsCustomerSummaryByUserRespVO> respVoList = new ArrayList<>(userIds.size());
123 126 userIds.forEach(userId -> {
124 127 final CrmStatisticsCustomerSummaryByUserRespVO vo = new CrmStatisticsCustomerSummaryByUserRespVO();
125 128 vo.setOwnerUserId(userId);
126 129 vo.setCustomerCreateCount(customerCreateCountMap.getOrDefault(userId, 0))
127   - .setCustomerDealCount(customerDealCountMap.getOrDefault(userId, 0))
128   - .setContractPrice(contractPriceMap.getOrDefault(userId, BigDecimal.ZERO))
129   - .setReceivablePrice(receivablePriceMap.getOrDefault(userId, BigDecimal.ZERO));
  130 + .setCustomerDealCount(customerDealCountMap.getOrDefault(userId, 0))
  131 + .setContractPrice(contractPriceMap.getOrDefault(userId, BigDecimal.ZERO))
  132 + .setReceivablePrice(receivablePriceMap.getOrDefault(userId, BigDecimal.ZERO));
130 133 respVoList.add(vo);
131 134 });
132 135  
... ... @@ -156,15 +159,15 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
156 159 // 4. 合并统计数据
157 160 List<CrmStatisticsFollowupSummaryByDateRespVO> respVoList = new ArrayList<>(times.size());
158 161 final Map<String, Integer> followupRecordCountMap = convertMap(followupRecordCount,
159   - CrmStatisticsFollowupSummaryByDateRespVO::getTime,
160   - CrmStatisticsFollowupSummaryByDateRespVO::getFollowupRecordCount);
  162 + CrmStatisticsFollowupSummaryByDateRespVO::getTime,
  163 + CrmStatisticsFollowupSummaryByDateRespVO::getFollowupRecordCount);
161 164 final Map<String, Integer> followupCustomerCountMap = convertMap(followupCustomerCount,
162   - CrmStatisticsFollowupSummaryByDateRespVO::getTime,
163   - CrmStatisticsFollowupSummaryByDateRespVO::getFollowupCustomerCount);
  165 + CrmStatisticsFollowupSummaryByDateRespVO::getTime,
  166 + CrmStatisticsFollowupSummaryByDateRespVO::getFollowupCustomerCount);
164 167 times.forEach(time -> respVoList.add(
165   - new CrmStatisticsFollowupSummaryByDateRespVO().setTime(time)
166   - .setFollowupRecordCount(followupRecordCountMap.getOrDefault(time, 0))
167   - .setFollowupCustomerCount(followupCustomerCountMap.getOrDefault(time, 0))
  168 + new CrmStatisticsFollowupSummaryByDateRespVO().setTime(time)
  169 + .setFollowupRecordCount(followupRecordCountMap.getOrDefault(time, 0))
  170 + .setFollowupCustomerCount(followupCustomerCountMap.getOrDefault(time, 0))
168 171 ));
169 172  
170 173 return respVoList;
... ... @@ -186,16 +189,16 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
186 189  
187 190 // 3. 合并统计数据
188 191 final Map<Long, Integer> followupRecordCountMap = convertMap(followupRecordCount,
189   - CrmStatisticsFollowupSummaryByUserRespVO::getOwnerUserId,
190   - CrmStatisticsFollowupSummaryByUserRespVO::getFollowupRecordCount);
  192 + CrmStatisticsFollowupSummaryByUserRespVO::getOwnerUserId,
  193 + CrmStatisticsFollowupSummaryByUserRespVO::getFollowupRecordCount);
191 194 final Map<Long, Integer> followupCustomerCountMap = convertMap(followupCustomerCount,
192   - CrmStatisticsFollowupSummaryByUserRespVO::getOwnerUserId,
193   - CrmStatisticsFollowupSummaryByUserRespVO::getFollowupCustomerCount);
  195 + CrmStatisticsFollowupSummaryByUserRespVO::getOwnerUserId,
  196 + CrmStatisticsFollowupSummaryByUserRespVO::getFollowupCustomerCount);
194 197 List<CrmStatisticsFollowupSummaryByUserRespVO> respVoList = new ArrayList<>(userIds.size());
195 198 userIds.forEach(userId -> {
196 199 final CrmStatisticsFollowupSummaryByUserRespVO vo = new CrmStatisticsFollowupSummaryByUserRespVO()
197   - .setFollowupRecordCount(followupRecordCountMap.getOrDefault(userId, 0))
198   - .setFollowupCustomerCount(followupCustomerCountMap.getOrDefault(userId, 0));
  200 + .setFollowupRecordCount(followupRecordCountMap.getOrDefault(userId, 0))
  201 + .setFollowupCustomerCount(followupCustomerCountMap.getOrDefault(userId, 0));
199 202 vo.setOwnerUserId(userId);
200 203 respVoList.add(vo);
201 204 });
... ... @@ -221,7 +224,7 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
221 224 // 3. 获取字典数据
222 225 List<DictDataRespDTO> followUpTypes = dictDataApi.getDictDataList(CRM_FOLLOW_UP_TYPE);
223 226 final Map<String, String> followUpTypeMap = convertMap(followUpTypes,
224   - DictDataRespDTO::getValue, DictDataRespDTO::getLabel);
  227 + DictDataRespDTO::getValue, DictDataRespDTO::getLabel);
225 228 respVoList.forEach(vo -> {
226 229 vo.setFollowupType(followUpTypeMap.get(vo.getFollowupType()));
227 230 });
... ... @@ -244,19 +247,19 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
244 247 // 3. 设置 创建人、负责人、行业、来源
245 248 // 获取客户所属行业
246 249 Map<String, String> industryMap = convertMap(dictDataApi.getDictDataList(CRM_CUSTOMER_INDUSTRY),
247   - DictDataRespDTO::getValue, DictDataRespDTO::getLabel);
  250 + DictDataRespDTO::getValue, DictDataRespDTO::getLabel);
248 251 // 获取客户来源
249 252 Map<String, String> sourceMap = convertMap(dictDataApi.getDictDataList(CRM_CUSTOMER_SOURCE),
250   - DictDataRespDTO::getValue, DictDataRespDTO::getLabel);
  253 + DictDataRespDTO::getValue, DictDataRespDTO::getLabel);
251 254 // 获取创建人、负责人列表
252 255 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(respVoList,
253   - vo -> Stream.of(NumberUtils.parseLong(vo.getCreatorUserId()), vo.getOwnerUserId())));
  256 + vo -> Stream.of(NumberUtils.parseLong(vo.getCreatorUserId()), vo.getOwnerUserId())));
254 257  
255 258 respVoList.forEach(vo -> {
256 259 MapUtils.findAndThen(industryMap, vo.getIndustryId(), vo::setIndustryName);
257 260 MapUtils.findAndThen(sourceMap, vo.getSource(), vo::setSourceName);
258 261 MapUtils.findAndThen(userMap, NumberUtils.parseLong(vo.getCreatorUserId()),
259   - user -> vo.setCreatorUserName(user.getNickname()));
  262 + user -> vo.setCreatorUserName(user.getNickname()));
260 263 MapUtils.findAndThen(userMap, vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname()));
261 264 });
262 265  
... ... @@ -283,11 +286,11 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
283 286 // 4. 合并统计数据
284 287 List<CrmStatisticsCustomerDealCycleByDateRespVO> respVoList = new ArrayList<>(times.size());
285 288 final Map<String, Double> customerDealCycleMap = convertMap(customerDealCycle,
286   - CrmStatisticsCustomerDealCycleByDateRespVO::getTime,
287   - CrmStatisticsCustomerDealCycleByDateRespVO::getCustomerDealCycle);
  289 + CrmStatisticsCustomerDealCycleByDateRespVO::getTime,
  290 + CrmStatisticsCustomerDealCycleByDateRespVO::getCustomerDealCycle);
288 291 times.forEach(time -> respVoList.add(
289   - new CrmStatisticsCustomerDealCycleByDateRespVO().setTime(time)
290   - .setCustomerDealCycle(customerDealCycleMap.getOrDefault(time, 0D))
  292 + new CrmStatisticsCustomerDealCycleByDateRespVO().setTime(time)
  293 + .setCustomerDealCycle(customerDealCycleMap.getOrDefault(time, 0D))
291 294 ));
292 295 return respVoList;
293 296 }
... ... @@ -308,16 +311,16 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
308 311  
309 312 // 3. 合并统计数据
310 313 final Map<Long, Double> customerDealCycleMap = convertMap(customerDealCycle,
311   - CrmStatisticsCustomerDealCycleByUserRespVO::getOwnerUserId,
312   - CrmStatisticsCustomerDealCycleByUserRespVO::getCustomerDealCycle);
  314 + CrmStatisticsCustomerDealCycleByUserRespVO::getOwnerUserId,
  315 + CrmStatisticsCustomerDealCycleByUserRespVO::getCustomerDealCycle);
313 316 final Map<Long, Integer> customerDealCountMap = convertMap(customerDealCount,
314   - CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
315   - CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount);
  317 + CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId,
  318 + CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount);
316 319 List<CrmStatisticsCustomerDealCycleByUserRespVO> respVoList = new ArrayList<>(userIds.size());
317 320 userIds.forEach(userId -> {
318 321 final CrmStatisticsCustomerDealCycleByUserRespVO vo = new CrmStatisticsCustomerDealCycleByUserRespVO()
319   - .setCustomerDealCycle(customerDealCycleMap.getOrDefault(userId, 0.0))
320   - .setCustomerDealCount(customerDealCountMap.getOrDefault(userId, 0));
  322 + .setCustomerDealCycle(customerDealCycleMap.getOrDefault(userId, 0.0))
  323 + .setCustomerDealCount(customerDealCountMap.getOrDefault(userId, 0));
321 324 vo.setOwnerUserId(userId);
322 325 respVoList.add(vo);
323 326 });
... ... @@ -328,6 +331,75 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
328 331 return respVoList;
329 332 }
330 333  
  334 + @Override
  335 + public List<CrmStatisticCustomerIndustryRespVO> getCustomerIndustry(CrmStatisticsCustomerReqVO reqVO) {
  336 + // 1. 获得用户编号数组
  337 + List<Long> userIds = getUserIds(reqVO);
  338 + if (CollUtil.isEmpty(userIds)) {
  339 + return Collections.emptyList();
  340 + }
  341 + reqVO.setUserIds(userIds);
  342 + // 2. 获取客户行业统计数据
  343 + List<CrmStatisticCustomerIndustryRespVO> industryRespVOList = customerMapper.selectCustomerIndustryListGroupbyIndustryId(reqVO);
  344 + if (CollUtil.isEmpty(industryRespVOList)) {
  345 + return Collections.emptyList();
  346 + }
  347 +
  348 + return convertList(industryRespVOList, item -> {
  349 + if (ObjUtil.isNull(item.getIndustryId())) {
  350 + return item;
  351 + }
  352 + item.setIndustryName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, item.getIndustryId()));
  353 + return item;
  354 + });
  355 + }
  356 +
  357 + @Override
  358 + public List<CrmStatisticCustomerSourceRespVO> getCustomerSource(CrmStatisticsCustomerReqVO reqVO) {
  359 + // 1. 获得用户编号数组
  360 + List<Long> userIds = getUserIds(reqVO);
  361 + if (CollUtil.isEmpty(userIds)) {
  362 + return Collections.emptyList();
  363 + }
  364 + reqVO.setUserIds(userIds);
  365 + // 2. 获取客户行业统计数据
  366 + List<CrmStatisticCustomerSourceRespVO> sourceRespVOList = customerMapper.selectCustomerSourceListGroupbySource(reqVO);
  367 + if (CollUtil.isEmpty(sourceRespVOList)) {
  368 + return Collections.emptyList();
  369 + }
  370 +
  371 + return convertList(sourceRespVOList, item -> {
  372 + if (ObjUtil.isNull(item.getSource())) {
  373 + return item;
  374 + }
  375 + item.setSourceName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_SOURCE, item.getSource()));
  376 + return item;
  377 + });
  378 + }
  379 +
  380 + @Override
  381 + public List<CrmStatisticCustomerLevelRespVO> getCustomerLevel(CrmStatisticsCustomerReqVO reqVO) {
  382 + // 1. 获得用户编号数组
  383 + List<Long> userIds = getUserIds(reqVO);
  384 + if (CollUtil.isEmpty(userIds)) {
  385 + return Collections.emptyList();
  386 + }
  387 + reqVO.setUserIds(userIds);
  388 + // 2. 获取客户行业统计数据
  389 + List<CrmStatisticCustomerLevelRespVO> levelRespVOList = customerMapper.selectCustomerLevelListGroupbyLevel(reqVO);
  390 + if (CollUtil.isEmpty(levelRespVOList)) {
  391 + return Collections.emptyList();
  392 + }
  393 +
  394 + return convertList(levelRespVOList, item -> {
  395 + if (ObjUtil.isNull(item.getLevel())) {
  396 + return item;
  397 + }
  398 + item.setLevelName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_LEVEL, item.getLevel()));
  399 + return item;
  400 + });
  401 + }
  402 +
331 403 /**
332 404 * 拼接用户信息(昵称)
333 405 *
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsCustomerMapper.xml
... ... @@ -249,4 +249,68 @@
249 249 GROUP BY a.owner_user_id
250 250 </select>
251 251  
  252 + <select id="selectCustomerIndustryListGroupbyIndustryId"
  253 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerIndustryRespVO">
  254 + SELECT
  255 + industry_id,
  256 + COUNT(*) AS customerCount,
  257 + SUM(deal_status) AS dealCount,
  258 + ROUND(COUNT(*) / (SELECT COUNT(*) FROM crm_customer WHERE deleted = 0) * 100, 2) AS industryPortion,
  259 + ROUND(SUM(deal_status) / NULLIF(COUNT(*), 0) * 100, 2) AS dealPortion
  260 + FROM
  261 + crm_customer
  262 + WHERE
  263 + deleted = 0 AND industry_id IS NOT NULL
  264 + AND owner_user_id IN
  265 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  266 + #{userId}
  267 + </foreach>
  268 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
  269 + #{times[1],javaType=java.time.LocalDateTime}
  270 + GROUP BY
  271 + industry_id;
  272 + </select>
  273 + <select id="selectCustomerSourceListGroupbySource"
  274 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerSourceRespVO">
  275 + SELECT
  276 + source,
  277 + COUNT(*) AS customerCount,
  278 + SUM(deal_status) AS dealCount,
  279 + ROUND(COUNT(*) / (SELECT COUNT(*) FROM crm_customer WHERE deleted = 0) * 100, 2) AS sourcePortion,
  280 + ROUND(SUM(deal_status) / NULLIF(COUNT(*), 0) * 100, 2) AS dealPortion
  281 + FROM
  282 + crm_customer
  283 + WHERE
  284 + deleted = 0 AND source IS NOT NULL
  285 + AND owner_user_id IN
  286 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  287 + #{userId}
  288 + </foreach>
  289 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
  290 + #{times[1],javaType=java.time.LocalDateTime}
  291 + GROUP BY
  292 + source;
  293 + </select>
  294 + <select id="selectCustomerLevelListGroupbyLevel"
  295 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerLevelRespVO">
  296 + SELECT
  297 + level,
  298 + COUNT(*) AS customerCount,
  299 + SUM(deal_status) AS dealCount,
  300 + ROUND(COUNT(*) / (SELECT COUNT(*) FROM crm_customer WHERE deleted = 0) * 100, 2) AS levelPortion,
  301 + ROUND(SUM(deal_status) / NULLIF(COUNT(*), 0) * 100, 2) AS dealPortion
  302 + FROM
  303 + crm_customer
  304 + WHERE
  305 + deleted = 0 AND level IS NOT NULL
  306 + AND owner_user_id IN
  307 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  308 + #{userId}
  309 + </foreach>
  310 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
  311 + #{times[1],javaType=java.time.LocalDateTime}
  312 + GROUP BY
  313 + level;
  314 + </select>
  315 +
252 316 </mapper>
... ...
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java
1 1 package cn.iocoder.yudao.module.system.api.dict;
2 2  
  3 +import cn.hutool.core.util.ObjUtil;
  4 +import cn.hutool.core.util.StrUtil;
3 5 import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
4 6  
5 7 import java.util.Collection;
... ... @@ -34,6 +36,21 @@ public interface DictDataApi {
34 36 DictDataRespDTO getDictData(String type, String value);
35 37  
36 38 /**
  39 + * 获得指定的字典标签,从缓存中
  40 + *
  41 + * @param type 字典类型
  42 + * @param value 字典数据值
  43 + * @return 字典标签
  44 + */
  45 + default String getDictDataLabel(String type, Integer value) {
  46 + DictDataRespDTO dictData = getDictData(type, String.valueOf(value));
  47 + if (ObjUtil.isNull(dictData)) {
  48 + return StrUtil.EMPTY;
  49 + }
  50 + return dictData.getLabel();
  51 + }
  52 +
  53 + /**
37 54 * 解析获得指定的字典数据,从缓存中
38 55 *
39 56 * @param type 字典类型
... ...
yudao-server/pom.xml
... ... @@ -95,11 +95,11 @@
95 95 </dependency>
96 96  
97 97 <!-- ERP 相关模块。默认注释,保证编译速度 -->
98   - <dependency>
99   - <groupId>cn.iocoder.boot</groupId>
100   - <artifactId>yudao-module-erp-biz</artifactId>
101   - <version>${revision}</version>
102   - </dependency>
  98 +<!-- <dependency>-->
  99 +<!-- <groupId>cn.iocoder.boot</groupId>-->
  100 +<!-- <artifactId>yudao-module-erp-biz</artifactId>-->
  101 +<!-- <version>${revision}</version>-->
  102 +<!-- </dependency>-->
103 103  
104 104 <!-- spring boot 配置所需依赖 -->
105 105 <dependency>
... ...