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 | package cn.iocoder.yudao.module.crm.controller.admin.statistics; | 1 | package cn.iocoder.yudao.module.crm.controller.admin.statistics; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 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 | import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerAreaRespVO; | 5 | import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerAreaRespVO; |
| 6 | import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerIndustryRespVO; | 6 | import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerIndustryRespVO; |
| 7 | import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerLevelRespVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.CrmStatisticCustomerLevelRespVO; |
| @@ -30,34 +30,32 @@ public class CrmStatisticsPortraitController { | @@ -30,34 +30,32 @@ public class CrmStatisticsPortraitController { | ||
| 30 | @Resource | 30 | @Resource |
| 31 | private CrmStatisticsPortraitService statisticsPortraitService; | 31 | private CrmStatisticsPortraitService statisticsPortraitService; |
| 32 | 32 | ||
| 33 | - // TODO @puhui999:搞个属于自己的 CrmStatisticsCustomerReqVO 类哈 | ||
| 34 | - | ||
| 35 | @GetMapping("/get-customer-area-summary") | 33 | @GetMapping("/get-customer-area-summary") |
| 36 | @Operation(summary = "获取客户地区统计数据", description = "用于【城市分布分析】页面") | 34 | @Operation(summary = "获取客户地区统计数据", description = "用于【城市分布分析】页面") |
| 37 | @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')") | 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 | @GetMapping("/get-customer-industry-summary") | 40 | @GetMapping("/get-customer-industry-summary") |
| 43 | @Operation(summary = "获取客户行业统计数据", description = "用于【客户行业分析】页面") | 41 | @Operation(summary = "获取客户行业统计数据", description = "用于【客户行业分析】页面") |
| 44 | @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')") | 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 | @GetMapping("/get-customer-level-summary") | 47 | @GetMapping("/get-customer-level-summary") |
| 50 | @Operation(summary = "获取客户级别统计数据", description = "用于【客户级别分析】页面") | 48 | @Operation(summary = "获取客户级别统计数据", description = "用于【客户级别分析】页面") |
| 51 | @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')") | 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 | @GetMapping("/get-customer-source-summary") | 54 | @GetMapping("/get-customer-source-summary") |
| 57 | @Operation(summary = "获取客户来源统计数据", description = "用于【客户来源分析】页面") | 55 | @Operation(summary = "获取客户来源统计数据", description = "用于【客户来源分析】页面") |
| 58 | @PreAuthorize("@ss.hasPermission('crm:statistics-portrait:query')") | 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,12 +18,4 @@ public class CrmStatisticCustomerAreaRespVO { | ||
| 18 | @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 18 | @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 19 | private Integer dealCount; | 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 +9,6 @@ public class CrmStatisticCustomerIndustryRespVO { | ||
| 9 | 9 | ||
| 10 | @Schema(description = "客户行业ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | 10 | @Schema(description = "客户行业ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 11 | private Integer industryId; | 11 | private Integer industryId; |
| 12 | - // TODO @puhui999:这个前端字典翻译哈 | ||
| 13 | - @Schema(description = "客户行业名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 14 | - private String industryName; | ||
| 15 | 12 | ||
| 16 | @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 13 | @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 17 | private Integer customerCount; | 14 | private Integer customerCount; |
| @@ -19,12 +16,4 @@ public class CrmStatisticCustomerIndustryRespVO { | @@ -19,12 +16,4 @@ public class CrmStatisticCustomerIndustryRespVO { | ||
| 19 | @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 16 | @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 20 | private Integer dealCount; | 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 +9,6 @@ public class CrmStatisticCustomerLevelRespVO { | ||
| 9 | 9 | ||
| 10 | @Schema(description = "客户级别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | 10 | @Schema(description = "客户级别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 11 | private Integer level; | 11 | private Integer level; |
| 12 | - // TODO @puhui999:这个前端字典翻译哈 | ||
| 13 | - @Schema(description = "客户级别名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 14 | - private String levelName; | ||
| 15 | 12 | ||
| 16 | @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 13 | @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 17 | private Integer customerCount; | 14 | private Integer customerCount; |
| @@ -19,12 +16,4 @@ public class CrmStatisticCustomerLevelRespVO { | @@ -19,12 +16,4 @@ public class CrmStatisticCustomerLevelRespVO { | ||
| 19 | @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 16 | @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 20 | private Integer dealCount; | 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 +9,6 @@ public class CrmStatisticCustomerSourceRespVO { | ||
| 9 | 9 | ||
| 10 | @Schema(description = "客户来源编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | 10 | @Schema(description = "客户来源编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 11 | private Integer source; | 11 | private Integer source; |
| 12 | - // TODO @puhui999:这个前端字典翻译哈 | ||
| 13 | - @Schema(description = "客户来源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 14 | - private String sourceName; | ||
| 15 | 12 | ||
| 16 | @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 13 | @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 17 | private Integer customerCount; | 14 | private Integer customerCount; |
| @@ -19,12 +16,4 @@ public class CrmStatisticCustomerSourceRespVO { | @@ -19,12 +16,4 @@ public class CrmStatisticCustomerSourceRespVO { | ||
| 19 | @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 16 | @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 20 | private Integer dealCount; | 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 | package cn.iocoder.yudao.module.crm.dal.mysql.statistics; | 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 | import org.apache.ibatis.annotations.Mapper; | 4 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 5 | ||
| 10 | import java.util.List; | 6 | import java.util.List; |
| @@ -17,14 +13,12 @@ import java.util.List; | @@ -17,14 +13,12 @@ import java.util.List; | ||
| 17 | @Mapper | 13 | @Mapper |
| 18 | public interface CrmStatisticsPortraitMapper { | 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 | package cn.iocoder.yudao.module.crm.service.statistics; | 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 | import java.util.List; | 5 | import java.util.List; |
| 10 | 6 | ||
| @@ -21,7 +17,7 @@ public interface CrmStatisticsPortraitService { | @@ -21,7 +17,7 @@ public interface CrmStatisticsPortraitService { | ||
| 21 | * @param reqVO 请求参数 | 17 | * @param reqVO 请求参数 |
| 22 | * @return 统计数据 | 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,7 +25,7 @@ public interface CrmStatisticsPortraitService { | ||
| 29 | * @param reqVO 请求参数 | 25 | * @param reqVO 请求参数 |
| 30 | * @return 统计数据 | 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,7 +33,7 @@ public interface CrmStatisticsPortraitService { | ||
| 37 | * @param reqVO 请求参数 | 33 | * @param reqVO 请求参数 |
| 38 | * @return 统计数据 | 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,6 +41,6 @@ public interface CrmStatisticsPortraitService { | ||
| 45 | * @param reqVO 请求参数 | 41 | * @param reqVO 请求参数 |
| 46 | * @return 统计数据 | 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,15 +5,10 @@ import cn.hutool.core.util.ObjUtil; | ||
| 5 | import cn.iocoder.yudao.framework.ip.core.Area; | 5 | import cn.iocoder.yudao.framework.ip.core.Area; |
| 6 | import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; | 6 | import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; |
| 7 | import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; | 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 | import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsPortraitMapper; | 9 | import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsPortraitMapper; |
| 14 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; | 10 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| 15 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | 11 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| 16 | -import cn.iocoder.yudao.module.system.api.dict.DictDataApi; | ||
| 17 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 12 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 18 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 13 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 19 | import jakarta.annotation.Resource; | 14 | import jakarta.annotation.Resource; |
| @@ -26,9 +21,7 @@ import java.util.Map; | @@ -26,9 +21,7 @@ import java.util.Map; | ||
| 26 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 21 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| 27 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | 22 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| 28 | import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | 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 | * CRM 客户画像 Service 实现类 | 26 | * CRM 客户画像 Service 实现类 |
| 34 | * | 27 | * |
| @@ -44,64 +37,54 @@ public class CrmStatisticsPortraitServiceImpl implements CrmStatisticsPortraitSe | @@ -44,64 +37,54 @@ public class CrmStatisticsPortraitServiceImpl implements CrmStatisticsPortraitSe | ||
| 44 | private AdminUserApi adminUserApi; | 37 | private AdminUserApi adminUserApi; |
| 45 | @Resource | 38 | @Resource |
| 46 | private DeptApi deptApi; | 39 | private DeptApi deptApi; |
| 47 | - @Resource | ||
| 48 | - private DictDataApi dictDataApi; | ||
| 49 | 40 | ||
| 50 | @Override | 41 | @Override |
| 51 | - public List<CrmStatisticCustomerAreaRespVO> getCustomerAreaSummary(CrmStatisticsCustomerReqVO reqVO) { | ||
| 52 | - // 1. 获得用户编号数组 | 42 | + public List<CrmStatisticCustomerAreaRespVO> getCustomerSummaryByArea(CrmStatisticsPortraitReqVO reqVO) { |
| 43 | + // 1.1 获得用户编号数组 | ||
| 53 | List<Long> userIds = getUserIds(reqVO); | 44 | List<Long> userIds = getUserIds(reqVO); |
| 54 | if (CollUtil.isEmpty(userIds)) { | 45 | if (CollUtil.isEmpty(userIds)) { |
| 55 | return Collections.emptyList(); | 46 | return Collections.emptyList(); |
| 56 | } | 47 | } |
| 57 | reqVO.setUserIds(userIds); | 48 | reqVO.setUserIds(userIds); |
| 58 | - // 2. 获取客户地区统计数据 | ||
| 59 | - List<CrmStatisticCustomerAreaRespVO> list = portraitMapper.selectSummaryListByAreaId(reqVO); | 49 | + // 1.2 获取客户地区统计数据 |
| 50 | + List<CrmStatisticCustomerAreaRespVO> list = portraitMapper.selectSummaryListGroupByAreaId(reqVO); | ||
| 60 | if (CollUtil.isEmpty(list)) { | 51 | if (CollUtil.isEmpty(list)) { |
| 61 | return Collections.emptyList(); | 52 | return Collections.emptyList(); |
| 62 | } | 53 | } |
| 63 | 54 | ||
| 64 | - // 拼接数据 | 55 | + // 2. 拼接数据 |
| 65 | List<Area> areaList = AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area); | 56 | List<Area> areaList = AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area); |
| 66 | areaList.add(new Area().setId(null).setName("未知")); | 57 | areaList.add(new Area().setId(null).setName("未知")); |
| 67 | Map<Integer, Area> areaMap = convertMap(areaList, Area::getId); | 58 | Map<Integer, Area> areaMap = convertMap(areaList, Area::getId); |
| 68 | - List<CrmStatisticCustomerAreaRespVO> customerAreaRespVOList = convertList(list, item -> { | 59 | + return convertList(list, item -> { |
| 69 | Integer parentId = AreaUtils.getParentIdByType(item.getAreaId(), AreaTypeEnum.PROVINCE); | 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 | findAndThen(areaMap, parentId, area -> item.setAreaId(parentId).setAreaName(area.getName())); | 64 | findAndThen(areaMap, parentId, area -> item.setAreaId(parentId).setAreaName(area.getName())); |
| 75 | return item; | 65 | return item; |
| 76 | }); | 66 | }); |
| 77 | - return customerAreaRespVOList; | ||
| 78 | } | 67 | } |
| 79 | 68 | ||
| 80 | @Override | 69 | @Override |
| 81 | - public List<CrmStatisticCustomerIndustryRespVO> getCustomerIndustrySummary(CrmStatisticsCustomerReqVO reqVO) { | 70 | + public List<CrmStatisticCustomerIndustryRespVO> getCustomerSummaryByIndustry(CrmStatisticsPortraitReqVO reqVO) { |
| 82 | // 1. 获得用户编号数组 | 71 | // 1. 获得用户编号数组 |
| 83 | List<Long> userIds = getUserIds(reqVO); | 72 | List<Long> userIds = getUserIds(reqVO); |
| 84 | if (CollUtil.isEmpty(userIds)) { | 73 | if (CollUtil.isEmpty(userIds)) { |
| 85 | return Collections.emptyList(); | 74 | return Collections.emptyList(); |
| 86 | } | 75 | } |
| 87 | reqVO.setUserIds(userIds); | 76 | reqVO.setUserIds(userIds); |
| 77 | + | ||
| 88 | // 2. 获取客户行业统计数据 | 78 | // 2. 获取客户行业统计数据 |
| 89 | - List<CrmStatisticCustomerIndustryRespVO> industryRespVOList = portraitMapper.selectCustomerIndustryListGroupbyIndustryId(reqVO); | 79 | + List<CrmStatisticCustomerIndustryRespVO> industryRespVOList = portraitMapper.selectCustomerIndustryListGroupByIndustryId(reqVO); |
| 90 | if (CollUtil.isEmpty(industryRespVOList)) { | 80 | if (CollUtil.isEmpty(industryRespVOList)) { |
| 91 | return Collections.emptyList(); | 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 | @Override | 86 | @Override |
| 104 | - public List<CrmStatisticCustomerSourceRespVO> getCustomerSourceSummary(CrmStatisticsCustomerReqVO reqVO) { | 87 | + public List<CrmStatisticCustomerSourceRespVO> getCustomerSummaryBySource(CrmStatisticsPortraitReqVO reqVO) { |
| 105 | // 1. 获得用户编号数组 | 88 | // 1. 获得用户编号数组 |
| 106 | List<Long> userIds = getUserIds(reqVO); | 89 | List<Long> userIds = getUserIds(reqVO); |
| 107 | if (CollUtil.isEmpty(userIds)) { | 90 | if (CollUtil.isEmpty(userIds)) { |
| @@ -110,41 +93,28 @@ public class CrmStatisticsPortraitServiceImpl implements CrmStatisticsPortraitSe | @@ -110,41 +93,28 @@ public class CrmStatisticsPortraitServiceImpl implements CrmStatisticsPortraitSe | ||
| 110 | reqVO.setUserIds(userIds); | 93 | reqVO.setUserIds(userIds); |
| 111 | 94 | ||
| 112 | // 2. 获取客户行业统计数据 | 95 | // 2. 获取客户行业统计数据 |
| 113 | - List<CrmStatisticCustomerSourceRespVO> sourceRespVOList = portraitMapper.selectCustomerSourceListGroupbySource(reqVO); | 96 | + List<CrmStatisticCustomerSourceRespVO> sourceRespVOList = portraitMapper.selectCustomerSourceListGroupBySource(reqVO); |
| 114 | if (CollUtil.isEmpty(sourceRespVOList)) { | 97 | if (CollUtil.isEmpty(sourceRespVOList)) { |
| 115 | return Collections.emptyList(); | 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 | @Override | 103 | @Override |
| 128 | - public List<CrmStatisticCustomerLevelRespVO> getCustomerLevelSummary(CrmStatisticsCustomerReqVO reqVO) { | 104 | + public List<CrmStatisticCustomerLevelRespVO> getCustomerSummaryByLevel(CrmStatisticsPortraitReqVO reqVO) { |
| 129 | // 1. 获得用户编号数组 | 105 | // 1. 获得用户编号数组 |
| 130 | List<Long> userIds = getUserIds(reqVO); | 106 | List<Long> userIds = getUserIds(reqVO); |
| 131 | if (CollUtil.isEmpty(userIds)) { | 107 | if (CollUtil.isEmpty(userIds)) { |
| 132 | return Collections.emptyList(); | 108 | return Collections.emptyList(); |
| 133 | } | 109 | } |
| 134 | reqVO.setUserIds(userIds); | 110 | reqVO.setUserIds(userIds); |
| 135 | - // 2. 获取客户行业统计数据 | ||
| 136 | - List<CrmStatisticCustomerLevelRespVO> levelRespVOList = portraitMapper.selectCustomerLevelListGroupbyLevel(reqVO); | 111 | + |
| 112 | + // 2. 获取客户级别统计数据 | ||
| 113 | + List<CrmStatisticCustomerLevelRespVO> levelRespVOList = portraitMapper.selectCustomerLevelListGroupByLevel(reqVO); | ||
| 137 | if (CollUtil.isEmpty(levelRespVOList)) { | 114 | if (CollUtil.isEmpty(levelRespVOList)) { |
| 138 | return Collections.emptyList(); | 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,7 +123,7 @@ public class CrmStatisticsPortraitServiceImpl implements CrmStatisticsPortraitSe | ||
| 153 | * @param reqVO 请求参数 | 123 | * @param reqVO 请求参数 |
| 154 | * @return 用户编号数组 | 124 | * @return 用户编号数组 |
| 155 | */ | 125 | */ |
| 156 | - private List<Long> getUserIds(CrmStatisticsCustomerReqVO reqVO) { | 126 | + private List<Long> getUserIds(CrmStatisticsPortraitReqVO reqVO) { |
| 157 | // 情况一:选中某个用户 | 127 | // 情况一:选中某个用户 |
| 158 | if (ObjUtil.isNotNull(reqVO.getUserId())) { | 128 | if (ObjUtil.isNotNull(reqVO.getUserId())) { |
| 159 | return List.of(reqVO.getUserId()); | 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,91 +2,60 @@ | ||
| 2 | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | 2 | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| 3 | <mapper namespace="cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsPortraitMapper"> | 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 | AND owner_user_id IN | 10 | AND owner_user_id IN |
| 20 | <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | 11 | <foreach collection="userIds" item="userId" open="(" close=")" separator=","> |
| 21 | #{userId} | 12 | #{userId} |
| 22 | </foreach> | 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 | </select> | 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 | AND owner_user_id IN | 24 | AND owner_user_id IN |
| 41 | <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | 25 | <foreach collection="userIds" item="userId" open="(" close=")" separator=","> |
| 42 | #{userId} | 26 | #{userId} |
| 43 | </foreach> | 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 | </select> | 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 | AND owner_user_id IN | 38 | AND owner_user_id IN |
| 62 | <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | 39 | <foreach collection="userIds" item="userId" open="(" close=")" separator=","> |
| 63 | #{userId} | 40 | #{userId} |
| 64 | </foreach> | 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 | </select> | 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 | AND owner_user_id IN | 52 | AND owner_user_id IN |
| 83 | <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | 53 | <foreach collection="userIds" item="userId" open="(" close=")" separator=","> |
| 84 | #{userId} | 54 | #{userId} |
| 85 | </foreach> | 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 | </select> | 59 | </select> |
| 91 | 60 | ||
| 92 | </mapper> | 61 | </mapper> |