From 90f82b157de162ecf07cb904ce2fe632d6bdb6ea Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 30 Mar 2024 09:22:54 +0800 Subject: [PATCH] =?UTF-8?q?CRM=EF=BC=9A=E4=BC=98=E5=8C=96=E3=80=90?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=BB=9F=E8=AE=A1=E3=80=91=E7=9A=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/enums/DateIntervalEnum.java | 28 +- .../framework/common/util/date/DateUtils.java | 39 -- .../common/util/date/LocalDateTimeUtils.java | 144 +++++- .../module/crm/enums/ErrorCodeConstants.java | 1 - .../CrmStatisticsCustomerController.http | 2 +- .../CrmStatisticsCustomerController.java | 18 +- ...CrmStatisticsCustomerByUserBaseRespVO.java | 2 - ...atisticsCustomerContractSummaryRespVO.java | 31 +- ...atisticsCustomerDealCycleByDateRespVO.java | 2 +- ...atisticsCustomerDealCycleByUserRespVO.java | 4 +- .../customer/CrmStatisticsCustomerReqVO.java | 7 +- ...StatisticsCustomerSummaryByDateRespVO.java | 4 +- ...StatisticsCustomerSummaryByUserRespVO.java | 8 +- ...tatisticsFollowUpSummaryByDateRespVO.java} | 6 +- ...tatisticsFollowUpSummaryByTypeRespVO.java} | 6 +- ...tatisticsFollowUpSummaryByUserRespVO.java} | 6 +- .../vo/rank/CrmStatisticsRankRespVO.java | 1 + .../CrmStatisticsCustomerMapper.java | 24 +- .../CrmStatisticsCustomerService.java | 8 +- .../CrmStatisticsCustomerServiceImpl.java | 454 +++++------------- .../CrmStatisticsCustomerMapper.xml | 288 +++++------ 21 files changed, 483 insertions(+), 600 deletions(-) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/{CrmStatisticsFollowupSummaryByDateRespVO.java => CrmStatisticsFollowUpSummaryByDateRespVO.java} (79%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/{CrmStatisticsFollowupSummaryByTypeRespVO.java => CrmStatisticsFollowUpSummaryByTypeRespVO.java} (76%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/{CrmStatisticsFollowupSummaryByUserRespVO.java => CrmStatisticsFollowUpSummaryByUserRespVO.java} (75%) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/DateIntervalEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/DateIntervalEnum.java index 9a614ddc9..498b67124 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/DateIntervalEnum.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/DateIntervalEnum.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.common.enums; +import cn.hutool.core.util.ArrayUtil; import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; import lombok.Getter; @@ -7,7 +8,7 @@ import lombok.Getter; import java.util.Arrays; /** - * 时间间隔类型枚举 + * 时间间隔的枚举 * * @author dhb52 */ @@ -15,26 +16,19 @@ import java.util.Arrays; @AllArgsConstructor public enum DateIntervalEnum implements IntArrayValuable { - TODAY(1, "今天"), - YESTERDAY(2, "昨天"), - THIS_WEEK(3, "本周"), - LAST_WEEK(4, "上周"), - THIS_MONTH(5, "本月"), - LAST_MONTH(6, "上月"), - THIS_QUARTER(7, "本季度"), - LAST_QUARTER(8, "上季度"), - THIS_YEAR(9, "本年"), - LAST_YEAR(10, "去年"), - CUSTOMER(11, "自定义"), + DAY(1, "天"), + WEEK(2, "周"), + MONTH(3, "月"), + QUARTER(4, "季度"), + YEAR(5, "年") ; - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DateIntervalEnum::getType).toArray(); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DateIntervalEnum::getInterval).toArray(); /** * 类型 */ - private final Integer type; - + private final Integer interval; /** * 名称 */ @@ -45,4 +39,8 @@ public enum DateIntervalEnum implements IntArrayValuable { return ARRAYS; } + public static DateIntervalEnum valueOf(Integer interval) { + return ArrayUtil.firstMatch(item -> item.getInterval().equals(interval), DateIntervalEnum.values()); + } + } \ No newline at end of file diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java index 60b3f1e1e..b51a838c6 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java @@ -65,19 +65,11 @@ public class DateUtils { return new Date(System.currentTimeMillis() + duration.toMillis()); } - public static boolean isExpired(Date time) { - return System.currentTimeMillis() > time.getTime(); - } - public static boolean isExpired(LocalDateTime time) { LocalDateTime now = LocalDateTime.now(); return now.isAfter(time); } - public static long diff(Date endTime, Date startTime) { - return endTime.getTime() - startTime.getTime(); - } - /** * 创建指定时间 * @@ -134,37 +126,6 @@ public class DateUtils { return a.isAfter(b) ? a : b; } - /** - * 计算当期时间相差的日期 - * - * @param field 日历字段.
eg:Calendar.MONTH,Calendar.DAY_OF_MONTH,
Calendar.HOUR_OF_DAY等. - * @param amount 相差的数值 - * @return 计算后的日志 - */ - public static Date addDate(int field, int amount) { - return addDate(null, field, amount); - } - - /** - * 计算当期时间相差的日期 - * - * @param date 设置时间 - * @param field 日历字段 例如说,{@link Calendar#DAY_OF_MONTH} 等 - * @param amount 相差的数值 - * @return 计算后的日志 - */ - public static Date addDate(Date date, int field, int amount) { - if (amount == 0) { - return date; - } - Calendar c = Calendar.getInstance(); - if (date != null) { - c.setTime(date); - } - c.add(field, amount); - return c.getTime(); - } - /** * 是否今天 * diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java index 87c20798e..cf978d81a 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java @@ -1,13 +1,18 @@ package cn.iocoder.yudao.framework.common.util.date; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum; -import java.time.Duration; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; +import java.time.*; +import java.time.format.DateTimeParseException; import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalAdjusters; +import java.util.ArrayList; +import java.util.List; /** * 时间工具类,用于 {@link java.time.LocalDateTime} @@ -21,6 +26,22 @@ public class LocalDateTimeUtils { */ public static LocalDateTime EMPTY = buildTime(1970, 1, 1); + /** + * 解析时间 + * + * 相比 {@link LocalDateTimeUtil#parse(CharSequence)} 方法来说,会尽量去解析,直到成功 + * + * @param time 时间 + * @return 时间字符串 + */ + public static LocalDateTime parse(String time) { + try { + return LocalDateTimeUtil.parse(time, DatePattern.NORM_DATE_PATTERN); + } catch (DateTimeParseException e) { + return LocalDateTimeUtil.parse(time); + } + } + public static LocalDateTime addTime(Duration duration) { return LocalDateTime.now().plus(duration); } @@ -54,6 +75,21 @@ public class LocalDateTimeUtils { return new LocalDateTime[]{buildTime(year1, mouth1, day1), buildTime(year2, mouth2, day2)}; } + /** + * 判指定断时间,是否在该时间范围内 + * + * @param startTime 开始时间 + * @param endTime 结束时间 + * @param time 指定时间 + * @return 是否 + */ + public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime, String time) { + if (startTime == null || endTime == null || time == null) { + return false; + } + return LocalDateTimeUtil.isIn(parse(time), startTime, endTime); + } + /** * 判断当前时间是否在该时间范围内 * @@ -122,6 +158,16 @@ public class LocalDateTimeUtils { return date.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX); } + /** + * 获得指定日期所在季度 + * + * @param date 日期 + * @return 所在季度 + */ + public static int getQuarterOfYear(LocalDateTime date) { + return (date.getMonthValue() - 1) / 3 + 1; + } + /** * 获取指定日期到现在过了几天,如果指定日期在当前日期之后,获取结果为负 * @@ -168,4 +214,94 @@ public class LocalDateTimeUtils { return LocalDateTime.now().with(TemporalAdjusters.firstDayOfYear()).with(LocalTime.MIN); } + public static List getDateRangeList(LocalDateTime startTime, + LocalDateTime endTime, + Integer interval) { + // 1.1 找到枚举 + DateIntervalEnum intervalEnum = DateIntervalEnum.valueOf(interval); + Assert.notNull(intervalEnum, "interval({}} 找不到对应的枚举", interval); + // 1.2 将时间对齐 + startTime = LocalDateTimeUtil.beginOfDay(startTime); + endTime = LocalDateTimeUtil.endOfDay(endTime); + + // 2. 循环,生成时间范围 + List timeRanges = new ArrayList<>(); + switch (intervalEnum) { + case DateIntervalEnum.DAY: + while (startTime.isBefore(endTime)) { + timeRanges.add(new LocalDateTime[]{startTime, startTime.plusDays(1).minusNanos(1)}); + startTime = startTime.plusDays(1); + } + break; + case DateIntervalEnum.WEEK: + while (startTime.isBefore(endTime)) { + LocalDateTime endOfWeek = startTime.with(DayOfWeek.SUNDAY).plusDays(1).minusNanos(1); + timeRanges.add(new LocalDateTime[]{startTime, endOfWeek}); + startTime = endOfWeek.plusNanos(1); + } + break; + case DateIntervalEnum.MONTH: + while (startTime.isBefore(endTime)) { + LocalDateTime endOfMonth = startTime.with(TemporalAdjusters.lastDayOfMonth()).plusDays(1).minusNanos(1); + timeRanges.add(new LocalDateTime[]{startTime, endOfMonth}); + startTime = endOfMonth.plusNanos(1); + } + break; + case DateIntervalEnum.QUARTER: + while (startTime.isBefore(endTime)) { + LocalDateTime quarterEnd = startTime.withMonth(getQuarterOfYear(startTime) * 3 + 1) + .withDayOfMonth(1).minusNanos(1); + timeRanges.add(new LocalDateTime[]{startTime, quarterEnd}); + startTime = quarterEnd.plusNanos(1); + } + break; + case DateIntervalEnum.YEAR: + while (startTime.isBefore(endTime)) { + LocalDateTime endOfYear = startTime.with(TemporalAdjusters.lastDayOfYear()).plusDays(1).minusNanos(1); + timeRanges.add(new LocalDateTime[]{startTime, endOfYear}); + startTime = endOfYear.plusNanos(1); + } + break; + default: + throw new IllegalArgumentException("Invalid interval: " + interval); + } + // 3. 兜底,最后一个时间,需要保持在 endTime 之前 + LocalDateTime[] lastTimeRange = CollUtil.getLast(timeRanges); + if (lastTimeRange != null) { + lastTimeRange[1] = endTime; + } + return timeRanges; + } + + /** + * 格式化时间范围 + * + * @param startTime 开始时间 + * @param endTime 结束时间 + * @param interval 时间间隔 + * @return 时间范围 + */ + public static String formatDateRange(LocalDateTime startTime, LocalDateTime endTime, Integer interval) { + // 1. 找到枚举 + DateIntervalEnum intervalEnum = DateIntervalEnum.valueOf(interval); + Assert.notNull(intervalEnum, "interval({}} 找不到对应的枚举", interval); + + // 2. 循环,生成时间范围 + switch (intervalEnum) { + case DateIntervalEnum.DAY: + return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATE_PATTERN); + case DateIntervalEnum.WEEK: + return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATE_PATTERN) + + StrUtil.format("(第 {} 周)", LocalDateTimeUtil.weekOfYear(startTime)); + case DateIntervalEnum.MONTH: + return LocalDateTimeUtil.format(startTime, DatePattern.NORM_MONTH_PATTERN); + case DateIntervalEnum.QUARTER: + return StrUtil.format("{}-Q{}", startTime.getYear(), getQuarterOfYear(startTime)); + case DateIntervalEnum.YEAR: + return LocalDateTimeUtil.format(startTime, DatePattern.NORM_YEAR_PATTERN); + default: + throw new IllegalArgumentException("Invalid interval: " + interval); + } + } + } diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index d49f6068c..27fb6f9ce 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -104,6 +104,5 @@ public interface ErrorCodeConstants { ErrorCode FOLLOW_UP_RECORD_DELETE_DENIED = new ErrorCode(1_020_013_001, "删除跟进记录失败,原因:没有权限"); // ========== 数据统计 1_020_014_000 ========== - ErrorCode STATISTICS_CUSTOMER_TIMES_NOT_SET = new ErrorCode(1_020_014_000, "自定义时间间隔,必须输入时间区间"); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.http index 9d96e159a..b5d35f5c4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.http +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.http @@ -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}} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.java index 4a0b2e760..7d45ae217 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.java @@ -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> getFollowupSummaryByDate(@Valid CrmStatisticsCustomerReqVO reqVO) { - return success(customerService.getFollowupSummaryByDate(reqVO)); + public CommonResult> 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> getFollowupSummaryByUser(@Valid CrmStatisticsCustomerReqVO reqVO) { - return success(customerService.getFollowupSummaryByUser(reqVO)); + public CommonResult> 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> getFollowupSummaryByType(@Valid CrmStatisticsCustomerReqVO reqVO) { - return success(customerService.getFollowupSummaryByType(reqVO)); + public CommonResult> getFollowUpSummaryByType(@Valid CrmStatisticsCustomerReqVO reqVO) { + return success(customerService.getFollowUpSummaryByType(reqVO)); } @GetMapping("/get-contract-summary") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerByUserBaseRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerByUserBaseRespVO.java index 41fa9152e..bde0029c6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerByUserBaseRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerByUserBaseRespVO.java @@ -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 = "芋道源码") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerContractSummaryRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerContractSummaryRespVO.java index ec1d27303..fa03d4609 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerContractSummaryRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerContractSummaryRespVO.java @@ -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; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByDateRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByDateRespVO.java index 44b2526e8..62facb053 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByDateRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByDateRespVO.java @@ -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; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByUserRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByUserRespVO.java index 6c8137983..1c394b8b4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByUserRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByUserRespVO.java @@ -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; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerReqVO.java index 38f15cf03..0564c2679 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerReqVO.java @@ -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 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; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByDateRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByDateRespVO.java index 866a58f1e..7ffcb20ff 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByDateRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByDateRespVO.java @@ -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; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByUserRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByUserRespVO.java index bd719a1b8..fa8372b8b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByUserRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByUserRespVO.java @@ -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; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowupSummaryByDateRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByDateRespVO.java similarity index 79% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowupSummaryByDateRespVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByDateRespVO.java index 6bd6f1d4d..9040c1eab 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowupSummaryByDateRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByDateRespVO.java @@ -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; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowupSummaryByTypeRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByTypeRespVO.java similarity index 76% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowupSummaryByTypeRespVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByTypeRespVO.java index c722305a5..d39f1cc0d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowupSummaryByTypeRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByTypeRespVO.java @@ -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; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowupSummaryByUserRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByUserRespVO.java similarity index 75% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowupSummaryByUserRespVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByUserRespVO.java index 5cd610c36..065135626 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowupSummaryByUserRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByUserRespVO.java @@ -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; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/rank/CrmStatisticsRankRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/rank/CrmStatisticsRankRespVO.java index 101cd8bcc..261aa893e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/rank/CrmStatisticsRankRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/rank/CrmStatisticsRankRespVO.java @@ -17,6 +17,7 @@ public class CrmStatisticsRankRespVO { @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private String deptName; + // TODO @芋艿:需要改下,金额是 bigdecimal /** * 数量是个特别“抽象”的概念,在不同排行下,代表不同含义 *

diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsCustomerMapper.java index 7c8ed7e93..6b535d4c8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsCustomerMapper.java @@ -13,32 +13,32 @@ import java.util.List; @Mapper public interface CrmStatisticsCustomerMapper { - List selectCustomerCreateCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); // 已经 review + List selectCustomerCreateCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); - List selectCustomerDealCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); // 已经 review + List selectCustomerDealCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); - List selectCustomerCreateCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); // 已经 review + List selectCustomerCreateCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); - List selectCustomerDealCountGroupByUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review + List selectCustomerDealCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); - List selectContractPriceGroupByUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review + List selectContractPriceGroupByUser(CrmStatisticsCustomerReqVO reqVO); - List selectReceivablePriceGroupByUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review + List selectReceivablePriceGroupByUser(CrmStatisticsCustomerReqVO reqVO); - List selectFollowupRecordCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); + List selectFollowUpRecordCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); - List selectFollowupCustomerCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); + List selectFollowUpCustomerCountGroupByDate(CrmStatisticsCustomerReqVO reqVO); - List selectFollowupRecordCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); + List selectFollowUpRecordCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); - List selectFollowupCustomerCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); + List selectFollowUpCustomerCountGroupByUser(CrmStatisticsCustomerReqVO reqVO); List selectContractSummary(CrmStatisticsCustomerReqVO reqVO); - List selectFollowupRecordCountGroupByType(CrmStatisticsCustomerReqVO reqVO); + List selectFollowUpRecordCountGroupByType(CrmStatisticsCustomerReqVO reqVO); List selectCustomerDealCycleGroupByDate(CrmStatisticsCustomerReqVO reqVO); - List selectCustomerDealCycleGroupByUser(CrmStatisticsCustomerReqVO reqVO); + List selectCustomerDealCycleGroupByUser(CrmStatisticsCustomerReqVO reqVO); // TODO } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerService.java index 546124701..06873e4a1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerService.java @@ -27,14 +27,13 @@ public interface CrmStatisticsCustomerService { */ List getCustomerSummaryByUser(CrmStatisticsCustomerReqVO reqVO); - /** * 跟进次数分析(按日期) * * @param reqVO 请求参数 * @return 统计数据 */ - List getFollowupSummaryByDate(CrmStatisticsCustomerReqVO reqVO); + List getFollowUpSummaryByDate(CrmStatisticsCustomerReqVO reqVO); /** * 跟进次数分析(按用户) @@ -42,7 +41,7 @@ public interface CrmStatisticsCustomerService { * @param reqVO 请求参数 * @return 统计数据 */ - List getFollowupSummaryByUser(CrmStatisticsCustomerReqVO reqVO); + List getFollowUpSummaryByUser(CrmStatisticsCustomerReqVO reqVO); /** * 客户跟进次数分析(按类型) @@ -50,8 +49,7 @@ public interface CrmStatisticsCustomerService { * @param reqVO 请求参数 * @return 统计数据 */ - List getFollowupSummaryByType(CrmStatisticsCustomerReqVO reqVO); - + List getFollowUpSummaryByType(CrmStatisticsCustomerReqVO reqVO); /** * 获取合同摘要信息(客户转化率页面) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerServiceImpl.java index f951e25f5..250560ef2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerServiceImpl.java @@ -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 getCustomerSummaryByDate(CrmStatisticsCustomerReqVO reqVO) { // 1. 获得用户编号数组 - List 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 customerCreateCountVoList = customerMapper.selectCustomerCreateCountGroupByDate(reqVO); - List customerDealCountVoList = customerMapper.selectCustomerDealCountGroupByDate(reqVO); + // 2. 按天统计,获取分项统计数据 + List customerCreateCountList = customerMapper.selectCustomerCreateCountGroupByDate(reqVO); + List customerDealCountList = customerMapper.selectCustomerDealCountGroupByDate(reqVO); - // 3. 合并数据 - List times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]); - Map customerCreateCountMap = convertMap(customerCreateCountVoList, - CrmStatisticsCustomerSummaryByDateRespVO::getTime, - CrmStatisticsCustomerSummaryByDateRespVO::getCustomerCreateCount); - Map customerDealCountMap = convertMap(customerDealCountVoList, - CrmStatisticsCustomerSummaryByDateRespVO::getTime, - CrmStatisticsCustomerSummaryByDateRespVO::getCustomerDealCount); - List respVoList = convertList(times, - time -> new CrmStatisticsCustomerSummaryByDateRespVO() - .setTime(time) - .setCustomerCreateCount(customerCreateCountMap.getOrDefault(time, 0)) - .setCustomerDealCount(customerDealCountMap.getOrDefault(time, 0))); - - return respVoList; + // 3. 按照日期间隔,合并数据 + List 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 getCustomerSummaryByUser(CrmStatisticsCustomerReqVO reqVO) { // 1. 获得用户编号数组 - List 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 customerCreateCount = customerMapper.selectCustomerCreateCountGroupByUser(reqVO); - List customerDealCount = customerMapper.selectCustomerDealCountGroupByUser(reqVO); - List contractPrice = customerMapper.selectContractPriceGroupByUser(reqVO); - List receivablePrice = customerMapper.selectReceivablePriceGroupByUser(reqVO); + // 2. 按用户统计,获取分项统计数据 + List customerCreateCountList = customerMapper.selectCustomerCreateCountGroupByUser(reqVO); + List customerDealCountList = customerMapper.selectCustomerDealCountGroupByUser(reqVO); + List contractPriceList = customerMapper.selectContractPriceGroupByUser(reqVO); + List receivablePriceList = customerMapper.selectReceivablePriceGroupByUser(reqVO); - // 3. 合并统计数据 - Map customerCreateCountMap = convertMap(customerCreateCount, - CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId, - CrmStatisticsCustomerSummaryByUserRespVO::getCustomerCreateCount); - Map customerDealCountMap = convertMap(customerDealCount, - CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId, - CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount); - Map contractPriceMap = convertMap(contractPrice, - CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId, - CrmStatisticsCustomerSummaryByUserRespVO::getContractPrice); - Map receivablePriceMap = convertMap(receivablePrice, - CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId, - CrmStatisticsCustomerSummaryByUserRespVO::getReceivablePrice); - List 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 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 getFollowupSummaryByDate(CrmStatisticsCustomerReqVO reqVO) { + public List getFollowUpSummaryByDate(CrmStatisticsCustomerReqVO reqVO) { // 1. 获得用户编号数组 - List 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 followupRecordCount = customerMapper.selectFollowupRecordCountGroupByDate(reqVO); - List followupCustomerCount = customerMapper.selectFollowupCustomerCountGroupByDate(reqVO); + // 2. 按天统计,获取分项统计数据 + List followUpRecordCountList = customerMapper.selectFollowUpRecordCountGroupByDate(reqVO); + List followUpCustomerCountList = customerMapper.selectFollowUpCustomerCountGroupByDate(reqVO); - // 3. 合并统计数据 - List times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]); - Map followupRecordCountMap = convertMap(followupRecordCount, - CrmStatisticsFollowupSummaryByDateRespVO::getTime, - CrmStatisticsFollowupSummaryByDateRespVO::getFollowupRecordCount); - Map followupCustomerCountMap = convertMap(followupCustomerCount, - CrmStatisticsFollowupSummaryByDateRespVO::getTime, - CrmStatisticsFollowupSummaryByDateRespVO::getFollowupCustomerCount); - List respVoList = convertList(times, time -> - new CrmStatisticsFollowupSummaryByDateRespVO().setTime(time) - .setFollowupRecordCount(followupRecordCountMap.getOrDefault(time, 0)) - .setFollowupCustomerCount(followupCustomerCountMap.getOrDefault(time, 0)) - ); - - return respVoList; + // 3. 按照时间间隔,合并统计数据 + List 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 getFollowupSummaryByUser(CrmStatisticsCustomerReqVO reqVO) { + public List getFollowUpSummaryByUser(CrmStatisticsCustomerReqVO reqVO) { // 1. 获得用户编号数组 - List 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 followupRecordCount = customerMapper.selectFollowupRecordCountGroupByUser(reqVO); - List followupCustomerCount = customerMapper.selectFollowupCustomerCountGroupByUser(reqVO); + // 2. 按用户统计,获取分项统计数据 + List followUpRecordCountList = customerMapper.selectFollowUpRecordCountGroupByUser(reqVO); + List followUpCustomerCountList = customerMapper.selectFollowUpCustomerCountGroupByUser(reqVO); - // 3. 合并统计数据 - Map followupRecordCountMap = convertMap(followupRecordCount, - CrmStatisticsFollowupSummaryByUserRespVO::getOwnerUserId, - CrmStatisticsFollowupSummaryByUserRespVO::getFollowupRecordCount); - Map followupCustomerCountMap = convertMap(followupCustomerCount, - CrmStatisticsFollowupSummaryByUserRespVO::getOwnerUserId, - CrmStatisticsFollowupSummaryByUserRespVO::getFollowupCustomerCount); - List 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 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 getFollowupSummaryByType(CrmStatisticsCustomerReqVO reqVO) { + public List getFollowUpSummaryByType(CrmStatisticsCustomerReqVO reqVO) { // 1. 获得用户编号数组 - List 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 respVoList = customerMapper.selectFollowupRecordCountGroupByType(reqVO); - - // 3. 获取字典数据 - List followUpTypes = dictDataApi.getDictDataList(CRM_FOLLOW_UP_TYPE); - Map 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 getContractSummary(CrmStatisticsCustomerReqVO reqVO) { // 1. 获得用户编号数组 - List 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 respVoList = customerMapper.selectContractSummary(reqVO); + // 2. 按用户统计,获取统计数据 + List summaryList = customerMapper.selectContractSummary(reqVO); - // 3. 设置 创建人、负责人、行业、来源 - // 3.1 获取客户所属行业 - Map industryMap = convertMap(dictDataApi.getDictDataList(CRM_CUSTOMER_INDUSTRY), - DictDataRespDTO::getValue, DictDataRespDTO::getLabel); - // 3.2 获取客户来源 - Map sourceMap = convertMap(dictDataApi.getDictDataList(CRM_CUSTOMER_SOURCE), - DictDataRespDTO::getValue, DictDataRespDTO::getLabel); - // 3.3 获取创建人、负责人列表 - Map 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 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 getCustomerDealCycleByDate(CrmStatisticsCustomerReqVO reqVO) { // 1. 获得用户编号数组 - List 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 customerDealCycle = customerMapper.selectCustomerDealCycleGroupByDate(reqVO); + // 2. 按天统计,获取分项统计数据 + List customerDealCycleList = customerMapper.selectCustomerDealCycleGroupByDate(reqVO); - // 3. 合并统计数据 - List times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]); - Map customerDealCycleMap = convertMap(customerDealCycle, - CrmStatisticsCustomerDealCycleByDateRespVO::getTime, - CrmStatisticsCustomerDealCycleByDateRespVO::getCustomerDealCycle); - List respVoList = convertList(times, time -> - new CrmStatisticsCustomerDealCycleByDateRespVO().setTime(time) - .setCustomerDealCycle(customerDealCycleMap.getOrDefault(time, 0D)) - ); - - return respVoList; + // 3. 按照日期间隔,合并统计数据 + List 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 getCustomerDealCycleByUser(CrmStatisticsCustomerReqVO reqVO) { // 1. 获得用户编号数组 - List 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 customerDealCycle = customerMapper.selectCustomerDealCycleGroupByUser(reqVO); - List customerDealCount = customerMapper.selectCustomerDealCountGroupByUser(reqVO); + // 2. 按用户统计,获取分项统计数据 + List customerDealCycleList = customerMapper.selectCustomerDealCycleGroupByUser(reqVO); + List customerDealCountList = customerMapper.selectCustomerDealCountGroupByUser(reqVO); - // 3. 合并统计数据 - Map customerDealCycleMap = convertMap(customerDealCycle, - CrmStatisticsCustomerDealCycleByUserRespVO::getOwnerUserId, - CrmStatisticsCustomerDealCycleByUserRespVO::getCustomerDealCycle); - Map customerDealCountMap = convertMap(customerDealCount, - CrmStatisticsCustomerSummaryByUserRespVO::getOwnerUserId, - CrmStatisticsCustomerSummaryByUserRespVO::getCustomerDealCount); - List 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 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 void appendUserInfo(List respVoList) { - Map userMap = adminUserApi.getUserMap(convertSet(respVoList, - CrmStatisticsCustomerByUserBaseRespVO::getOwnerUserId)); - respVoList.forEach(vo -> MapUtils.findAndThen(userMap, - vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname()))); + private void appendUserInfo(List voList) { + Map 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 deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId); - deptIds.add(deptId); + List 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 generateTimeSeries(LocalDateTime startTime, LocalDateTime endTime) { - boolean byMonth = queryByMonth(startTime, endTime); - List 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])); - } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsCustomerMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsCustomerMapper.xml index 32a1d425e..4e1cee0ea 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsCustomerMapper.xml +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsCustomerMapper.xml @@ -5,31 +5,31 @@ @@ -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 - - #{userId} - - 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 + + #{userId} + + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime} GROUP BY owner_user_id @@ -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 - - #{userId} - - 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 + + #{userId} + + 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 - DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time, - COUNT(*) AS followup_record_count - FROM crm_follow_up_record - WHERE creator IN - - #{userId} - - 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 + + #{userId} + + 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 - DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time, - COUNT(DISTINCT biz_id) AS followup_customer_count - FROM crm_follow_up_record - WHERE creator IN - - #{userId} - - 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 + + #{userId} + + 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 creator as owner_user_id, - COUNT(*) AS followup_record_count - FROM crm_follow_up_record - WHERE creator IN - - #{userId} - - 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 + + #{userId} + + 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 creator as owner_user_id, - COUNT(DISTINCT biz_id) AS followup_customer_count - FROM crm_follow_up_record - WHERE creator IN - - #{userId} - - 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 + + #{userId} + + 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 - type AS followupType, - COUNT(*) AS followup_record_count - FROM crm_follow_up_record - WHERE creator IN - - #{userId} - - 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 + + #{userId} + + 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