Commit 9ea43ce55ac7a79ac1894d8291c498515ef6da69
Committed by
Gitee
!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> | ... | ... |