mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	CRM:优化【客户统计】的代码实现
This commit is contained in:
		| @@ -1,6 +1,6 @@ | ||||
| # == 1. 客户总量分析 == | ||||
| ### 1.1 客户总量分析(按日) | ||||
| GET {{baseUrl}}/crm/statistics-customer/get-customer-summary-by-date?deptId=100&intervalType=11×[0]=2024-01-01 00:00:00×[1]=2024-01-29 23:59:59 | ||||
| GET {{baseUrl}}/crm/statistics-customer/get-customer-summary-by-date?deptId=100&interval=1×[0]=2024-01-01 00:00:00×[1]=2024-01-29 23:59:59 | ||||
| Authorization: Bearer {{token}} | ||||
| tenant-id: {{adminTenentId}} | ||||
|  | ||||
|   | ||||
| @@ -40,25 +40,25 @@ public class CrmStatisticsCustomerController { | ||||
|         return success(customerService.getCustomerSummaryByUser(reqVO)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/get-followup-summary-by-date") | ||||
|     @GetMapping("/get-follow-up-summary-by-date") | ||||
|     @Operation(summary = "获取客户跟进次数分析(按日期)") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:statistics-customer:query')") | ||||
|     public CommonResult<List<CrmStatisticsFollowupSummaryByDateRespVO>> getFollowupSummaryByDate(@Valid CrmStatisticsCustomerReqVO reqVO) { | ||||
|         return success(customerService.getFollowupSummaryByDate(reqVO)); | ||||
|     public CommonResult<List<CrmStatisticsFollowUpSummaryByDateRespVO>> getFollowupSummaryByDate(@Valid CrmStatisticsCustomerReqVO reqVO) { | ||||
|         return success(customerService.getFollowUpSummaryByDate(reqVO)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/get-followup-summary-by-user") | ||||
|     @GetMapping("/get-follow-up-summary-by-user") | ||||
|     @Operation(summary = "获取客户跟进次数分析(按用户)") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:statistics-customer:query')") | ||||
|     public CommonResult<List<CrmStatisticsFollowupSummaryByUserRespVO>> getFollowupSummaryByUser(@Valid CrmStatisticsCustomerReqVO reqVO) { | ||||
|         return success(customerService.getFollowupSummaryByUser(reqVO)); | ||||
|     public CommonResult<List<CrmStatisticsFollowUpSummaryByUserRespVO>> getFollowUpSummaryByUser(@Valid CrmStatisticsCustomerReqVO reqVO) { | ||||
|         return success(customerService.getFollowUpSummaryByUser(reqVO)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/get-followup-summary-by-type") | ||||
|     @GetMapping("/get-follow-up-summary-by-type") | ||||
|     @Operation(summary = "获取客户跟进次数分析(按类型)") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:statistics-customer:query')") | ||||
|     public CommonResult<List<CrmStatisticsFollowupSummaryByTypeRespVO>> getFollowupSummaryByType(@Valid CrmStatisticsCustomerReqVO reqVO) { | ||||
|         return success(customerService.getFollowupSummaryByType(reqVO)); | ||||
|     public CommonResult<List<CrmStatisticsFollowUpSummaryByTypeRespVO>> getFollowUpSummaryByType(@Valid CrmStatisticsCustomerReqVO reqVO) { | ||||
|         return success(customerService.getFollowUpSummaryByType(reqVO)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/get-contract-summary") | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer; | ||||
|  | ||||
| import com.fasterxml.jackson.annotation.JsonIgnore; | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
| @@ -13,7 +12,6 @@ import lombok.Data; | ||||
| public class CrmStatisticsCustomerByUserBaseRespVO { | ||||
|  | ||||
|     @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     @JsonIgnore | ||||
|     private Long ownerUserId; | ||||
|  | ||||
|     @Schema(description = "负责人", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") | ||||
|   | ||||
| @@ -1,18 +1,12 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer; | ||||
|  | ||||
|  | ||||
| import com.fasterxml.jackson.annotation.JsonFormat; | ||||
| import com.fasterxml.jackson.annotation.JsonIgnore; | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
| import java.math.BigDecimal; | ||||
| import java.time.LocalDate; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; | ||||
| import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; | ||||
|  | ||||
| @Schema(description = "管理后台 - CRM 客户转化率分析 VO") | ||||
| @Data | ||||
| public class CrmStatisticsCustomerContractSummaryRespVO { | ||||
| @@ -29,31 +23,19 @@ public class CrmStatisticsCustomerContractSummaryRespVO { | ||||
|     @Schema(description = "回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1200.00") | ||||
|     private BigDecimal receivablePrice; | ||||
|  | ||||
|     @Schema(description = "客户行业ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||||
|     @JsonIgnore | ||||
|     private String industryId; | ||||
|     @Schema(description = "客户行业编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||||
|     private Integer industryId; | ||||
|  | ||||
|     @Schema(description = "客户行业", requiredMode = Schema.RequiredMode.REQUIRED, example = "金融") | ||||
|     private String industryName; | ||||
|  | ||||
|     @Schema(description = "客户来源ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     @JsonIgnore | ||||
|     private String source; | ||||
|  | ||||
|     @Schema(description = "客户来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "外呼") | ||||
|     private String sourceName; | ||||
|     @Schema(description = "客户来源编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer source; | ||||
|  | ||||
|     @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     @JsonIgnore | ||||
|     private Long ownerUserId; | ||||
|  | ||||
|     @Schema(description = "负责人", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") | ||||
|     private String ownerUserName; | ||||
|  | ||||
|     @Schema(description = "创建人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||||
|     @JsonIgnore | ||||
|     private String creatorUserId; | ||||
|  | ||||
|     private String creator; | ||||
|     @Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED, example = "源码") | ||||
|     private String creatorUserName; | ||||
|  | ||||
| @@ -61,7 +43,6 @@ public class CrmStatisticsCustomerContractSummaryRespVO { | ||||
|     private LocalDateTime createTime; | ||||
|  | ||||
|     @Schema(description = "下单日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02 00:00:00") | ||||
|     @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY, timezone = TIME_ZONE_DEFAULT) | ||||
|     private LocalDate orderDate; | ||||
|     private LocalDateTime orderDate; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -11,6 +11,6 @@ public class CrmStatisticsCustomerDealCycleByDateRespVO { | ||||
|     private String time; | ||||
|  | ||||
|     @Schema(description = "成交周期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1.0") | ||||
|     private Double customerDealCycle = 0.0; | ||||
|     private Double customerDealCycle; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -8,9 +8,9 @@ import lombok.Data; | ||||
| public class CrmStatisticsCustomerDealCycleByUserRespVO extends CrmStatisticsCustomerByUserBaseRespVO { | ||||
|  | ||||
|     @Schema(description = "成交周期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1.0") | ||||
|     private Double customerDealCycle = 0.0; | ||||
|     private Double customerDealCycle; | ||||
|  | ||||
|     @Schema(description = "成交客户数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer customerDealCount = 0; | ||||
|     private Integer customerDealCount; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -30,12 +30,12 @@ public class CrmStatisticsCustomerReqVO { | ||||
|      * userIds 目前不用前端传递,目前是方便后端通过 deptId 读取编号后,设置回来 | ||||
|      * 后续,可能会支持选择部分用户进行查询 | ||||
|      */ | ||||
|     @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2") | ||||
|     @Schema(description = "负责人用户 id 集合", hidden = true, example = "2") | ||||
|     private List<Long> userIds; | ||||
|  | ||||
|     @Schema(description = "时间间隔类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     @InEnum(value = DateIntervalEnum.class, message = "时间间隔类型,必须是 {value}") | ||||
|     private Integer intervalType; | ||||
|     private Integer interval; | ||||
|  | ||||
|     /** | ||||
|      * 前端如果选择自定义时间, 那么前端传递起始-终止时间, 如果选择其他时间间隔类型, 则由后台计算起始-终止时间 | ||||
| @@ -49,7 +49,8 @@ public class CrmStatisticsCustomerReqVO { | ||||
|      * group by DATE_FORMAT(field, #{dateFormat}) | ||||
|      * 非前端传递, 由Service计算后传递给Mapper的参数 | ||||
|      */ | ||||
|     @Schema(description = "Group By 日期格式", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "%Y%m") | ||||
|     @Deprecated | ||||
|     @Schema(description = "Group By 日期格式", hidden = true, example = "%Y%m") | ||||
|     private String sqlDateFormat; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -11,9 +11,9 @@ public class CrmStatisticsCustomerSummaryByDateRespVO { | ||||
|     private String time; | ||||
|  | ||||
|     @Schema(description = "新建客户数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer customerCreateCount = 0; | ||||
|     private Integer customerCreateCount; | ||||
|  | ||||
|     @Schema(description = "成交客户数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer customerDealCount = 0; | ||||
|     private Integer customerDealCount; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -10,15 +10,15 @@ import java.math.BigDecimal; | ||||
| public class CrmStatisticsCustomerSummaryByUserRespVO extends CrmStatisticsCustomerByUserBaseRespVO { | ||||
|  | ||||
|     @Schema(description = "新建客户数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer customerCreateCount = 0; | ||||
|     private Integer customerCreateCount; | ||||
|  | ||||
|     @Schema(description = "成交客户数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer customerDealCount = 0; | ||||
|     private Integer customerDealCount; | ||||
|  | ||||
|     @Schema(description = "合同总金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") | ||||
|     private BigDecimal contractPrice = BigDecimal.ZERO; | ||||
|     private BigDecimal contractPrice; | ||||
|  | ||||
|     @Schema(description = "回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") | ||||
|     private BigDecimal receivablePrice = BigDecimal.ZERO; | ||||
|     private BigDecimal receivablePrice; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -5,15 +5,15 @@ import lombok.Data; | ||||
| 
 | ||||
| @Schema(description = "管理后台 - CRM 跟进次数分析(按日期) VO") | ||||
| @Data | ||||
| public class CrmStatisticsFollowupSummaryByDateRespVO { | ||||
| public class CrmStatisticsFollowUpSummaryByDateRespVO { | ||||
| 
 | ||||
|     @Schema(description = "时间轴", requiredMode = Schema.RequiredMode.REQUIRED, example = "202401") | ||||
|     private String time; | ||||
| 
 | ||||
|     @Schema(description = "跟进次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer followupRecordCount = 0; | ||||
|     private Integer followUpRecordCount; | ||||
| 
 | ||||
|     @Schema(description = "跟进客户数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer followupCustomerCount = 0; | ||||
|     private Integer followUpCustomerCount; | ||||
| 
 | ||||
| } | ||||
| @@ -6,12 +6,12 @@ import lombok.Data; | ||||
| 
 | ||||
| @Schema(description = "管理后台 - CRM 跟进次数分析(按类型) VO") | ||||
| @Data | ||||
| public class CrmStatisticsFollowupSummaryByTypeRespVO { | ||||
| public class CrmStatisticsFollowUpSummaryByTypeRespVO { | ||||
| 
 | ||||
|     @Schema(description = "跟进类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private String followupType; | ||||
|     private Integer followUpType; | ||||
| 
 | ||||
|     @Schema(description = "跟进次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer followupRecordCount = 0; | ||||
|     private Integer followUpRecordCount; | ||||
| 
 | ||||
| } | ||||
| @@ -5,12 +5,12 @@ import lombok.Data; | ||||
| 
 | ||||
| @Schema(description = "管理后台 - CRM 跟进次数分析(按用户) VO") | ||||
| @Data | ||||
| public class CrmStatisticsFollowupSummaryByUserRespVO extends CrmStatisticsCustomerByUserBaseRespVO { | ||||
| public class CrmStatisticsFollowUpSummaryByUserRespVO extends CrmStatisticsCustomerByUserBaseRespVO { | ||||
| 
 | ||||
|     @Schema(description = "跟进次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer followupRecordCount = 0; | ||||
|     private Integer followUpRecordCount; | ||||
| 
 | ||||
|     @Schema(description = "跟进客户数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer followupCustomerCount = 0; | ||||
|     private Integer followUpCustomerCount; | ||||
| 
 | ||||
| } | ||||
| @@ -17,6 +17,7 @@ public class CrmStatisticsRankRespVO { | ||||
|     @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private String deptName; | ||||
|  | ||||
|     // TODO @芋艿:需要改下,金额是 bigdecimal | ||||
|     /** | ||||
|      * 数量是个特别“抽象”的概念,在不同排行下,代表不同含义 | ||||
|      * <p> | ||||
|   | ||||
| @@ -13,32 +13,32 @@ import java.util.List; | ||||
| @Mapper | ||||
| public interface CrmStatisticsCustomerMapper { | ||||
|  | ||||
|     List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerCreateCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); // 已经 review | ||||
|     List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerCreateCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerDealCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); // 已经 review | ||||
|     List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerDealCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerCreateCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); // 已经 review | ||||
|     List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerCreateCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerDealCountGroupByUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review | ||||
|     List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerDealCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsCustomerSummaryByUserRespVO> selectContractPriceGroupByUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review | ||||
|     List<CrmStatisticsCustomerSummaryByUserRespVO> selectContractPriceGroupByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsCustomerSummaryByUserRespVO> selectReceivablePriceGroupByUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO);  // 已经 review | ||||
|     List<CrmStatisticsCustomerSummaryByUserRespVO> selectReceivablePriceGroupByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsFollowupSummaryByDateRespVO> selectFollowupRecordCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); | ||||
|     List<CrmStatisticsFollowUpSummaryByDateRespVO> selectFollowUpRecordCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsFollowupSummaryByDateRespVO> selectFollowupCustomerCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); | ||||
|     List<CrmStatisticsFollowUpSummaryByDateRespVO> selectFollowUpCustomerCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsFollowupSummaryByUserRespVO> selectFollowupRecordCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|     List<CrmStatisticsFollowUpSummaryByUserRespVO> selectFollowUpRecordCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsFollowupSummaryByUserRespVO> selectFollowupCustomerCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|     List<CrmStatisticsFollowUpSummaryByUserRespVO> selectFollowUpCustomerCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsCustomerContractSummaryRespVO> selectContractSummary(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsFollowupSummaryByTypeRespVO> selectFollowupRecordCountGroupByType(CrmStatisticsCustomerReqVO reqVO); | ||||
|     List<CrmStatisticsFollowUpSummaryByTypeRespVO> selectFollowUpRecordCountGroupByType(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsCustomerDealCycleByDateRespVO> selectCustomerDealCycleGroupByDate(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsCustomerDealCycleByUserRespVO> selectCustomerDealCycleGroupByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|     List<CrmStatisticsCustomerDealCycleByUserRespVO> selectCustomerDealCycleGroupByUser(CrmStatisticsCustomerReqVO reqVO); // TODO | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -27,14 +27,13 @@ public interface CrmStatisticsCustomerService { | ||||
|      */ | ||||
|     List<CrmStatisticsCustomerSummaryByUserRespVO> getCustomerSummaryByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * 跟进次数分析(按日期) | ||||
|      * | ||||
|      * @param reqVO 请求参数 | ||||
|      * @return 统计数据 | ||||
|      */ | ||||
|     List<CrmStatisticsFollowupSummaryByDateRespVO> getFollowupSummaryByDate(CrmStatisticsCustomerReqVO reqVO); | ||||
|     List<CrmStatisticsFollowUpSummaryByDateRespVO> getFollowUpSummaryByDate(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     /** | ||||
|      * 跟进次数分析(按用户) | ||||
| @@ -42,7 +41,7 @@ public interface CrmStatisticsCustomerService { | ||||
|      * @param reqVO 请求参数 | ||||
|      * @return 统计数据 | ||||
|      */ | ||||
|     List<CrmStatisticsFollowupSummaryByUserRespVO> getFollowupSummaryByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|     List<CrmStatisticsFollowUpSummaryByUserRespVO> getFollowUpSummaryByUser(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     /** | ||||
|      * 客户跟进次数分析(按类型) | ||||
| @@ -50,8 +49,7 @@ public interface CrmStatisticsCustomerService { | ||||
|      * @param reqVO 请求参数 | ||||
|      * @return 统计数据 | ||||
|      */ | ||||
|     List<CrmStatisticsFollowupSummaryByTypeRespVO> getFollowupSummaryByType(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     List<CrmStatisticsFollowUpSummaryByTypeRespVO> getFollowUpSummaryByType(CrmStatisticsCustomerReqVO reqVO); | ||||
|  | ||||
|     /** | ||||
|      * 获取合同摘要信息(客户转化率页面) | ||||
|   | ||||
| @@ -1,19 +1,13 @@ | ||||
| package cn.iocoder.yudao.module.crm.service.statistics; | ||||
|  | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.hutool.core.date.DateTime; | ||||
| import cn.hutool.core.date.DateUtil; | ||||
| import cn.hutool.core.date.LocalDateTimeUtil; | ||||
| import cn.hutool.core.util.ObjUtil; | ||||
| import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum; | ||||
| import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | ||||
| import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | ||||
| import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*; | ||||
| import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsCustomerMapper; | ||||
| import cn.iocoder.yudao.module.system.api.dept.DeptApi; | ||||
| import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | ||||
| import cn.iocoder.yudao.module.system.api.dict.DictDataApi; | ||||
| import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; | ||||
| import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||||
| import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||||
| import jakarta.annotation.Resource; | ||||
| @@ -27,10 +21,8 @@ import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.stream.Stream; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | ||||
| import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.*; | ||||
| import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.STATISTICS_CUSTOMER_TIMES_NOT_SET; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||||
|  | ||||
| /** | ||||
|  * CRM 客户分析 Service 实现类 | ||||
| @@ -41,13 +33,6 @@ import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.STATISTICS_CU | ||||
| @Validated | ||||
| public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerService { | ||||
|  | ||||
|     private static final String SQL_DATE_FORMAT_BY_MONTH = "%Y%m"; | ||||
|     private static final String SQL_DATE_FORMAT_BY_DAY = "%Y%m%d"; | ||||
|  | ||||
|     private static final String TIME_FORMAT_BY_MONTH = "yyyyMM"; | ||||
|     private static final String TIME_FORMAT_BY_DAY = "yyyyMMdd"; | ||||
|  | ||||
|  | ||||
|     @Resource | ||||
|     private CrmStatisticsCustomerMapper customerMapper; | ||||
|  | ||||
| @@ -55,283 +40,211 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe | ||||
|     private AdminUserApi adminUserApi; | ||||
|     @Resource | ||||
|     private DeptApi deptApi; | ||||
|     @Resource | ||||
|     private DictDataApi dictDataApi; | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmStatisticsCustomerSummaryByDateRespVO> getCustomerSummaryByDate(CrmStatisticsCustomerReqVO reqVO) { | ||||
|         // 1. 获得用户编号数组 | ||||
|         List<Long> userIds = getUserIds(reqVO); | ||||
|         if (CollUtil.isEmpty(userIds)) { | ||||
|         reqVO.setUserIds(getUserIds(reqVO)); | ||||
|         if (CollUtil.isEmpty(reqVO.getUserIds())) { | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|         reqVO.setUserIds(userIds); | ||||
|  | ||||
|         // 2. 获取分项统计数据 | ||||
|         initParams(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByDateRespVO> customerCreateCountVoList = customerMapper.selectCustomerCreateCountGroupByDate(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByDateRespVO> customerDealCountVoList = customerMapper.selectCustomerDealCountGroupByDate(reqVO); | ||||
|         // 2. 按天统计,获取分项统计数据 | ||||
|         List<CrmStatisticsCustomerSummaryByDateRespVO> customerCreateCountList = customerMapper.selectCustomerCreateCountGroupByDate(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByDateRespVO> customerDealCountList = customerMapper.selectCustomerDealCountGroupByDate(reqVO); | ||||
|  | ||||
|         // 3. 合并数据 | ||||
|         List<String> times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]); | ||||
|         Map<String, Integer> customerCreateCountMap = convertMap(customerCreateCountVoList, | ||||
|             CrmStatisticsCustomerSummaryByDateRespVO::getTime, | ||||
|             CrmStatisticsCustomerSummaryByDateRespVO::getCustomerCreateCount); | ||||
|         Map<String, Integer> customerDealCountMap = convertMap(customerDealCountVoList, | ||||
|             CrmStatisticsCustomerSummaryByDateRespVO::getTime, | ||||
|             CrmStatisticsCustomerSummaryByDateRespVO::getCustomerDealCount); | ||||
|         List<CrmStatisticsCustomerSummaryByDateRespVO> respVoList = convertList(times, | ||||
|             time -> new CrmStatisticsCustomerSummaryByDateRespVO() | ||||
|                 .setTime(time) | ||||
|                 .setCustomerCreateCount(customerCreateCountMap.getOrDefault(time, 0)) | ||||
|                 .setCustomerDealCount(customerDealCountMap.getOrDefault(time, 0))); | ||||
|  | ||||
|         return respVoList; | ||||
|         // 3. 按照日期间隔,合并数据 | ||||
|         List<LocalDateTime[]> timeRanges = LocalDateTimeUtils.getDateRangeList(reqVO.getTimes()[0], reqVO.getTimes()[1], reqVO.getInterval()); | ||||
|         return convertList(timeRanges, times -> { | ||||
|             Integer customerCreateCount = customerCreateCountList.stream() | ||||
|                     .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], vo.getTime())) | ||||
|                     .mapToInt(CrmStatisticsCustomerSummaryByDateRespVO::getCustomerCreateCount).sum(); | ||||
|             Integer customerDealCount = customerDealCountList.stream() | ||||
|                     .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], vo.getTime())) | ||||
|                     .mapToInt(CrmStatisticsCustomerSummaryByDateRespVO::getCustomerDealCount).sum(); | ||||
|             return new CrmStatisticsCustomerSummaryByDateRespVO() | ||||
|                     .setTime(LocalDateTimeUtils.formatDateRange(times[0], times[1], reqVO.getInterval())) | ||||
|                     .setCustomerCreateCount(customerCreateCount).setCustomerDealCount(customerDealCount); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmStatisticsCustomerSummaryByUserRespVO> getCustomerSummaryByUser(CrmStatisticsCustomerReqVO reqVO) { | ||||
|         // 1. 获得用户编号数组 | ||||
|         List<Long> userIds = getUserIds(reqVO); | ||||
|         if (CollUtil.isEmpty(userIds)) { | ||||
|         reqVO.setUserIds(getUserIds(reqVO)); | ||||
|         if (CollUtil.isEmpty(reqVO.getUserIds())) { | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|         reqVO.setUserIds(userIds); | ||||
|  | ||||
|         // 2. 获取分项统计数据 | ||||
|         initParams(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> customerCreateCount = customerMapper.selectCustomerCreateCountGroupByUser(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> customerDealCount = customerMapper.selectCustomerDealCountGroupByUser(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> contractPrice = customerMapper.selectContractPriceGroupByUser(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> receivablePrice = customerMapper.selectReceivablePriceGroupByUser(reqVO); | ||||
|         // 2. 按用户统计,获取分项统计数据 | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> customerCreateCountList = customerMapper.selectCustomerCreateCountGroupByUser(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> customerDealCountList = customerMapper.selectCustomerDealCountGroupByUser(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> contractPriceList = customerMapper.selectContractPriceGroupByUser(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> receivablePriceList = customerMapper.selectReceivablePriceGroupByUser(reqVO); | ||||
|  | ||||
|         // 3. 合并统计数据 | ||||
|         Map<Long, Integer> customerCreateCountMap = convertMap(customerCreateCount, | ||||
|             CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId, | ||||
|             CrmStatisticsCustomerSummaryByUserRespVO::getCustomerCreateCount); | ||||
|         Map<Long, Integer> customerDealCountMap = convertMap(customerDealCount, | ||||
|             CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId, | ||||
|             CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount); | ||||
|         Map<Long, BigDecimal> contractPriceMap = convertMap(contractPrice, | ||||
|             CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId, | ||||
|             CrmStatisticsCustomerSummaryByUserRespVO::getContractPrice); | ||||
|         Map<Long, BigDecimal> receivablePriceMap = convertMap(receivablePrice, | ||||
|             CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId, | ||||
|             CrmStatisticsCustomerSummaryByUserRespVO::getReceivablePrice); | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> respVoList = convertList(userIds, userId -> { | ||||
|             CrmStatisticsCustomerSummaryByUserRespVO vo = new CrmStatisticsCustomerSummaryByUserRespVO(); | ||||
|             // ownerUserId 为基类属性 | ||||
|             vo.setOwnerUserId(userId); | ||||
|             vo.setCustomerCreateCount(customerCreateCountMap.getOrDefault(userId, 0)) | ||||
|                 .setCustomerDealCount(customerDealCountMap.getOrDefault(userId, 0)) | ||||
|                 .setContractPrice(contractPriceMap.getOrDefault(userId, BigDecimal.ZERO)) | ||||
|                 .setReceivablePrice(receivablePriceMap.getOrDefault(userId, BigDecimal.ZERO)); | ||||
|             return vo; | ||||
|         // 3.1 按照用户,合并统计数据 | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> summaryList = convertList(reqVO.getUserIds(), userId -> { | ||||
|             Integer customerCreateCount = customerCreateCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId())) | ||||
|                     .mapToInt(CrmStatisticsCustomerSummaryByUserRespVO::getCustomerCreateCount).sum(); | ||||
|             Integer customerDealCount = customerDealCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId())) | ||||
|                     .mapToInt(CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount).sum(); | ||||
|             BigDecimal contractPrice = contractPriceList.stream().filter(vo -> userId.equals(vo.getOwnerUserId())) | ||||
|                     .reduce(BigDecimal.ZERO, (sum, vo) -> sum.add(vo.getContractPrice()), BigDecimal::add); | ||||
|             BigDecimal receivablePrice = receivablePriceList.stream().filter(vo -> userId.equals(vo.getOwnerUserId())) | ||||
|                     .reduce(BigDecimal.ZERO, (sum, vo) -> sum.add(vo.getReceivablePrice()), BigDecimal::add); | ||||
|             return (CrmStatisticsCustomerSummaryByUserRespVO) new CrmStatisticsCustomerSummaryByUserRespVO() | ||||
|                     .setCustomerCreateCount(customerCreateCount).setCustomerDealCount(customerDealCount) | ||||
|                     .setContractPrice(contractPrice).setReceivablePrice(receivablePrice).setOwnerUserId(userId); | ||||
|         }); | ||||
|  | ||||
|         // 4. 拼接用户信息 | ||||
|         appendUserInfo(respVoList); | ||||
|  | ||||
|         return respVoList; | ||||
|         // 3.2 拼接用户信息 | ||||
|         appendUserInfo(summaryList); | ||||
|         return summaryList; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmStatisticsFollowupSummaryByDateRespVO> getFollowupSummaryByDate(CrmStatisticsCustomerReqVO reqVO) { | ||||
|     public List<CrmStatisticsFollowUpSummaryByDateRespVO> getFollowUpSummaryByDate(CrmStatisticsCustomerReqVO reqVO) { | ||||
|         // 1. 获得用户编号数组 | ||||
|         List<Long> userIds = getUserIds(reqVO); | ||||
|         if (CollUtil.isEmpty(userIds)) { | ||||
|         reqVO.setUserIds(getUserIds(reqVO)); | ||||
|         if (CollUtil.isEmpty(reqVO.getUserIds())) { | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|         reqVO.setUserIds(userIds); | ||||
|  | ||||
|         // 2. 获取分项统计数据 | ||||
|         initParams(reqVO); | ||||
|         List<CrmStatisticsFollowupSummaryByDateRespVO> followupRecordCount = customerMapper.selectFollowupRecordCountGroupByDate(reqVO); | ||||
|         List<CrmStatisticsFollowupSummaryByDateRespVO> followupCustomerCount = customerMapper.selectFollowupCustomerCountGroupByDate(reqVO); | ||||
|         // 2. 按天统计,获取分项统计数据 | ||||
|         List<CrmStatisticsFollowUpSummaryByDateRespVO> followUpRecordCountList = customerMapper.selectFollowUpRecordCountGroupByDate(reqVO); | ||||
|         List<CrmStatisticsFollowUpSummaryByDateRespVO> followUpCustomerCountList = customerMapper.selectFollowUpCustomerCountGroupByDate(reqVO); | ||||
|  | ||||
|         // 3. 合并统计数据 | ||||
|         List<String> times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]); | ||||
|         Map<String, Integer> followupRecordCountMap = convertMap(followupRecordCount, | ||||
|             CrmStatisticsFollowupSummaryByDateRespVO::getTime, | ||||
|             CrmStatisticsFollowupSummaryByDateRespVO::getFollowupRecordCount); | ||||
|         Map<String, Integer> followupCustomerCountMap = convertMap(followupCustomerCount, | ||||
|             CrmStatisticsFollowupSummaryByDateRespVO::getTime, | ||||
|             CrmStatisticsFollowupSummaryByDateRespVO::getFollowupCustomerCount); | ||||
|         List<CrmStatisticsFollowupSummaryByDateRespVO> respVoList = convertList(times, time -> | ||||
|             new CrmStatisticsFollowupSummaryByDateRespVO().setTime(time) | ||||
|                 .setFollowupRecordCount(followupRecordCountMap.getOrDefault(time, 0)) | ||||
|                 .setFollowupCustomerCount(followupCustomerCountMap.getOrDefault(time, 0)) | ||||
|         ); | ||||
|  | ||||
|         return respVoList; | ||||
|         // 3. 按照时间间隔,合并统计数据 | ||||
|         List<LocalDateTime[]> timeRanges = LocalDateTimeUtils.getDateRangeList(reqVO.getTimes()[0], reqVO.getTimes()[1], reqVO.getInterval()); | ||||
|         return convertList(timeRanges, times -> { | ||||
|             Integer followUpRecordCount = followUpRecordCountList.stream() | ||||
|                     .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], vo.getTime())) | ||||
|                     .mapToInt(CrmStatisticsFollowUpSummaryByDateRespVO::getFollowUpRecordCount).sum(); | ||||
|             Integer followUpCustomerCount = followUpCustomerCountList.stream() | ||||
|                     .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], vo.getTime())) | ||||
|                     .mapToInt(CrmStatisticsFollowUpSummaryByDateRespVO::getFollowUpCustomerCount).sum(); | ||||
|             return new CrmStatisticsFollowUpSummaryByDateRespVO() | ||||
|                     .setTime(LocalDateTimeUtils.formatDateRange(times[0], times[1], reqVO.getInterval())) | ||||
|                     .setFollowUpCustomerCount(followUpRecordCount).setFollowUpRecordCount(followUpCustomerCount); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmStatisticsFollowupSummaryByUserRespVO> getFollowupSummaryByUser(CrmStatisticsCustomerReqVO reqVO) { | ||||
|     public List<CrmStatisticsFollowUpSummaryByUserRespVO> getFollowUpSummaryByUser(CrmStatisticsCustomerReqVO reqVO) { | ||||
|         // 1. 获得用户编号数组 | ||||
|         List<Long> userIds = getUserIds(reqVO); | ||||
|         if (CollUtil.isEmpty(userIds)) { | ||||
|         reqVO.setUserIds(getUserIds(reqVO)); | ||||
|         if (CollUtil.isEmpty(reqVO.getUserIds())) { | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|         reqVO.setUserIds(userIds); | ||||
|  | ||||
|         // 2. 获取分项统计数据 | ||||
|         initParams(reqVO); | ||||
|         List<CrmStatisticsFollowupSummaryByUserRespVO> followupRecordCount = customerMapper.selectFollowupRecordCountGroupByUser(reqVO); | ||||
|         List<CrmStatisticsFollowupSummaryByUserRespVO> followupCustomerCount = customerMapper.selectFollowupCustomerCountGroupByUser(reqVO); | ||||
|         // 2. 按用户统计,获取分项统计数据 | ||||
|         List<CrmStatisticsFollowUpSummaryByUserRespVO> followUpRecordCountList = customerMapper.selectFollowUpRecordCountGroupByUser(reqVO); | ||||
|         List<CrmStatisticsFollowUpSummaryByUserRespVO> followUpCustomerCountList = customerMapper.selectFollowUpCustomerCountGroupByUser(reqVO); | ||||
|  | ||||
|         // 3. 合并统计数据 | ||||
|         Map<Long, Integer> followupRecordCountMap = convertMap(followupRecordCount, | ||||
|             CrmStatisticsFollowupSummaryByUserRespVO::getOwnerUserId, | ||||
|             CrmStatisticsFollowupSummaryByUserRespVO::getFollowupRecordCount); | ||||
|         Map<Long, Integer> followupCustomerCountMap = convertMap(followupCustomerCount, | ||||
|             CrmStatisticsFollowupSummaryByUserRespVO::getOwnerUserId, | ||||
|             CrmStatisticsFollowupSummaryByUserRespVO::getFollowupCustomerCount); | ||||
|         List<CrmStatisticsFollowupSummaryByUserRespVO> respVoList = convertList(userIds, userId -> { | ||||
|             CrmStatisticsFollowupSummaryByUserRespVO vo = new CrmStatisticsFollowupSummaryByUserRespVO() | ||||
|                 .setFollowupRecordCount(followupRecordCountMap.getOrDefault(userId, 0)) | ||||
|                 .setFollowupCustomerCount(followupCustomerCountMap.getOrDefault(userId, 0)); | ||||
|             // ownerUserId 为基类属性 | ||||
|             vo.setOwnerUserId(userId); | ||||
|             return vo; | ||||
|         // 3.1 按照用户,合并统计数据 | ||||
|         List<CrmStatisticsFollowUpSummaryByUserRespVO> summaryList = convertList(reqVO.getUserIds(), userId -> { | ||||
|             Integer followUpRecordCount = followUpRecordCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId())) | ||||
|                     .mapToInt(CrmStatisticsFollowUpSummaryByUserRespVO::getFollowUpRecordCount).sum(); | ||||
|             Integer followUpCustomerCount = followUpCustomerCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId())) | ||||
|                     .mapToInt(CrmStatisticsFollowUpSummaryByUserRespVO::getFollowUpCustomerCount).sum(); | ||||
|             return (CrmStatisticsFollowUpSummaryByUserRespVO) new CrmStatisticsFollowUpSummaryByUserRespVO() | ||||
|                     .setFollowUpCustomerCount(followUpRecordCount).setFollowUpRecordCount(followUpCustomerCount).setOwnerUserId(userId); | ||||
|         }); | ||||
|  | ||||
|         // 4. 拼接用户信息 | ||||
|         appendUserInfo(respVoList); | ||||
|         return respVoList; | ||||
|         // 3.2 拼接用户信息 | ||||
|         appendUserInfo(summaryList); | ||||
|         return summaryList; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmStatisticsFollowupSummaryByTypeRespVO> getFollowupSummaryByType(CrmStatisticsCustomerReqVO reqVO) { | ||||
|     public List<CrmStatisticsFollowUpSummaryByTypeRespVO> getFollowUpSummaryByType(CrmStatisticsCustomerReqVO reqVO) { | ||||
|         // 1. 获得用户编号数组 | ||||
|         List<Long> userIds = getUserIds(reqVO); | ||||
|         if (CollUtil.isEmpty(userIds)) { | ||||
|         reqVO.setUserIds(getUserIds(reqVO)); | ||||
|         if (CollUtil.isEmpty(reqVO.getUserIds())) { | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|         reqVO.setUserIds(userIds); | ||||
|  | ||||
|         // 2. 获得排行数据 | ||||
|         initParams(reqVO); | ||||
|         List<CrmStatisticsFollowupSummaryByTypeRespVO> respVoList = customerMapper.selectFollowupRecordCountGroupByType(reqVO); | ||||
|  | ||||
|         // 3. 获取字典数据 | ||||
|         List<DictDataRespDTO> followUpTypes = dictDataApi.getDictDataList(CRM_FOLLOW_UP_TYPE); | ||||
|         Map<String, String> followUpTypeMap = convertMap(followUpTypes, | ||||
|             DictDataRespDTO::getValue, DictDataRespDTO::getLabel); | ||||
|         respVoList.forEach(vo -> { | ||||
|             vo.setFollowupType(followUpTypeMap.get(vo.getFollowupType())); | ||||
|         }); | ||||
|  | ||||
|         return respVoList; | ||||
|         // 2. 获得跟进数据 | ||||
|         return customerMapper.selectFollowUpRecordCountGroupByType(reqVO); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmStatisticsCustomerContractSummaryRespVO> getContractSummary(CrmStatisticsCustomerReqVO reqVO) { | ||||
|         // 1. 获得用户编号数组 | ||||
|         List<Long> userIds = getUserIds(reqVO); | ||||
|         if (CollUtil.isEmpty(userIds)) { | ||||
|         reqVO.setUserIds(getUserIds(reqVO)); | ||||
|         if (CollUtil.isEmpty(reqVO.getUserIds())) { | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|         reqVO.setUserIds(userIds); | ||||
|  | ||||
|         // 2. 获取统计数据 | ||||
|         initParams(reqVO); | ||||
|         List<CrmStatisticsCustomerContractSummaryRespVO> respVoList = customerMapper.selectContractSummary(reqVO); | ||||
|         // 2. 按用户统计,获取统计数据 | ||||
|         List<CrmStatisticsCustomerContractSummaryRespVO> summaryList = customerMapper.selectContractSummary(reqVO); | ||||
|  | ||||
|         // 3. 设置 创建人、负责人、行业、来源 | ||||
|         // 3.1 获取客户所属行业 | ||||
|         Map<String, String> industryMap = convertMap(dictDataApi.getDictDataList(CRM_CUSTOMER_INDUSTRY), | ||||
|             DictDataRespDTO::getValue, DictDataRespDTO::getLabel); | ||||
|         // 3.2 获取客户来源 | ||||
|         Map<String, String> sourceMap = convertMap(dictDataApi.getDictDataList(CRM_CUSTOMER_SOURCE), | ||||
|             DictDataRespDTO::getValue, DictDataRespDTO::getLabel); | ||||
|         // 3.3 获取创建人、负责人列表 | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(respVoList, | ||||
|             vo -> Stream.of(NumberUtils.parseLong(vo.getCreatorUserId()), vo.getOwnerUserId()))); | ||||
|         // 3.4 设置 创建人、负责人、行业、来源 | ||||
|         respVoList.forEach(vo -> { | ||||
|             MapUtils.findAndThen(industryMap, vo.getIndustryId(), vo::setIndustryName); | ||||
|             MapUtils.findAndThen(sourceMap, vo.getSource(), vo::setSourceName); | ||||
|             MapUtils.findAndThen(userMap, NumberUtils.parseLong(vo.getCreatorUserId()), | ||||
|                 user -> vo.setCreatorUserName(user.getNickname())); | ||||
|             MapUtils.findAndThen(userMap, vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname())); | ||||
|         // 3. 拼接信息 | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||||
|                 convertSetByFlatMap(summaryList, vo -> Stream.of(NumberUtils.parseLong(vo.getCreator()), vo.getOwnerUserId()))); | ||||
|         summaryList.forEach(vo -> { | ||||
|             findAndThen(userMap, NumberUtils.parseLong(vo.getCreator()), user -> vo.setCreatorUserName(user.getNickname())); | ||||
|             findAndThen(userMap, vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname())); | ||||
|         }); | ||||
|  | ||||
|         return respVoList; | ||||
|         return summaryList; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmStatisticsCustomerDealCycleByDateRespVO> getCustomerDealCycleByDate(CrmStatisticsCustomerReqVO reqVO) { | ||||
|         // 1. 获得用户编号数组 | ||||
|         List<Long> userIds = getUserIds(reqVO); | ||||
|         if (CollUtil.isEmpty(userIds)) { | ||||
|         reqVO.setUserIds(getUserIds(reqVO)); | ||||
|         if (CollUtil.isEmpty(reqVO.getUserIds())) { | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|         reqVO.setUserIds(userIds); | ||||
|  | ||||
|         // 2. 获取分项统计数据 | ||||
|         initParams(reqVO); | ||||
|         List<CrmStatisticsCustomerDealCycleByDateRespVO> customerDealCycle = customerMapper.selectCustomerDealCycleGroupByDate(reqVO); | ||||
|         // 2. 按天统计,获取分项统计数据 | ||||
|         List<CrmStatisticsCustomerDealCycleByDateRespVO> customerDealCycleList = customerMapper.selectCustomerDealCycleGroupByDate(reqVO); | ||||
|  | ||||
|         // 3. 合并统计数据 | ||||
|         List<String> times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]); | ||||
|         Map<String, Double> customerDealCycleMap = convertMap(customerDealCycle, | ||||
|             CrmStatisticsCustomerDealCycleByDateRespVO::getTime, | ||||
|             CrmStatisticsCustomerDealCycleByDateRespVO::getCustomerDealCycle); | ||||
|         List<CrmStatisticsCustomerDealCycleByDateRespVO> respVoList = convertList(times, time -> | ||||
|             new CrmStatisticsCustomerDealCycleByDateRespVO().setTime(time) | ||||
|                 .setCustomerDealCycle(customerDealCycleMap.getOrDefault(time, 0D)) | ||||
|         ); | ||||
|  | ||||
|         return respVoList; | ||||
|         // 3. 按照日期间隔,合并统计数据 | ||||
|         List<LocalDateTime[]> timeRanges = LocalDateTimeUtils.getDateRangeList(reqVO.getTimes()[0], reqVO.getTimes()[1], reqVO.getInterval()); | ||||
|         return convertList(timeRanges, times -> { | ||||
|             Double customerDealCycle = customerDealCycleList.stream() | ||||
|                     .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], vo.getTime())) | ||||
|                     .mapToDouble(CrmStatisticsCustomerDealCycleByDateRespVO::getCustomerDealCycle).sum(); | ||||
|             return new CrmStatisticsCustomerDealCycleByDateRespVO() | ||||
|                     .setTime(LocalDateTimeUtils.formatDateRange(times[0], times[1], reqVO.getInterval())) | ||||
|                     .setCustomerDealCycle(customerDealCycle); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmStatisticsCustomerDealCycleByUserRespVO> getCustomerDealCycleByUser(CrmStatisticsCustomerReqVO reqVO) { | ||||
|         // 1. 获得用户编号数组 | ||||
|         List<Long> userIds = getUserIds(reqVO); | ||||
|         if (CollUtil.isEmpty(userIds)) { | ||||
|         reqVO.setUserIds(getUserIds(reqVO)); | ||||
|         if (CollUtil.isEmpty(reqVO.getUserIds())) { | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|         reqVO.setUserIds(userIds); | ||||
|  | ||||
|         // 2. 获取分项统计数据 | ||||
|         initParams(reqVO); | ||||
|         List<CrmStatisticsCustomerDealCycleByUserRespVO> customerDealCycle = customerMapper.selectCustomerDealCycleGroupByUser(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> customerDealCount = customerMapper.selectCustomerDealCountGroupByUser(reqVO); | ||||
|         // 2. 按用户统计,获取分项统计数据 | ||||
|         List<CrmStatisticsCustomerDealCycleByUserRespVO> customerDealCycleList = customerMapper.selectCustomerDealCycleGroupByUser(reqVO); | ||||
|         List<CrmStatisticsCustomerSummaryByUserRespVO> customerDealCountList = customerMapper.selectCustomerDealCountGroupByUser(reqVO); | ||||
|  | ||||
|         // 3. 合并统计数据 | ||||
|         Map<Long, Double> customerDealCycleMap = convertMap(customerDealCycle, | ||||
|             CrmStatisticsCustomerDealCycleByUserRespVO::getOwnerUserId, | ||||
|             CrmStatisticsCustomerDealCycleByUserRespVO::getCustomerDealCycle); | ||||
|         Map<Long, Integer> customerDealCountMap = convertMap(customerDealCount, | ||||
|             CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId, | ||||
|             CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount); | ||||
|         List<CrmStatisticsCustomerDealCycleByUserRespVO> respVoList = convertList(userIds, userId -> { | ||||
|             CrmStatisticsCustomerDealCycleByUserRespVO vo = new CrmStatisticsCustomerDealCycleByUserRespVO() | ||||
|                 .setCustomerDealCycle(customerDealCycleMap.getOrDefault(userId, 0.0)) | ||||
|                 .setCustomerDealCount(customerDealCountMap.getOrDefault(userId, 0)); | ||||
|             // ownerUserId 为基类属性 | ||||
|             vo.setOwnerUserId(userId); | ||||
|             return vo; | ||||
|         // 3.1 按照用户,合并统计数据 | ||||
|         List<CrmStatisticsCustomerDealCycleByUserRespVO> summaryList = convertList(reqVO.getUserIds(), userId -> { | ||||
|             Double customerDealCycle = customerDealCycleList.stream().filter(vo -> userId.equals(vo.getOwnerUserId())) | ||||
|                     .mapToDouble(CrmStatisticsCustomerDealCycleByUserRespVO::getCustomerDealCycle).sum(); | ||||
|             Integer customerDealCount = customerDealCountList.stream().filter(vo -> userId.equals(vo.getOwnerUserId())) | ||||
|                     .mapToInt(CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount).sum(); | ||||
|             return (CrmStatisticsCustomerDealCycleByUserRespVO) new CrmStatisticsCustomerDealCycleByUserRespVO() | ||||
|                     .setCustomerDealCycle(customerDealCycle).setCustomerDealCount(customerDealCount).setOwnerUserId(userId); | ||||
|         }); | ||||
|  | ||||
|         // 4. 拼接用户信息 | ||||
|         appendUserInfo(respVoList); | ||||
|  | ||||
|         return respVoList; | ||||
|         // 3.2 拼接用户信息 | ||||
|         appendUserInfo(summaryList); | ||||
|         return summaryList; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 拼接用户信息(昵称) | ||||
|      * | ||||
|      * @param respVoList 统计数据 | ||||
|      * @param voList 统计数据 | ||||
|      */ | ||||
|     private <T extends CrmStatisticsCustomerByUserBaseRespVO> void appendUserInfo(List<T> respVoList) { | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(respVoList, | ||||
|             CrmStatisticsCustomerByUserBaseRespVO::getOwnerUserId)); | ||||
|         respVoList.forEach(vo -> MapUtils.findAndThen(userMap, | ||||
|             vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname()))); | ||||
|     private <T extends CrmStatisticsCustomerByUserBaseRespVO> void appendUserInfo(List<T> voList) { | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||||
|                 convertSet(voList, CrmStatisticsCustomerByUserBaseRespVO::getOwnerUserId)); | ||||
|         voList.forEach(vo -> findAndThen(userMap, vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname()))); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -347,113 +260,10 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe | ||||
|         } | ||||
|         // 情况二:选中某个部门 | ||||
|         // 2.1 获得部门列表 | ||||
|         Long deptId = reqVO.getDeptId(); | ||||
|         List<Long> deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId); | ||||
|         deptIds.add(deptId); | ||||
|         List<Long> deptIds = convertList(deptApi.getChildDeptList(reqVO.getDeptId()), DeptRespDTO::getId); | ||||
|         deptIds.add(reqVO.getDeptId()); | ||||
|         // 2.2 获得用户编号 | ||||
|         return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * 判断是否按照 月粒度 统计 | ||||
|      * | ||||
|      * @param startTime 开始时间 | ||||
|      * @param endTime   结束时间 | ||||
|      * @return 是, 按月粒度, 否则按天粒度统计。 | ||||
|      */ | ||||
|     private boolean queryByMonth(LocalDateTime startTime, LocalDateTime endTime) { | ||||
|         return LocalDateTimeUtil.between(startTime, endTime).toDays() > 31; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 生成时间序列 | ||||
|      * | ||||
|      * @param startTime 开始时间 | ||||
|      * @param endTime   结束时间 | ||||
|      * @return 时间序列 | ||||
|      */ | ||||
|     private List<String> generateTimeSeries(LocalDateTime startTime, LocalDateTime endTime) { | ||||
|         boolean byMonth = queryByMonth(startTime, endTime); | ||||
|         List<String> times = CollUtil.newArrayList(); | ||||
|         while (!startTime.isAfter(endTime)) { | ||||
|             times.add(LocalDateTimeUtil.format(startTime, byMonth ? TIME_FORMAT_BY_MONTH : TIME_FORMAT_BY_DAY)); | ||||
|             if (byMonth) | ||||
|                 startTime = startTime.plusMonths(1); | ||||
|             else | ||||
|                 startTime = startTime.plusDays(1); | ||||
|         } | ||||
|  | ||||
|         return times; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取 SQL 查询 GROUP BY 的时间格式 | ||||
|      * | ||||
|      * @param startTime 开始时间 | ||||
|      * @param endTime   结束时间 | ||||
|      * @return SQL 查询 GROUP BY 的时间格式 | ||||
|      */ | ||||
|     private String getSqlDateFormat(LocalDateTime startTime, LocalDateTime endTime) { | ||||
|         return queryByMonth(startTime, endTime) ? SQL_DATE_FORMAT_BY_MONTH : SQL_DATE_FORMAT_BY_DAY; | ||||
|     } | ||||
|  | ||||
|     private void initParams(CrmStatisticsCustomerReqVO reqVO) { | ||||
|         final Integer intervalType = reqVO.getIntervalType(); | ||||
|  | ||||
|         // 1. 自定义时间间隔,必须输入起始日期-结束日期 | ||||
|         if (DateIntervalEnum.CUSTOMER.getType().equals(intervalType)) { | ||||
|             if (ObjUtil.isEmpty(reqVO.getTimes()) || reqVO.getTimes().length != 2) { | ||||
|                 throw exception(STATISTICS_CUSTOMER_TIMES_NOT_SET); | ||||
|             } | ||||
|             // 设置 mapper sqlDateFormat 参数 | ||||
|             reqVO.setSqlDateFormat(getSqlDateFormat(reqVO.getTimes()[0], reqVO.getTimes()[1])); | ||||
|             // 自定义日期无需计算日期参数 | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // 2. 根据时间区间类型计算时间段区间日期 | ||||
|         DateTime beginDate = null; | ||||
|         DateTime endDate = null; | ||||
|         if (DateIntervalEnum.TODAY.getType().equals(intervalType)) { | ||||
|             beginDate = DateUtil.beginOfDay(DateUtil.date()); | ||||
|             endDate = DateUtil.endOfDay(DateUtil.date()); | ||||
|         } else if (DateIntervalEnum.YESTERDAY.getType().equals(intervalType)) { | ||||
|             beginDate = DateUtil.offsetDay(DateUtil.date(), -1); | ||||
|             endDate = DateUtil.offsetDay(DateUtil.date(), -1); | ||||
|         } else if (DateIntervalEnum.THIS_WEEK.getType().equals(intervalType)) { | ||||
|             beginDate = DateUtil.beginOfWeek(DateUtil.date()); | ||||
|             endDate = DateUtil.endOfWeek(DateUtil.date()); | ||||
|         } else if (DateIntervalEnum.LAST_WEEK.getType().equals(intervalType)) { | ||||
|             beginDate = DateUtil.beginOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)); | ||||
|             endDate = DateUtil.endOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)); | ||||
|         } else if (DateIntervalEnum.THIS_MONTH.getType().equals(intervalType)) { | ||||
|             beginDate = DateUtil.beginOfMonth(DateUtil.date()); | ||||
|             endDate = DateUtil.endOfMonth(DateUtil.date()); | ||||
|         } else if (DateIntervalEnum.LAST_MONTH.getType().equals(intervalType)) { | ||||
|             beginDate = DateUtil.beginOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1)); | ||||
|             endDate = DateUtil.endOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1)); | ||||
|         } else if (DateIntervalEnum.THIS_QUARTER.getType().equals(intervalType)) { | ||||
|             beginDate = DateUtil.beginOfQuarter(DateUtil.date()); | ||||
|             endDate = DateUtil.endOfQuarter(DateUtil.date()); | ||||
|         } else if (DateIntervalEnum.LAST_QUARTER.getType().equals(intervalType)) { | ||||
|             beginDate = DateUtil.beginOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3)); | ||||
|             endDate = DateUtil.endOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3)); | ||||
|         } else if (DateIntervalEnum.THIS_YEAR.getType().equals(intervalType)) { | ||||
|             beginDate = DateUtil.beginOfYear(DateUtil.date()); | ||||
|             endDate = DateUtil.endOfYear(DateUtil.date()); | ||||
|         } else if (DateIntervalEnum.LAST_YEAR.getType().equals(intervalType)) { | ||||
|             beginDate = DateUtil.beginOfYear(DateUtil.offsetMonth(DateUtil.date(), -12)); | ||||
|             endDate = DateUtil.endOfYear(DateUtil.offsetMonth(DateUtil.date(), -12)); | ||||
|         } | ||||
|  | ||||
|         // 3. 计算开始、结束日期时间,并设置reqVo | ||||
|         LocalDateTime[] times = new LocalDateTime[2]; | ||||
|         times[0] = LocalDateTimeUtil.beginOfDay(LocalDateTimeUtil.of(beginDate)); | ||||
|         times[1] = LocalDateTimeUtil.endOfDay(LocalDateTimeUtil.of(endDate)); | ||||
|         // 3.1 设置 mapper 时间区间 参数 | ||||
|         reqVO.setTimes(times); | ||||
|         // 3.2 设置 mapper sqlDateFormat 参数 | ||||
|         reqVO.setSqlDateFormat(getSqlDateFormat(times[0], times[1])); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -5,31 +5,31 @@ | ||||
|     <select id="selectCustomerCreateCountGroupByDate" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByDateRespVO"> | ||||
|         SELECT | ||||
|             DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time, | ||||
|             DATE_FORMAT(create_time, '%Y-%m-%d') AS time, | ||||
|             COUNT(*) AS customerCreateCount | ||||
|           FROM crm_customer | ||||
|          WHERE deleted = 0 | ||||
|            AND owner_user_id IN | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|            AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|          GROUP BY time | ||||
|         FROM crm_customer | ||||
|         WHERE deleted = 0 | ||||
|         AND owner_user_id IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         GROUP BY time | ||||
|     </select> | ||||
|  | ||||
|     <select id="selectCustomerDealCountGroupByDate" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByDateRespVO"> | ||||
|         SELECT | ||||
|             DATE_FORMAT( order_date, #{sqlDateFormat} ) AS time, | ||||
|             DATE_FORMAT( order_date, '%Y-%m-%d' ) AS time, | ||||
|             COUNT( DISTINCT customer_id ) AS customerDealCount | ||||
|          FROM crm_contract | ||||
|         FROM crm_contract | ||||
|         WHERE deleted = 0 | ||||
|           AND audit_status = 20 | ||||
|           AND owner_user_id IN | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|           AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         AND audit_status = 20 | ||||
|         AND owner_user_id IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         GROUP BY time | ||||
|     </select> | ||||
|  | ||||
| @@ -38,13 +38,13 @@ | ||||
|         SELECT | ||||
|             owner_user_id, | ||||
|             COUNT(1) AS customer_create_count | ||||
|           FROM crm_customer | ||||
|          WHERE deleted = 0 | ||||
|            AND owner_user_id in | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|           AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         FROM crm_customer | ||||
|         WHERE deleted = 0 | ||||
|         AND owner_user_id in | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         GROUP BY owner_user_id | ||||
|     </select> | ||||
|  | ||||
| @@ -53,16 +53,16 @@ | ||||
|         SELECT | ||||
|             customer.owner_user_id, | ||||
|             COUNT( DISTINCT customer.id ) AS customer_deal_count | ||||
|           FROM crm_customer AS customer | ||||
|                 LEFT JOIN crm_contract AS contract ON contract.customer_id = customer.id | ||||
|          WHERE customer.deleted = 0 AND contract.deleted = 0 | ||||
|            AND contract.audit_status = 20 | ||||
|            AND customer.owner_user_id IN | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|            AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|          GROUP BY customer.owner_user_id | ||||
|         FROM crm_customer AS customer | ||||
|         LEFT JOIN crm_contract AS contract ON contract.customer_id = customer.id | ||||
|         WHERE customer.deleted = 0 AND contract.deleted = 0 | ||||
|         AND contract.audit_status = 20 | ||||
|         AND customer.owner_user_id IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         GROUP BY customer.owner_user_id | ||||
|     </select> | ||||
|  | ||||
|     <select id="selectContractPriceGroupByUser" | ||||
| @@ -70,15 +70,15 @@ | ||||
|         SELECT | ||||
|             owner_user_id, | ||||
|             IFNULL(SUM(total_price), 0) AS contract_price | ||||
|           FROM crm_contract | ||||
|          WHERE deleted = 0 | ||||
|            AND audit_status = 20 | ||||
|            AND owner_user_id in | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|            AND order_date BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|          GROUP BY owner_user_id | ||||
|         FROM crm_contract | ||||
|         WHERE deleted = 0 | ||||
|         AND audit_status = 20 | ||||
|         AND owner_user_id in | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND order_date BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         GROUP BY owner_user_id | ||||
|     </select> | ||||
|  | ||||
|     <select id="selectReceivablePriceGroupByUser" | ||||
| @@ -86,132 +86,132 @@ | ||||
|         SELECT | ||||
|             owner_user_id, | ||||
|             IFNULL(SUM(price), 0) AS receivable_price | ||||
|           FROM crm_receivable | ||||
|          WHERE deleted = 0 | ||||
|            AND audit_status = 20 | ||||
|            AND owner_user_id IN | ||||
|                  <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                      #{userId} | ||||
|                  </foreach> | ||||
|            AND return_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|          GROUP BY owner_user_id | ||||
|         FROM crm_receivable | ||||
|         WHERE deleted = 0 | ||||
|         AND audit_status = 20 | ||||
|         AND owner_user_id IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND return_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         GROUP BY owner_user_id | ||||
|     </select> | ||||
|  | ||||
|     <select id="selectFollowupRecordCountGroupByDate" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowupSummaryByDateRespVO"> | ||||
|     <select id="selectFollowUpRecordCountGroupByDate" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowUpSummaryByDateRespVO"> | ||||
|         SELECT | ||||
|             DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time, | ||||
|             COUNT(*) AS followup_record_count | ||||
|           FROM crm_follow_up_record | ||||
|          WHERE creator IN | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|            AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|            AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type} | ||||
|          GROUP BY time | ||||
|             DATE_FORMAT( create_time, '%Y-%m-%d' ) AS time, | ||||
|             COUNT(*) AS follow_up_record_count | ||||
|         FROM crm_follow_up_record | ||||
|         WHERE creator IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type} | ||||
|         GROUP BY time | ||||
|     </select> | ||||
|  | ||||
|     <select id="selectFollowupCustomerCountGroupByDate" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowupSummaryByDateRespVO"> | ||||
|     <select id="selectFollowUpCustomerCountGroupByDate" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowUpSummaryByDateRespVO"> | ||||
|         SELECT | ||||
|             DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time, | ||||
|             COUNT(DISTINCT biz_id) AS followup_customer_count | ||||
|           FROM crm_follow_up_record | ||||
|          WHERE creator IN | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|            AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|            AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type} | ||||
|          GROUP BY time | ||||
|             DATE_FORMAT( create_time, '%Y-%m-%d' ) AS time, | ||||
|             COUNT(DISTINCT biz_id) AS follow_up_customer_count | ||||
|         FROM crm_follow_up_record | ||||
|         WHERE creator IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type} | ||||
|         GROUP BY time | ||||
|     </select> | ||||
|  | ||||
|     <select id="selectFollowupRecordCountGroupByUser" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowupSummaryByUserRespVO"> | ||||
|     <select id="selectFollowUpRecordCountGroupByUser" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowUpSummaryByUserRespVO"> | ||||
|         SELECT | ||||
|             creator as owner_user_id, | ||||
|             COUNT(*) AS followup_record_count | ||||
|           FROM crm_follow_up_record | ||||
|          WHERE creator IN | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|            AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|            AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type} | ||||
|          GROUP BY creator | ||||
|             COUNT(*) AS follow_up_record_count | ||||
|         FROM crm_follow_up_record | ||||
|         WHERE creator IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type} | ||||
|         GROUP BY creator | ||||
|     </select> | ||||
|  | ||||
|     <select id="selectFollowupCustomerCountGroupByUser" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowupSummaryByUserRespVO"> | ||||
|     <select id="selectFollowUpCustomerCountGroupByUser" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowUpSummaryByUserRespVO"> | ||||
|         SELECT | ||||
|             creator as owner_user_id, | ||||
|             COUNT(DISTINCT biz_id) AS followup_customer_count | ||||
|           FROM crm_follow_up_record | ||||
|          WHERE creator IN | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|            AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|            AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type} | ||||
|          GROUP BY creator | ||||
|             COUNT(DISTINCT biz_id) AS follow_up_customer_count | ||||
|         FROM crm_follow_up_record | ||||
|         WHERE creator IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type} | ||||
|         GROUP BY creator | ||||
|     </select> | ||||
|  | ||||
|     <select id="selectFollowupRecordCountGroupByType" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowupSummaryByTypeRespVO"> | ||||
|     <select id="selectFollowUpRecordCountGroupByType" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsFollowUpSummaryByTypeRespVO"> | ||||
|         SELECT | ||||
|             type AS followupType, | ||||
|             COUNT(*) AS followup_record_count | ||||
|           FROM crm_follow_up_record | ||||
|          WHERE creator IN | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|            AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|            AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type} | ||||
|          GROUP BY followupType | ||||
|             type AS follow_up_type, | ||||
|             COUNT(*) AS follow_up_record_count | ||||
|         FROM crm_follow_up_record | ||||
|         WHERE creator IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         AND biz_type = ${@cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum@CRM_CUSTOMER.type} | ||||
|         GROUP BY follow_up_type | ||||
|     </select> | ||||
|  | ||||
|     <select id="selectContractSummary" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerContractSummaryRespVO"> | ||||
|         SELECT | ||||
|             customer.`name` AS customer_name, | ||||
|             contract.`name` AS contract_name, | ||||
|             customer.name AS customer_name, | ||||
|             contract.name AS contract_name, | ||||
|             contract.total_price, | ||||
|             IFNULL( receivable.price, 0 ) AS receivable_price, | ||||
|             customer.industry_id, | ||||
|             customer.source, | ||||
|             customer.owner_user_id, | ||||
|             customer.creator AS creator_user_id, | ||||
|             customer.creator, | ||||
|             customer.create_time, | ||||
|             contract.order_date | ||||
|           FROM crm_customer AS customer | ||||
|                 INNER JOIN crm_contract AS contract ON customer.id = contract.customer_id | ||||
|                 LEFT JOIN crm_receivable AS receivable ON contract.id = receivable.contract_id | ||||
|          WHERE customer.deleted = 0 AND contract.deleted = 0 AND receivable.deleted = 0 | ||||
|            AND contract.audit_status = 20 | ||||
|            AND customer.owner_user_id IN | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|            AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         FROM crm_customer AS customer | ||||
|         INNER JOIN crm_contract AS contract ON customer.id = contract.customer_id | ||||
|         LEFT JOIN crm_receivable AS receivable ON contract.id = receivable.contract_id | ||||
|         WHERE customer.deleted = 0 AND contract.deleted = 0 AND receivable.deleted = 0 | ||||
|         AND contract.audit_status = 20 | ||||
|         AND customer.owner_user_id IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|     </select> | ||||
|  | ||||
|     <select id="selectCustomerDealCycleGroupByDate" | ||||
|             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerDealCycleByDateRespVO"> | ||||
|         SELECT | ||||
|             DATE_FORMAT( contract.order_date, #{sqlDateFormat} ) AS time, | ||||
|             DATE_FORMAT( contract.order_date, '%Y-%m-%d' ) AS time, | ||||
|             IFNULL( TRUNCATE ( AVG( TIMESTAMPDIFF( DAY, customer.create_time, contract.order_date )), 1 ), 0 ) AS customer_deal_cycle | ||||
|           FROM crm_customer AS customer | ||||
|                 LEFT JOIN crm_contract AS contract ON contract.customer_id = customer.id | ||||
|          WHERE customer.deleted = 0 AND contract.deleted = 0 | ||||
|            AND contract.audit_status = 20 | ||||
|            AND customer.owner_user_id IN | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|            AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|          GROUP BY time | ||||
|         FROM crm_customer AS customer | ||||
|         LEFT JOIN crm_contract AS contract ON contract.customer_id = customer.id | ||||
|         WHERE customer.deleted = 0 AND contract.deleted = 0 | ||||
|         AND contract.audit_status = 20 | ||||
|         AND customer.owner_user_id IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         GROUP BY time | ||||
|     </select> | ||||
|  | ||||
|     <select id="selectCustomerDealCycleGroupByUser" | ||||
| @@ -219,16 +219,16 @@ | ||||
|         SELECT | ||||
|             customer.owner_user_id, | ||||
|             IFNULL( TRUNCATE ( AVG( TIMESTAMPDIFF( DAY, customer.create_time, contract.order_date )), 1 ), 0 ) AS customer_deal_cycle | ||||
|           FROM crm_customer AS customer | ||||
|                 LEFT JOIN crm_contract AS contract ON contract.customer_id = customer.id | ||||
|          WHERE customer.deleted = 0 AND contract.deleted = 0 | ||||
|            AND contract.audit_status = 20 | ||||
|            AND customer.owner_user_id IN | ||||
|                 <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                     #{userId} | ||||
|                 </foreach> | ||||
|            AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|          GROUP BY customer.owner_user_id | ||||
|         FROM crm_customer AS customer | ||||
|         LEFT JOIN crm_contract AS contract ON contract.customer_id = customer.id | ||||
|         WHERE customer.deleted = 0 AND contract.deleted = 0 | ||||
|         AND contract.audit_status = 20 | ||||
|         AND customer.owner_user_id IN | ||||
|             <foreach collection="userIds" item="userId" open="(" close=")" separator=","> | ||||
|                 #{userId} | ||||
|             </foreach> | ||||
|         AND contract.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} | ||||
|         GROUP BY customer.owner_user_id | ||||
|     </select> | ||||
|  | ||||
| </mapper> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV